hhkb.dev

BLOG

2025-12-17 / 파이썬기초 · 03

메모리 관리와 가비지 컬렉션

1. 파이썬의 메모리 관리 전략

파이썬은 개발자가 직접 메모리를 할당하고 해제하지 않는다. C/C++의 malloc/free처럼 직접 다루는 구조가 아니라, 런타임이 자동으로 관리한다.

기본 구조는 두 가지를 함께 쓰는 방식이다.

  1. 레퍼런스 카운팅: 가장 기본이 되는 주 방식
  2. 가비지 컬렉션: 순환 참조를 정리하는 보조 방식

2. 레퍼런스 카운팅 (Reference Counting)

레퍼런스 카운팅은 각 객체가 몇 번 참조되고 있는지를 세는 방식이다. CPython에서는 이 값을 ob_refcnt로 관리한다.

  • 작동 원리:
    • 객체를 참조하는 이름이나 객체가 늘어나면 카운트가 올라간다.
    • 이 값이 0이 되는 순간 메모리에서 바로 해제된다.
  • 장점:
    • 언제 메모리가 해제되는지 시점이 비교적 명확하다.
    • 사용이 끝난 객체를 바로 정리할 수 있어서 반응이 빠르다.
  • 단점:
    • 순환 참조를 스스로 해결하지 못한다.
    • 예를 들어 A가 B를 참조하고, B도 A를 참조하면 둘 다 안 써도 카운트가 0이 되지 않아 남아 있을 수 있다.

3. 세대별 가비지 컬렉션 (Generational Garbage Collection)

세대별 가비지 컬렉션은 레퍼런스 카운팅이 해결하지 못하는 순환 참조를 정리하기 위해 존재한다.

핵심 가정은 이렇다.

  • 대부분의 객체는 금방 필요 없어지고
  • 오래 살아남은 객체는 계속 오래 남을 가능성이 높다

작동 방식은 0세대부터 2세대까지 나눠서 보면 된다.

  1. 모든 객체는 처음에 0세대로 시작한다.
  2. 파이썬은 주기적으로 0세대 객체를 검사한다.
  3. 살아남은 객체는 1세대로 올라간다.
  4. 다시 살아남으면 2세대로 올라간다.
  5. 세대가 높을수록 검사 주기는 더 길어진다.

4. 순환 참조와 weakref

순환 참조는 gc가 결국 정리해주지만, 컬렉션이 돌기 전까지는 메모리를 계속 잡고 있을 수 있다. 그래서 구조에 따라서는 weakref를 쓰는 편이 낫다.

  • 약한 참조(weakref): 객체를 가리키되, 레퍼런스 카운트를 올리지 않는 참조 방식이다.
  • 사용처: 캐시를 만들거나, 객체끼리 서로 연결돼야 하지만 수명까지 서로 붙잡으면 안 되는 경우에 유용하다.
import weakref

class A: pass

a = A()
r = weakref.ref(a) # 참조 카운트 안 올라감

print(r()) # 객체 접근 가능
del a      # 원본 삭제됨
print(r()) # None (접근 불가, 자동으로 연결 끊김)