Tech Story

[Python] 배열 복사 (흔히 하는 실수?)

쭝허니 2025. 5. 31. 21:35

파이썬 할당과 복사의 핵심: 얕은 복사 vs 깊은 복사, 이제 헷갈리지 마세요!

파이썬 할당, 복사 얘기 좀 해볼까? 얕은 복사? 깊은 복사? 뭔 소리야?! 🤔

 

어이 친구! 오늘은 파이썬에서 엄청 중요하지만, 은근히 헷갈리는 할당과 복사에 대해서 얘기 좀 해볼까 해. 특히 얕은 복사(shallow copy)랑 깊은 복사(deep copy)는 진짜 헷갈리거든!  내가 그림도 잔뜩 넣고, 코드도 보여주면서 쉽게 설명해줄 테니까, 끝까지 따라와 봐! 😎



### 1. 할당 vs 복사: 같은 건가, 다른 건가?

 

먼저 리스트를 예로 들어볼게.  리스트 `a`를 `b`에 할당해보자.

 

```python

a = [1, 2, 3]

b = a

```

 

이렇게 하면 `a`와 `b`는 같은 리스트를 가리키게 돼.  마치 같은 방의 다른 문짝을 열어본 것과 같은 거야.  하나의 리스트가 메모리에 존재하고, `a`와 `b`는 그 주소를 참조하고 있는 거지.

 

![리스트 할당 이미지](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2Fbbc9d428-9e80-46ea-9ebf-5ba7b82fdf35%2Fimage.png)

 

이걸 확인하는 방법은 `is` 연산자를 사용하면 돼. `is`는 메모리 주소를 비교하는 거야.

 

```python

print(a is b)  # True 출력!

```

 

그래서 `b`의 요소를 바꾸면 `a`도 같이 바뀌어.

 

```python

b[1] = 5

print(a)  # [1, 5, 3] 출력

print(b)  # [1, 5, 3] 출력

```

 

![할당 그림](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2F7d0fbb04-c042-4fca-a2d0-2ca2bc8c1b0c%2Fimage.png)

 

자, 이번에는 복사를 해볼게.  `copy()` 메서드를 사용하면 돼.

 

```python

a = [1, 2, 3]

b = a.copy()

```

 

이번에는 `a`와 `b`가 서로 다른 리스트를 가리키게 돼.  서로 다른 방에 있는 같은 내용의 리스트를 가지고 있는 거야.

 

![복사 후 리스트 비교](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2Ff10f7acb-d7b4-4405-82c3-29699c183604%2Fimage.png)

 

```python

print(a is b)  # False 출력!

print(a == b)  # True 출력!  (내용은 같다는 뜻)

```

 

`b`의 요소를 바꿔도 `a`는 그대로야.

 

```python

b[1] = 5

print(a)  # [1, 2, 3] 출력

print(b)  # [1, 5, 3] 출력

```

 

![할당과 복사 비교 그림](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2F4b85933b-61ef-448c-8277-3808555be935%2Fimage.png)



### 2. 가변 객체(mutable)와 불변 객체(immutable):  핵심 차이!

 

자, 여기서 중요한 개념이 하나 나와. 바로 **가변 객체(mutable)**와 **불변 객체(immutable)**이야.  리스트처럼 생성 후 값을 바꿀 수 있는 객체가 가변 객체이고, 튜플처럼 생성 후 값을 바꿀 수 없는 객체가 불변 객체야.

 

![가변, 불변 객체 표](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2F90bad738-3206-409b-80a1-dbaf557afab2%2Fimage.png)

 

튜플을 예로 들어보면,  `copy()` 메서드를 사용할 수 없어.  에러가 나지!  왜냐하면 튜플은 변경이 불가능하니까.

 

```python

a = (1, 2, 3)

# b = a.copy()  # AttributeError: 'tuple' object has no attribute 'copy'

```

 

![튜플 할당 이미지](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2Fa8956ed2-8292-47cd-be40-436e86ffc1f4%2Fimage.png)



### 3. 얕은 복사(shallow copy): 겉만 베끼기!

 

이제 얕은 복사를 알아볼까? `copy` 모듈의 `copy()` 함수를 사용해.

 

```python

import copy

 

a = [1, 2, [3, 4]]

b = copy.copy(a)

```

 

`b`는 `a`의 얕은 복사본이야.  가장 바깥쪽 리스트만 복사하고, 안쪽 리스트는 같은 것을 참조해.

 

![얕은 복사 초기 그림](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2Ffcf0f80f-953e-4d92-bc05-909c39bce008%2Fimage.png)

 

그래서 바깥쪽 요소를 바꾸면 `a`에는 영향을 안 주지만, 안쪽 리스트를 바꾸면 `a`에도 영향을 줘.

 

```python

b[0] = 5  # a는 변경되지 않음

b[2].append(5)  # a도 변경됨!

```

 

![얕은 복사 바깥 요소 변경](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2Fae990d20-b588-4de7-92ac-7b23f0d70f89%2Fimage.png)

![얕은 복사 안쪽 요소 변경](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2Fb29011e0-abdd-4072-89fb-84d6d73eff25%2Fimage.png)



### 4. 깊은 복사(deep copy): 속까지 똑같이 만들기!

 

진짜 완벽하게 복사하고 싶다면 `copy.deepcopy()`를 사용해. 이 함수는 안쪽 리스트까지 완전히 새로운 복사본을 만들어.

 

```python

import copy

 

a = [1, 2, [3, 4]]

b = copy.deepcopy(a)

 

b[2].append(5)  # a는 변경되지 않음!

```

 

![깊은 복사 그림](https://velog.velcdn.com/images%2Fkkamyang%2Fpost%2F965f60f9-27b7-4164-8310-6174d81fd4b7%2Fimage.png)



이제 할당과 복사, 그리고 얕은 복사와 깊은 복사의 차이를 확실히 알겠지?  이 개념을 잘 이해해야 파이썬 프로그래밍에서 예상치 못한 버그를 피할 수 있어!  잘 기억해두고, 궁금한 점 있으면 언제든지 물어봐! 😉