studyLAB

python - 얕은 복사, 깊은 복사 본문

codeLAB

python - 얕은 복사, 깊은 복사

studyLAB 2026. 1. 18. 12:51

python에서 코드를 작성하거나, 다른 개발자 분들의 코드를 보다 보면 .copy(), .deepcopy() 메서드를 자주 보게 됩니다. 

copy는 말 그대로 복사를 한다는 의미지만 왜 두 copy를 구분하였을까요?

 

그 이유는 파이썬이 객체(object)를 다루는 방식 때문입니다. 겉으로 보기엔 똑같은 복사처럼 보이지만, 메모리 구조에서는 어떤 복사를 활용하느냐에 따라 결과가 달라집니다.

이 차이를 이해하지 못하면, 원본 데이터를 지키려고 복사본을 만들었는데 복사본 수정 시 원본도 같이 망가지는 문제가 발생하며 복구하는데 많은 시간이 소요될 지도 모릅니다.

 

출처 : (The Python Memory Model: Introduction) https://www.cs.toronto.edu/~david/course-notes/csc110-111/06-memory-model/04-python-memory-model-1.html

 

상단 이미지와 같이 메모리는 id라는 주소가 할당되어 있습니다. 각 id별로 고유한 값을 지니게 되고, 해당 id 주소를 가진 메모리를 참조하기 위한 이름표의 역할로 변수명을 지정하게 됩니다. 여기서 얕은 복사와 깊은 복사의 차이가 발생하게 됩니다. 

 

이 차이를 눈으로 직접 확인하는 가장 확실한 방법은 파이썬 내장 함수인 id()를 사용해 **실제 메모리 주소(ID)**를 까보는 것입니다.

 

codeLAB 1. 얕은 복사 : 겉표지만 다른 쌍둥이

얕은 복사(.copy())를 하면, 데이터를 담는 바깥 상자(컨테이너)의 ID는 달라지지만, 그 안에 들어있는 내용물들의 ID는 원본과 똑같습니다.

마치 Person이라는 서류철은 새로 샀지만, 그 안에 끼워진 속지는 원본 서류철에 있는 종이를 그대로 가리키고 있는 것과 같습니다.

 

복사 대상이 1차원 리스트일 때는 문제가 없습니다.

a = [1, 2, 3]
b = a.copy() 

b[0] = 100
print(a) # [1, 2, 3]  <- 원본 안전함!
print(b) # [100, 2, 3]

 

 

그러나 중첩 리스트의 경우 결과가 달라지게 됩니다.

# 리스트 안에 리스트가 있는 중첩 구조
a = [[1, 2], [3, 4]]
b = a.copy() # 얕은 복사

# b의 내부 리스트 값을 변경해보겠습니다.
b[0][0] = 999

print(a) # [[999, 2], [3, 4]]  <- 원본의 리스트값도 변경됨
print(b) # [[999, 2], [3, 4]]

얕은 복사는 바깥쪽 리스트 []는 새로 만들었지만, 그 안의 내부 리스트 [1, 2]는 새로 만들지 않고 원본이 보던 주소(id)를 그대로 공유했기 때문에 원본의 리스트도 바뀌게 되는것입니다.

약간의 비유를 들자면 가방은 새것을 샀지만 내용물은 이전 가방의 물건들을 그대로 옮긴것이라 볼 수 있습니다.

 

 

 

codeLAB 2. 깊은 복사 : 완전한 클론

반면 깊은 복사(.deepcopy())는 내부의 내용물까지 재귀적으로 추적하여 새로운 ID를 부여합니다. 

import copy

a = [[1, 2], [3, 4]]
b = copy.deepcopy(a) # 깊은 복사

b[0][0] = 999

print(a) # [[1, 2], [3, 4]]   <- 원본이 완벽하게 보호되며
print(b) # [[999, 2], [3, 4]] <- 사본만 변경됨

 

깊은 복사는 객체 안에 객체가 있다면, 그안의 객체, 또 그 안의 객체까지 재귀적으로 파고들어 모든것을 새롭게 생성하여 완벽한 복제를 수행합니다. 깊은 복사는 메모리 공간을 얕은 복사보다 더 많이 차지하고 속도가 느려질 수 있지만, 원본과 사본을 완벽하게 분리하고 싶은 경우 필수적으로 활용해야할 기능입니다. 

 

codeLAB 3. 요약

간단하게 요약으로 마무리 해보겠습니다.

  1. 변수 (=) : 메모리 값에 이름표만 하나 더 붙인 것. (id 완전 일치)
  2. 얕은 복사 (.copy()) : 껍데기만 새로 만들고 내용은 공유 (내부 id 일치)
  3. 깊은 복사 (.deepcopy()) : 속까지 완벽하게 복제함. (id 완전 불일치)