파이썬의 비밀스러운 삶: 마트료시카 함정

발행: (2026년 1월 9일 오전 10:30 GMT+9)
6 min read
원문: Dev.to

I’m happy to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content (excluding the source line you already provided) here? Once I have the text, I’ll translate it into Korean while preserving the original formatting, markdown, and any code blocks or URLs.

티모시의 중첩 계획

티모시는 도서관 아카이브를 정리하면서 멜로디를 흥얼거리고 있었다. 그는 리스트를 복제하고 별칭(alias) 문제를 피할 수 있게 해주는 “슬라이스” ([:]) 문법을 완전히 장악한 듯 자신감을 느꼈다.

“마가렛, 나는 도서관 섹션을 재배치하고 있어. 선반들의 마스터 맵과 이동하기 전에 백업을 만들었어. 이 얕은 복사본을 봐.”

그는 새로운 실력에 자부심을 가지고 코드를 보여주었다.

# Timothy's Nested Plan
shelf_A = ["Fiction", "Mystery"]
shelf_B = ["Biography", "History"]

# The Master Layout: a list of lists
library_layout = [shelf_A, shelf_B]

# The Backup: using the slice trick
backup_layout = library_layout[:]  # (Surely this clones everything... right?)

# Move "Mystery" to a new location in the backup
backup_layout[0].remove("Mystery")

print(f"Backup Shelf A: {backup_layout[0]}")
print(f"Master Shelf A: {library_layout[0]}")

콘솔 출력

Backup Shelf A: ['Fiction']
Master Shelf A: ['Fiction']

티모시는 충격을 받았다. “Mystery” 책이 마스터 레이아웃에서도 사라졌는데, 그는 슬라이스가 완전히 독립적인 리스트를 만든다고 생각했기 때문이다.

얕은 복사의 함정

Margaret는 슬라이스(또는 list.copy())가 새로운 외부 컨테이너를 만들지만 내부의 가변 객체에 대한 참조를 공유한다는 것을 설명했습니다.

Original List        Backup List
   [Box 1]             [Box 2]
      |                   |
      +-------+   +-------+
              |   |
              v   v
           [Inner List]
          (Shared Data!)

Timothy가 backup_layout[0]을 수정했을 때, 그는 실제로 library_layout[0]이 가리키는 동일한 내부 리스트를 수정한 것이었습니다. 이것이 전형적인 Matryoshka (중첩 인형) 함정으로, 얕은 복사는 첫 번째 레이어만 복사합니다.

깊은 복사 솔루션

완전히 독립적인 복사본을 얻기 위해—중첩된 가변 객체까지 모두—Timothy는 깊은 복사가 필요했습니다.

import copy

shelf_A = ["Fiction", "Mystery"]
shelf_B = ["Biography", "History"]
library_layout = [shelf_A, shelf_B]

# Deep copy: recursively copies everything
backup_layout = copy.deepcopy(library_layout)

backup_layout[0].remove("Mystery")

print(f"Backup Shelf A: {backup_layout[0]}")
print(f"Master Shelf A: {library_layout[0]}")

출력

Backup Shelf A: ['Fiction']
Master Shelf A: ['Fiction', 'Mystery']

copy.deepcopy()는 전체 객체 그래프를 순회하며, 마주치는 각 가변 요소를 복제하므로 백업에 대한 변경이 원본에 영향을 주지 않습니다.

성능 고려사항

  • 깊은 복사가 기본이 아닌 이유는?
    깊은 복사는 시간과 메모리 모두에서 비용이 많이 듭니다. 작은 또는 평면 구조에서는 오버헤드가 무시할 수 있지만, 크고 깊게 중첩된 구조를 반복적으로 복제하면 성능 병목이 될 수 있습니다.

  • Python의 기본 철학
    Python은 속도를 중시합니다; 얕은 복사는 비용이 적고 많은 사용 사례에 충분합니다. 중첩된 데이터에 대한 안전성이 필요할 때는 명시적으로 요청해야 합니다.


복사 가이드라인

상황권장 복사 방법
평면 리스트 (예: [1, 2, 3])얕은 복사 (list[:], list.copy(), 또는 copy.copy(x))
중첩 리스트/딕셔너리 (예: [[1, 2], [3, 4]])깊은 복사 (copy.deepcopy(x))
어떤 객체에든 일반적인 얕은 복사가 필요할 때copy.copy(x) (리스트, 딕셔너리, 사용자 정의 객체에 작동)
복잡한 구조의 완전히 독립적인 복제본이 필요할 때copy.deepcopy(x)

빠른 참고

import copy

# 얕은 복사 (첫 번째 레이어만)
shallow = original_list[:]          # or original_list.copy()
shallow_generic = copy.copy(original)  # works on any object

# 깊은 복사 (전체 재귀)
deep = copy.deepcopy(original)

Deep Copy을 사용해야 할 때

  • 중첩 가변 컨테이너 – 리스트 안의 리스트, 리스트를 포함한 딕셔너리, 다른 가변 객체를 포함하는 객체.
  • 격리 필요 – 복사본을 수정해도 원본에 절대 영향을 주어서는 안 되는 경우, 구조 내부 깊숙이까지.
  • 테스트 또는 샌드박스 – 실험을 위한 안전한 샌드박스 버전의 데이터를 생성할 때.

단순하고 평평한 데이터 구조의 경우, 얕은 복사가 가장 효율적인 선택입니다.


다음 에피소드 “The Loophole”에서는 리스트를 순회하면서 수정하면 혼란스럽고 건너뛰는 타임라인이 발생하는 이야기가 이어집니다.

Back to Blog

관련 글

더 보기 »

문제 10: 중복 제거

문제 설명 우리는 리스트에서 중복을 제거하면서 원래 요소들의 순서를 유지하는 함수를 필요로 합니다. 예시: `remove_duplicates` 1, 2, 2, 3...

파이썬의 비밀스러운 삶: 허점

리스트를 순회하면서 수정하는 함정과 이를 해결하는 방법. 티모시가 화면에 보이는 센서 데이터 리스트를 바라보고 있었다. “I told it to remove the e...”