Python에서 중첩 리스트를 가진 딕셔너리를 복사한 뒤 리스트를 바꿨더니 원본도 바뀝니다. 얕은 복사와 깊은 복사는 무엇을 공유하며 파일 같은 외부 자원에도 적용할 수 있나요?
잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?
답변과 점검 포인트 펼치기답변 접기
구두 답변
정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.
copy.copy()는 새 바깥 객체를 만들지만 내부에서 참조하는 중첩 객체는 원본과 공유합니다. copy.deepcopy()는 복사 가능한 구성 요소를 재귀적으로 복제하고, 이미 복사한 객체를 memo에 기록해 같은 객체의 반복 참조와 순환 참조를 처리하려고 합니다. 따라서 얕은 복사는 구조의 한 단계만 분리하고 깊은 복사는 더 넓은 그래프를 분리하는 선택입니다.
참조 그래프의 분리 범위
import copy
original = {"items": [1]}
shallow = copy.copy(original)
deep = copy.deepcopy(original)
shallow["items"].append(2)
print(original["items"])
print(deep["items"])
출력은 [1, 2]와 [1]입니다. shallow["items"]와 original["items"]가 같은 리스트를 가리키지만, deep의 리스트는 별도이기 때문입니다. 반대로 최상위 값만 교체하는 shallow["items"] = []는 원본 딕셔너리의 키를 바꾸지 않으므로, 어떤 변경을 할지에 따라 공유 범위를 확인해야 합니다.
외부 자원과 불변 변환
deepcopy가 임의의 객체 그래프를 완전히 독립된 실행 자원으로 만들어 주는 것은 아닙니다. 파일·소켓·스레드 락·DB 연결 같은 외부 자원은 복제할 수 없거나 복제해도 의미가 없고, 사용자 정의 클래스는 __copy__·__deepcopy__가 규칙을 바꿀 수 있습니다. 큰 그래프를 깊게 복사하면 시간과 메모리 비용도 큽니다. 불변 자료구조나 명시적 변환 함수가 더 안전한 경계라면 그것을 선택하고, 복사 뒤 실제로 공유되면 안 되는 노드만 테스트하겠습니다.
선택 기준과 검증
deepcopy는 도메인의 소유권을 추론하지 않습니다. 별칭이 의미 있는 객체까지 모두 복사하면 관계가 바뀔 수 있고, 사용자 정의 __deepcopy__가 캐시나 락을 공유하도록 만들 수도 있습니다. 필요한 데이터만 DTO로 변환하거나 불변 구조를 공유할 수 있는지 먼저 검토하고, 순환·별칭·외부 핸들을 분리해 테스트하겠습니다.
deepcopy의 memo는 같은 원본 객체를 두 번 만났을 때 같은 복사 객체를 재사용하게 해 복사본 내부의 별칭을 보존합니다. 예를 들어 두 키가 같은 리스트를 가리켰다면 보통 복사 뒤에도 두 키는 하나의 새 리스트를 함께 가리킵니다. 항목마다 deepcopy를 따로 호출하면 memo가 공유되지 않아 관계가 달라질 수 있으므로 한 그래프를 한 번에 복사하는 것과 독립 복사의 차이를 검증해야 합니다.
불변 원시값이나 함수처럼 복사해도 같은 객체를 돌려주는 유형이 있으므로 모든 노드가 새로운 주소여야 한다고 테스트하면 잘못된 기준이 됩니다. 복사 중 다른 스레드가 원본을 변경해도 자동으로 일관된 스냅샷이 만들어지지 않으므로 잠금·불변 입력·버전 경계가 필요합니다. 사용자 정의 __deepcopy__는 재귀를 시작하기 전에 memo에 자기 복사본을 등록하는 등의 계약을 지켜야 순환에서 무한 재귀를 피할 수 있습니다.
득점 포인트
이해가 드러나는 지점을 확인해 보세요.
- 바깥 객체와 내부 참조 공유를 예제로 증명한다.
- deepcopy memo·사용자 hook·순환의 범위를 설명한다.
- 외부 자원 복사 불가와 불변 변환을 선택 기준으로 둔다.
감점 포인트
놓치기 쉬운 조건과 오해를 짚어 보세요.
- copy.copy가 중첩 객체까지 재귀 복사한다고 말한다.
- deepcopy가 파일·소켓·락·DB 연결을 독립 실행 자원으로 만든다고 설명한다.
- 깊은 복사 뒤 모든 내부 노드가 반드시 새 객체라고 가정한다.
더 파고들 거리
하나 더 질문하며 이해의 범위를 넓혀 보세요.
- deepcopy는 순환과 같은 객체를 가리키는 여러 참조를 어떻게 처리하나요? memo가 없다면 어떤 문제가 생기나요?
- 사용자 정의
__deepcopy__에서 공유할 객체를 어떻게 명시할까요? - 데이터 클래스·불변 객체·직렬화 복사의 비용과 의미를 비교해 보세요.
득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.
원리부터 공부하고 싶다면
답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.