가변성

AI
gemma-4-31b
작성자
익명
작성일
2026.07.19
조회수
21
버전
v1

가변성 (Mutability)

가변성이란 프로그래밍에서 객체가 생성된 후 그 상태(내부 값)를 변경할 수 있는지 여부를 나타내는 특성을 의미합니다. 가변성은 프로그래밍 언어 전반의 공통적인 개념이며, 본 문서는 특히 Python 언어에서의 동작 방식을 중심으로 설명합니다.

1. 가변성과 불변성의 정의

프로그래밍에서 객체는 메모리 상의 특정 주소에 할당됩니다. 이때 객체의 값을 수정할 수 있는 성질을 가변성(Mutability), 수정할 수 없는 성질을 불변성(Immutability)이라고 합니다.

  • 가변 객체 (Mutable Object): 객체가 생성된 후에도 메모리 주소를 유지한 채 내부의 값을 변경할 수 있는 객체입니다.
  • 불변 객체 (Immutable Object): 한 번 생성되면 그 값을 변경할 수 없는 객체입니다. 값을 변경하려는 시도가 있을 경우, 기존 객체를 수정하는 것이 아니라 새로운 값을 가진 새로운 객체를 생성하여 메모리에 할당하고 참조를 변경합니다.

Python은 모든 것이 객체로 취급되는 동적 타이핑 언어로, 변수는 객체 자체가 아니라 객체가 저장된 메모리 주소를 가리키는 참조(Reference) 역할을 합니다.

2. Python의 데이터 타입별 분류

Python의 주요 내장 자료형은 가변성과 불변성에 따라 다음과 같이 분류됩니다.

자료형 분류 특징
int, float, bool 불변 (Immutable) 숫자 값 변경 시 새로운 숫자 객체 생성
str 불변 (Immutable) 문자열의 일부를 직접 수정할 수 없음
tuple 불변 (Immutable) 생성 후 요소 추가, 삭제, 수정 불가
frozenset 불변 (Immutable) set의 불변 버전으로, 딕셔너리의 키로 사용 가능
bytes 불변 (Immutable) 바이트 시퀀스의 불변 버전
list 가변 (Mutable) 요소의 추가, 삭제, 수정이 자유로움
dict 가변 (Mutable) 키-값 쌍의 추가, 수정, 삭제 가능
set 가변 (Mutable) 중복 없는 요소의 추가 및 삭제 가능
bytearray 가변 (Mutable) 바이트 시퀀스의 가변 버전

3. 가변 객체의 동작 원리와 주의점

가변 객체는 내부 값을 변경해도 객체의 고유 식별자(메모리 주소)가 변하지 않습니다. Python의 내장 함수 id()를 통해 이를 확인할 수 있으며, is 연산자를 사용하여 두 변수가 동일한 객체를 참조하고 있는지 직접 비교할 수 있습니다.

참조와 메모리 주소

a = [1, 2, 3]
print(f"초기 주소: {id(a)}")

a.append(4)
print(f"수정 후 주소: {id(a)}") # 초기 주소와 동일함

# is 연산자를 통한 동일성 확인
b = a
print(a is b) # True: 두 변수가 동일한 메모리 주소를 가리킴

얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)

가변 객체를 단순히 대입 연산자(=)로 복사하면 동일한 객체에 대한 참조만 복사되어, 한쪽을 수정하면 다른 쪽도 함께 변경되는 부작용(Side Effect)이 발생합니다.

import copy

# 1. 단순 대입 (참조 복사)
list_a = [1, [2, 3]]
list_b = list_a
list_b[0] = 100 # list_a[0]도 100으로 변경됨

# 2. 얕은 복사 (Shallow Copy)
list_c = [1, [2, 3]]
list_d = list_c.copy()
list_d[0] = 100 # list_c[0]은 유지됨 (1차 요소는 독립적)
list_d[1][0] = 999 # list_c[1][0]도 999로 변경됨 (중첩된 가변 객체는 참조됨)

# 3. 깊은 복사 (Deep Copy)
list_e = [1, [2, 3]]
list_f = copy.deepcopy(list_e)
list_f[1][0] = 999 # list_e는 전혀 영향을 받지 않음

4. 불변 객체의 동작 원리와 효율성

불변 객체는 값이 변경될 때마다 새로운 객체를 생성합니다. 이는 언뜻 비효율적으로 보이지만, Python은 이를 최적화하기 위한 여러 메커니즘을 가지고 있습니다.

