파이썬의 비밀스러운 삶: 팬텀 복제

발행: (2026년 2월 6일 오후 03:28 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

Introduction

Timothy는 화면을 바라보며 얼굴이 창백해졌다. “Margaret? 방금 데이터베이스 절반을 실수로 삭제한 것 같아.”

Margaret는 즉시 의자를 끌고 와서 차분한 목소리로 말했다. “당황하지 마. 정확히 무슨 일이 있었는지 말해줘.”

Timothy는 설명했다. “사용자 리스트를 정리하는 스크립트를 테스트하고 있었어. 안전하게 테스트하고 싶어서 먼저 리스트를 복사했지. 복사본을 망쳐도 원본은 안전할 거라고 생각했어.”

그는 코드를 보여주었다:

# Timothy's Safety Plan

# The original list of critical users
users = ["Alice", "Bob", "Charlie", "Dave"]

# Create a "backup" copy to test on
test_group = users

# Timothy deletes 'Alice' from the test group
test_group.remove("Alice")

# Check the results
print(f"Test Group: {test_group}")
print(f"Original Users: {users}")

Output

Test Group: ['Bob', 'Charlie', 'Dave']
Original Users: ['Bob', 'Charlie', 'Dave']

Timothy는 몸을 움츠렸다. “봐? test_group에서 Alice를 삭제했는데 users 리스트에서도 사라졌어! 어떻게 이런 일이 가능하지? 백업을 건드렸을 뿐인데 원본도 건드렸잖아!”

The Address, Not the House

Margaret는 코드를 살펴보았다. “이건 파이썬에서 가장 흔한 오해 중 하나야. 파이썬이 메모리를 다루는 방식 때문이야.”

그녀가 물었다. “test_group = users 라고 썼을 때 네가 생각한 동작이 뭐였어?”

Timothy는 대답했다. “새 리스트가 만들어진다고 생각했어. users에 있는 모든 이름을 복사해서 test_group이라는 새로운 변수에 넣는다고 생각했지.”

“파이썬은 효율성을 위해 바로 가기를 사용해,” 라고 Margaret가 설명했다. “데이터를 복사하는 데는 시간과 메모리가 필요하니, 을 복사하는 대신 파이썬은 주소만 복사해.”

그녀는 간단한 다이어그램을 그렸다: 변수 users는 이름 리스트가 들어 있는 상자를 가리키고 있다. test_group = users 를 할당하면 두 번째 변수도 같은 주소를 갖게 되며, 두 이름은 정확히 같은 객체를 가리킨다.

“그러니까 userstest_group은 정확히 같은 객체에 대한 두 개의 다른 이름일 뿐인가요?”
“맞아요,” Margaret가 미소 지으며 말했다. “링크를 통해 문서를 공유하는 것과 같아요—그 링크를 가진 사람 모두가 변경 사항을 보게 됩니다.”

Timothy가 물었다. “그럼 어떻게 하면 실제로 복사본을 만들 수 있나요? 별도의 상자를 원해요.”

“We have to be explicit,” Margaret said. “Tell Python to take the data and build a new list.”

She showed him the .copy() method:

# Margaret's Fix: Explicit Copying

users = ["Alice", "Bob", "Charlie", "Dave"]

# .copy() creates a brand new list with the same data
test_group = users.copy()

test_group.remove("Alice")

print(f"Test Group: {test_group}")
print(f"Original Users: {users}")

Output

Test Group: ['Bob', 'Charlie', 'Dave']
Original Users: ['Alice', 'Bob', 'Charlie', 'Dave']

Timothy는 안도의 한숨을 내쉬었다. “Alice는 안전해.”

Margaret는 경고를 덧붙였다: .copy()얕은 복사를 만든다. 리스트 안에 다른 가변 객체(예: 내부 리스트)가 포함돼 있다면, 그 내부 객체들은 여전히 공유된다. 이름만 담긴 간단한 리스트라면 얕은 복사면 충분하다.

Margaret’s Cheat Sheet

  • The Trap: new_list = old_list 가 복사를 만든다고 가정하는 것.
  • The Reality: 할당(=)은 참조(별명)를 만든다, 복사가 아니다. 두 변수는 같은 객체를 가리킨다.
  • Why: 파이썬은 메모리를 절약하고 속도를 높이기 위해 이렇게 동작한다.

The Fix

  • Shallow Copy: new_list = old_list.copy() (표준 방법).
  • Slicing: new_list = old_list[:] (예전 방식이지만 여전히 흔히 사용됨).

The Check

두 변수가 같은 객체를 가리키는지 확인할 수 있다:

id(a) == id(b)   # True if a and b are the same object

Timothy는 편집기에 메모를 남겼다. “다시는 =가 ‘복사’라는 뜻이라고 가정하지 않을 거야.”

“It’s a rite of passage,” Margaret assured him. “Every Python developer learns this lesson the hard way. Better to learn it on a test script than on the production database.”

Back to Blog

관련 글

더 보기 »

파이썬의 비밀스러운 삶: 숨겨진 Return

왜 당신의 함수 결과가 None인지 — 그리고 이를 해결하는 방법. 티모시가 화면을 보며 환하게 웃었다. 그는 방금 pricing script를 깔끔하게 refactoring한 것이다,…