본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 가변(Mutable)과 불변(Immutable) 객체 : 파이썬 성능 최적화의 숨겨진 열쇠

by Papa Martino V 2026. 2. 5.
728x90

가변(Mutable)과 불변(Immutable) 객체
가변(Mutable)과 불변(Immutable) 객체

 

파이썬을 처음 접하면 모든 데이터가 '객체(Object)'로 취급된다는 사실을 배웁니다. 하지만 숙련된 개발자로 거듭나기 위해서는 단순히 객체를 사용하는 것을 넘어, 그 객체가 가변(Mutable)인지 불변(Immutable)인지를 명확히 구분할 줄 알아야 합니다. 이 작은 차이가 프로그램의 메모리 효율성, 버그 발생 가능성, 그리고 실행 속도를 결정짓기 때문입니다. 본 포스팅에서는 파이썬의 핵심 메커니즘인 객체 불변성과 가변성을 심층 분석하고, 실무에서 발생할 수 있는 실수와 이를 방지하기 위한 최적의 설계 전략을 공유합니다.


1. 객체의 정체성: 왜 가변과 불변을 나누는가?

파이썬의 모든 객체는 생성 시 세 가지 속성을 부여받습니다: ID(메모리 주소), Type(자료형), 그리고 Value(값)입니다. 여기서 '불변성(Immutability)'이란, 객체가 생성된 후 그 내부의 '값'을 변경할 수 없음을 의미합니다. 반대로 '가변성(Mutability)'은 객체 생성 후에도 내부 상태를 자유롭게 바꿀 수 있음을 뜻합니다. 파이썬 설계자들이 이를 나눈 이유는 명확합니다. 불변 객체는 값이 변하지 않기 때문에 데이터의 무결성을 보장하며, 딕셔너리의 키(Key)나 집합(Set)의 요소로 안전하게 사용될 수 있습니다. 또한, 동일한 불변 객체를 재사용함으로써 메모리를 절약하는 '인터닝(Interning)' 기법을 적용할 수 있습니다. 반면, 가변 객체는 대규모 데이터를 다룰 때 새로운 객체를 계속 생성하지 않고 기존 데이터를 수정하여 메모리 오버헤드를 줄이는 데 유리합니다.


2. 주요 자료형의 가변/불변 비교

개발 시 혼동하기 쉬운 주요 자료형을 기준으로 가변성과 불변성을 정리하였습니다. 특히 tuple의 경우, 그 자체는 불변이지만 내부에 가변 객체(예: list)를 포함할 경우 독특한 동작을 보이므로 주의가 필요합니다.

분류 자료형 (Type) 값 수정 가능 여부 주요 특징 및 용도
Immutable (불변) int, float, bool 불가능 수정 시 새로운 객체 생성 (재할당)
str 불가능 문자열 연산 시 매번 메모리 할당 발생
tuple 불가능 해싱(Hashing)이 가능하여 dict의 키로 사용 가능
Mutable (가변) list 가능 요소 추가, 삭제, 수정이 자유로움
dict 가능 Key-Value 쌍의 동적 관리
set 가능 중복 제거 및 집합 연산에 최적화

3. 실무 예제로 보는 치명적인 실수: 기본 인자(Default Argument)

가변 객체인 list를 함수의 기본 인자로 설정할 때 발생하는 현상은 초급 개발자들이 가장 많이 겪는 '논리적 오류' 중 하나입니다. 파이썬에서 함수의 기본 인자는 함수가 정의되는 시점에 딱 한 번만 생성되기 때문입니다.

Sample Example: 가변 객체의 기본 인자 함정


# 잘못된 예: 리스트를 기본 인자로 사용
def add_item(item, list_target=[]):
    list_target.append(item)
    return list_target

print(add_item("Apple"))  # 결과: ['Apple']
print(add_item("Banana")) # 결과: ['Apple', 'Banana'] (기존 리스트가 유지됨!)

# 올바른 예: None을 활용한 지연 초기화
def add_item_fixed(item, list_target=None):
    if list_target is None:
        list_target = []
    list_target.append(item)
    return list_target

print(add_item_fixed("Apple"))  # 결과: ['Apple']
print(add_item_fixed("Banana")) # 결과: ['Banana'] (새로운 리스트 생성)

위 예시에서 볼 수 있듯이, mutable 객체는 함수 호출 간에 상태를 공유할 수 있어 의도치 않은 결과를 초래합니다. 따라서 불변의 None을 기본값으로 사용하고 함수 내부에서 가변 객체를 할당하는 패턴이 권장됩니다.


4. 성능 최적화 팁: '+' 연산자 vs join()

문자열은 불변(Immutable) 객체입니다. 따라서 반복문 내에서 str1 += str2와 같은 연산을 수행하면, 매번 새로운 문자열 객체를 생성하고 기존 내용을 복사하는 과정을 거칩니다. 데이터 양이 많을수록 성능은 기하급수적으로 저하됩니다.

Best Practice: 수많은 문자열 조각을 합쳐야 할 때는 가변 객체인 list에 담아 마지막에 "".join(list)를 호출하는 것이 메모리 관리와 속도 면에서 훨씬 유리합니다.

5. 결론 및 요약

파이썬의 가변성과 불변성을 이해하는 것은 단순히 이론적인 지식을 넘어 안전한 코드를 작성하기 위한 기초입니다. 불변 객체는 예측 가능성을 높여 버그를 줄여주고, 가변 객체는 대량의 데이터 처리 시 유연성을 제공합니다. 내가 지금 다루는 변수가 메모리 상에서 어떻게 움직이는지 인지하는 순간, 당신의 코드는 한 단계 더 진화할 것입니다.

참고 문헌 및 출처:

  • Python Software Foundation - "Data Model" (Official Documentation)
  • Fluent Python by Luciano Ramalho (O'Reilly Media)
  • Real Python - "Python's Mutable vs Immutable Types"
728x90