동작 원리

s = "Hello"
print(f"초기 주소: {id(s)}")

s += " World"
print(f"수정 후 주소: {id(s)}") # 주소가 변경됨 (새로운 객체 생성)

최적화 메커니즘

  1. 문자열 인터닝 (String Interning): Python은 동일한 내용의 짧은 문자열이나 식별자(변수명 등)를 메모리에 하나만 생성하고 이를 공유하여 메모리 사용량을 줄이고 비교 속도를 높입니다.
  2. 정수 캐싱 (Small Integer Caching): Python은 자주 사용되는 작은 정수 범위(-5에서 256까지)의 객체를 미리 생성하여 메모리에 상주시키고 재사용합니다.
  3. 튜플의 성능 이점: 튜플은 리스트보다 메모리 할당 오버헤드가 적고 접근 속도가 빠릅니다. 또한 불변성이 보장되므로 딕셔너리의 키(Key)나 세트(Set)의 요소로 사용할 수 있습니다.

기본 튜플은 인덱스로 값에 접근해야 하므로 가독성이 떨어집니다. collections 모듈의 namedtuple을 사용하면 불변성을 유지하면서도 이름으로 필드에 접근할 수 있는 클래스 형태의 객체를 생성할 수 있습니다.

from collections import namedtuple

# 'Point'라는 이름의 불변 객체 정의
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)

print(p.x, p.y) # 이름으로 접근 가능

# 불변성 테스트
try:
    p.x = 30
except AttributeError as e:
    print(f"에러 발생: {e}")
출력 결과: 에러 발생: can't set attribute

6. 가변성으로 인한 흔한 실수와 해결책

가장 대표적인 실수는 함수의 기본 인자로 가변 객체를 사용하는 경우입니다. Python에서 기본 인자는 함수가 정의되는 시점에 한 번만 평가되어 생성됩니다.

잘못된 구현 사례

def add_item(item, target=[]): # 기본 인자로 가변 객체(list) 사용
    target.append(item)
    return target

print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] (이전 호출의 결과가 유지됨)

올바른 구현 방식 (None 활용)

기본값으로 None을 설정하고, 함수 내부에서 새로운 가변 객체를 생성하는 방식을 권장합니다.

def add_item_fixed(item, target=None):
    if target is None:
        target = [] # 호출될 때마다 새로운 리스트 생성
    target.append(item)
    return target

print(add_item_fixed(1)) # [1]
print(add_item_fixed(2)) # [2]

7. 요약 및 선택 가이드

상황에 맞는 자료형 선택은 프로그램의 안정성과 성능에 직결됩니다.

불변 객체의 주요 장점

장점 설명
데이터 무결성 생성 후 값이 변하지 않으므로 의도치 않은 변경으로 인한 버그를 원천 차단함
스레드 안전성 여러 스레드가 동시에 접근해도 값이 변하지 않아 동기화 처리가 필요 없음
해시 가능성 값이 일정하므로 해시 값을 생성할 수 있어 dict의 키나 set의 요소로 사용 가능
메모리 최적화 인터닝이나 캐싱을 통해 동일한 값을 가진 객체를 공유하여 효율적으로 관리함

자료형 선택 가이드

선택 기준 추천 자료형 이유
데이터 변경이 빈번함 list, dict, set 기존 객체를 수정하므로 매번 새로 생성하는 비용이 없음
데이터의 무결성 보장 tuple, frozenset 의도치 않은 값 변경을 방지하여 버그를 줄임
딕셔너리 키/세트 요소 str, int, tuple 반드시 해시 가능(Hashable)해야 함 (단, 튜플 내부에 가변 객체가 포함되면 해시 불가능)
구조화된 불변 데이터 namedtuple 가독성과 불변성을 동시에 확보 가능

트레이드오프 요약: * 가변 객체: 수정 성능이 우수하지만, 참조 공유로 인한 부작용(Side Effect) 위험이 큼. * 불변 객체: 데이터 안정성이 높고 멀티스레딩 환경에서 안전하지만, 값 변경 시마다 새로운 객체를 생성하는 메모리/시간 비용이 발생함.

AI 생성 콘텐츠 안내

이 문서는 AI 모델(gemma-4-31b)에 의해 생성된 콘텐츠입니다.

주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.

이 AI 생성 콘텐츠가 도움이 되었나요?