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

[PYTHON] 메모리 누수 해결하는 3가지 비결 : Weakref 모듈 활용 방법과 강한 참조와의 차이

by Papa Martino V 2026. 3. 3.
728x90
Weakref 모듈
Weakref 모듈

 

파이썬은 강력한 가비지 컬렉션(Garbage Collection, GC) 기능을 갖추고 있어 개발자가 메모리 관리에 직접 관여할 일이 적습니다. 하지만 복잡한 객체 관계를 설계하다 보면 순환 참조(Circular Reference)대용량 캐싱 과정에서 메모리가 해제되지 않고 쌓이는 '메모리 누수' 현상을 겪게 됩니다. 이를 세련되게 해결할 수 있는 열쇠가 바로 weakref 모듈입니다. 본 가이드에서는 전문 개발자의 시각에서 약한 참조의 메커니즘과 실무 적용 시나리오를 심도 있게 다룹니다.


1. 왜 Weakref가 필요한가? (문제 인식과 해결)

파이썬의 기본 참조 방식은 '강한 참조(Strong Reference)'입니다. 객체가 하나라도 강한 참조를 받고 있다면 참조 횟수(Reference Count)가 0이 되지 않아 GC가 해당 객체를 메모리에서 제거할 수 없습니다. weakref는 참조 횟수를 늘리지 않으면서 객체에 접근할 수 있게 해줌으로써, 대상 객체가 소멸되는 것을 방해하지 않습니다.


2. 강한 참조 vs 약한 참조: 핵심 차이 분석

두 참조 방식의 기술적 차이를 이해하는 것이 올바른 설계의 시작입니다.

참조 횟수(Ref Count)1 증가 시킴증가시키지 않음
GC 대상 포함 여부참조 중이면 소멸 불가참조 중이어도 소멸 가능
주요 용도일반적인 객체 할당 및 사용캐싱, 순환 참조 방지, 관찰자 패턴
접근 실패 시 결과항상 객체 존재 보장객체 소멸 시 None 반환 또는 에러

3. Weakref를 반드시 사용해야 하는 3가지 구체적 상황

첫째, 대규모 객체 캐싱 (Memory-Efficient Caching)

이미지를 로딩하거나 대용량 데이터프레임을 캐싱할 때, 일반적인 dict에 저장하면 해당 딕셔너리가 살아있는 한 메모리는 절대 비워지지 않습니다. 이때 weakref.WeakValueDictionary를 사용하면, 시스템의 다른 곳에서 해당 객체를 더 이상 사용하지 않을 때 캐시에서도 자동으로 삭제되도록 설계할 수 있습니다.

둘째, 순환 참조 구조의 고리 끊기

부모 객체가 자식 객체를 참조하고, 자식 객체가 다시 부모 객체를 참조하는 '양방향 참조' 구조에서 강한 참조를 사용하면 메모리 누수의 주범이 됩니다. 자식이 부모를 참조할 때 weakref.ref()를 사용하면 부모 객체가 안전하게 소멸될 수 있는 통로를 열어줍니다.

셋째, 프레임워크 및 라이브러리의 'Registry' 구현

현재 활성화된 모든 세션이나 연결 상태를 추적해야 하는 레지스트리 패턴에서, 수동으로 '제거' 로직을 넣는 것은 실수할 확률이 높습니다. 약한 참조를 활용하면 객체가 소멸될 때 레지스트리에서도 자동으로 자취를 감추게 할 수 있어 관리가 매우 용이합니다.


4. Sample Example: WeakValueDictionary 활용 방법

실제 실무에서 가장 활용도가 높은 '자동 소멸 캐시' 구현 예제입니다.


import weakref
import gc

class LargeData:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return f"LargeData({self.name})"

# 1. 약한 참조 딕셔너리 생성
cache = weakref.WeakValueDictionary()

# 2. 객체 생성 및 캐싱
obj = LargeData("BigFile_01")
cache["item1"] = obj

print(f"캐시 상태: {list(cache.items())}") # 출력됨

# 3. 강한 참조 제거
del obj
gc.collect() # 가비지 컬렉션 강제 수행

# 4. 캐시 확인 (자동으로 비워짐)
print(f"삭제 후 캐시 상태: {list(cache.items())}") # [] 출력

5. 주의사항: 모든 객체에 적용 가능한가?

파이썬의 모든 객체가 약한 참조를 지원하는 것은 아닙니다. int, str, tuple, list와 같은 기본 내장 타입은 기본적으로 약한 참조를 지원하지 않습니다. 반면 사용자 정의 클래스 인스턴스나 set 등은 지원이 가능합니다. 만약 직접 만든 클래스에 __slots__를 정의했다면, '__weakref__' 항목을 추가해야 약한 참조 기능을 사용할 수 있다는 점을 기억하십시오.


6. 결론: 효율적인 메모리 설계의 완성

weakref는 단순히 메모리를 아끼는 도구가 아니라, 객체의 생명 주기를 명확히 정의하고 시스템의 안정성을 높이는 고급 설계 기법입니다. 순환 참조가 우려되거나 대용량 데이터를 다루는 프로젝트라면, 오늘 소개한 방법들을 통해 파이썬의 GC와 협력하는 지능적인 코드를 작성해 보시기 바랍니다.


글 내용의 출처

  • Python Standard Library Documentation: weakref — Weak references
  • PEP 205 — Weak References
  • Real Python: Memory Management in Python
  • High Performance Python (Micha Gorelick, Ian Ozsvald) - Memory usage chapter
728x90