[Python] 리스트 복사와 참조 — 대입, copy(), 슬라이싱의 차이

차곡코딩·2026년 9월 23일

Python · 기초 문법

목록 보기
2/7

리스트를 다른 변수에 대입한 뒤 수정했을 때 원본까지 바뀌는 경우가 있다. 이때 확인할 것은 변수 이름이 아니라 두 변수가 가리키는 객체다. 대입과 얕은 복사, 깊은 복사를 같은 데이터로 비교해 정리한다.

1. 대입은 새 리스트를 만들지 않는다

original = [10, 20, 30]
assigned = original

assigned.append(40)

print(original)             # [10, 20, 30, 40]
print(assigned is original) # True

assigned = original은 리스트를 복제하는 명령이 아니다. 기존 리스트에 assigned라는 이름을 연결한다. 따라서 어느 이름으로 접근하든 같은 리스트를 수정하게 된다.

여기서 is는 같은 객체인지를 검사한다. 값이 같은지를 비교하는 ==와 구분해야 한다. 내용이 같아도 서로 다른 리스트일 수 있다.

2. copy()와 전체 슬라이싱

original = [10, 20, 30]
copied = original.copy()
sliced = original[:]

copied.append(40)
sliced[0] = 99

print(original)            # [10, 20, 30]
print(copied)              # [10, 20, 30, 40]
print(sliced)              # [99, 20, 30]
print(copied is original)  # False
print(sliced is original)  # False

두 방법 모두 바깥쪽 리스트를 새로 만든다. 복사한 리스트에 원소를 추가하거나 특정 위치의 값을 교체해도 원본 리스트의 구조는 바뀌지 않는다.

이번 예제의 원소는 변경할 수 없는 정수다. sliced[0] = 99는 정수 10 자체를 수정하는 것이 아니라, 새 리스트의 첫 번째 위치가 참조할 객체를 바꾸는 연산이다.

3. 중첩 리스트에서는 내부 객체를 확인해야 한다

original = [[10, 20], [30, 40]]
copied = original.copy()

copied[0].append(99)

print(original)               # [[10, 20, 99], [30, 40]]
print(copied is original)     # False
print(copied[0] is original[0]) # True

바깥쪽 리스트는 서로 다르지만, 첫 번째 원소인 내부 리스트는 공유한다. copied[0].append(99)는 공유 중인 내부 리스트를 수정하므로 원본에서도 변경이 보인다. 전체 슬라이싱으로 복사해도 같은 점에 주의해야 한다.

이것이 얕은 복사다. ‘복사했으니 모든 값이 독립적이다’라고 판단하기보다 어느 단계까지 새 객체가 만들어졌는지 확인하는 편이 정확하다.

4. 내부 리스트까지 독립적으로 수정하려면

from copy import deepcopy

original = [[10, 20], [30, 40]]
copied = deepcopy(original)
copied[0].append(99)

print(original)                # [[10, 20], [30, 40]]
print(copied)                  # [[10, 20, 99], [30, 40]]
print(copied[0] is original[0]) # False

이 예제에서는 deepcopy()가 내부 리스트까지 복사하므로 원본을 유지할 수 있다. 다만 모든 상황에서 깊은 복사를 사용할 필요는 없다. 복사 범위가 커지면 비용도 늘어나므로, 실제로 어떤 객체를 변경할 것인지 먼저 정해야 한다.

5. 선택 기준

방법바깥 리스트중첩된 내부 리스트적합한 상황
b = a공유공유같은 대상을 여러 이름으로 참조
a.copy()새로 생성공유바깥 리스트만 독립적으로 변경
a[:]새로 생성공유리스트 전체를 얕게 복사
deepcopy(a)새로 생성이 예제에서는 별도 복사중첩 리스트까지 독립적으로 변경

원본을 보존해야 한다면 ‘복사 여부’와 ‘복사 깊이’를 나누어 확인한다. 특히 내부 리스트를 수정하는 작업에서는 바깥 객체가 다르다는 사실만으로 안전하다고 판단하면 안 된다.

본문의 네 코드 블록은 각각 독립된 예제이며, Python에서 실행해 주석의 출력값을 확인했다.

참고 문서

이전 글

profile
비전공자의 개발 성장 기록. 바이브코딩 프리랜서 경험부터 Python·SQL·AI 서비스 개발까지

0개의 댓글