파이썬/기초 프로그래밍

Python 객체 복사: Copy, Shallow Copy, Deep Copy

Data Jun 2025. 9. 13. 11:57

파이썬에서 리스트나 딕셔너리 같은 가변 객체(mutable object) 를 다룰 때 “복사”는 중요한 주제입니다.
단순히 변수에 할당하는 것과, copy.copy() (얕은 복사), copy.deepcopy() (깊은 복사)는 동작 방식이 전혀 다릅니다.

이번 글에서는 코드 예제와 함께 복사의 종류를 정리해 보겠습니다.

 

1. 단순 할당 (Copy) — 주소 공유

a_list = [1, 2, 3, 4]
b_list = a_list

print(id(a_list))
print(id(b_list))  # 같은 주소
  • b_list = a_list 는 새로운 리스트를 만드는 게 아닙니다.
  • 두 변수는 같은 객체(주소)를 가리키는 별명(alias) 역할만 합니다.
  • 따라서 하나를 바꾸면 다른 것도 바뀝니다.
b_list[2] = 100
print(a_list)  # [1, 2, 100, 4]
print(b_list)  # [1, 2, 100, 4]

 

2. 얕은 복사 (Shallow Copy)

import copy

c_list = [1, 2, 3, [4, 5, 6], [7, 8, 9]]
d_list = copy.copy(c_list)

print(id(c_list))
print(id(d_list))  # 서로 다른 주소
  • copy.copy() 는 1차원 요소만 새로 복사합니다.
  • 따라서 c_list 와 d_list 는 서로 다른 리스트가 되지만,
    안에 있는 리스트(중첩 객체) 는 여전히 공유합니다.
d_list[1] = 100       # d_list만 바뀜
d_list[3].append(1000)  # 내부 리스트는 공유 → c_list도 영향 받음

print(c_list)  # [1, 2, 3, [4, 5, 6, 1000], [7, 8, 9]]
print(d_list)  # [1, 100, 3, [4, 5, 6, 1000], [7, 8, 9]]

따라서 데이터 원본을 백업하고 1차원 요소만 분리하고 싶을 때 얕은 복사가 적합합니다.

 

3. 깊은 복사 (Deep Copy)

e_list = [1, 2, 3, [4, 5, 6], [7, 8, 9]]
f_list = copy.deepcopy(e_list)

print(id(e_list))
print(id(f_list))  # 완전히 다른 객체
  • copy.deepcopy() 는 중첩된 객체까지 전부 새로운 객체로 복사합니다.
  • 따라서 원본과 복사본은 완전히 독립적입니다.
f_list[3].append(1000)
f_list[4][1] = 10000

print(e_list)  # [1, 2, 3, [4, 5, 6], [7, 8, 9]]
print(f_list)  # [1, 2, 3, [4, 5, 6, 1000], [7, 10000, 9]]

 

 

4. Call by Value, Reference, 그리고 Python의 Call by Share

1️⃣ C 같은 언어: Call by Value (값만 전달) 또는 Call by Reference (주소 전달)

2️⃣ Python: Call by Sharing (공유 호출) 모델을 따릅니다.

  • 객체의 참조(reference) 가 함수로 전달되지만,
  • 그 참조 자체를 바꾸면 원본에는 영향 없음.
  • 하지만 가변 객체의 내용을 수정하면 원본에 반영됩니다.

 

정리하면

  • 단순 할당: 같은 객체를 공유 → 하나 바꾸면 다른 것도 바뀜
  • 얕은 복사 (shallow copy): 1차원만 새 객체, 중첩 객체는 공유
  • 깊은 복사 (deep copy): 중첩 객체까지 모두 새로 생성 → 완전 독립
  • Python은 Call by Sharing 방식이므로, 복사를 어떻게 하느냐에 따라 결과가 크게 달라집니다.