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

[PYTHON] Memory Leak 방지를 위한 gc 모듈 활용 방법과 참조 횟수 관리의 2가지 핵심 차이

by Papa Martino V 2026. 4. 11.
728x90

Memory Leak
Memory Leak

 

파이썬은 개발자가 직접 메모리를 할당하고 해제할 필요가 없는 편리한 언어입니다. 하지만 대규모 AI 모델 서빙, 장시간 실행되는 백엔드 서버, 혹은 복잡한 데이터 파이프라인을 구축할 때 메모리 누수(Memory Leak) 현상은 예기치 못한 서비스 중단(OOM: Out Of Memory)을 초래합니다. 본 가이드에서는 파이썬 메모리 관리의 심장부인 참조 횟수(Reference Counting)와 이를 보완하는 Garbage Collection(gc) 모듈의 작동 원리를 파헤치고, 실무에서 즉시 적용 가능한 7가지 메모리 최적화 해결 방법을 제시합니다.


1. 파이썬 메모리 관리의 근간: 참조 횟수와 순환 참조의 차이

파이썬의 주된 메모리 해제 메커니즘은 '참조 횟수 계산'입니다. 객체가 참조될 때마다 카운트가 올라가고, 참조가 끊겨 0이 되면 즉시 메모리에서 제거됩니다. 그러나 두 객체가 서로를 참조하는 순환 참조(Circular Reference)가 발생하면 참조 횟수가 0이 되지 않아 메모리 누수가 발생합니다. 이를 해결하기 위해 파이썬은 세대별 가비지 컬렉터(Generational Garbage Collector)를 별도로 운영합니다.


2. 참조 횟수(RC)와 가비지 컬렉션(GC) 비교 분석

메모리 관리의 두 축인 RC와 GC의 특성을 표로 비교하여 정확한 적용 시점을 파악해 보겠습니다.

항목 참조 횟수 관리 (Reference Counting) 가비지 컬렉션 (Generational GC)
작동 시점 참조 카운트가 0이 되는 즉시 실행 특정 임계치(Threshold) 도달 시 실행
주요 장점 실시간 메모리 해제, 예측 가능성 순환 참조 문제 완벽 해결
성능 부하 모든 객체 조작 시 발생 (분산됨) "Stop-the-world" 발생으로 일시적 멈춤
관리 대상 모든 파이썬 객체 컨테이너 객체 (List, Dict, Class 등)
활용 도구 sys.getrefcount() gc 모듈 (gc.collect 등)

3. 실무 중심의 Memory Leak 해결 Example (7가지)

개발자가 복잡한 시스템에서 메모리 효율을 극대화하기 위해 바로 사용할 수 있는 실전 코드 예제입니다.

Example 1: sys.getrefcount를 이용한 참조 상태 모니터링

특정 객체가 왜 메모리에서 해제되지 않는지 추적하기 위한 가장 기본적인 방법입니다.


import sys

class DataBlock:
    pass

obj = DataBlock()
print(f"현재 참조 횟수: {sys.getrefcount(obj) - 1}") # 함수 인자로 전달되어 1 증가함

reference_list = [obj, obj]
print(f"리스트 추가 후 참조 횟수: {sys.getrefcount(obj) - 1}")
    

Example 2: 순환 참조 발생 상황과 gc.collect() 강제 호출

서로를 참조하는 클래스 구조에서 GC가 어떻게 메모리를 회수하는지 확인합니다.


import gc

class Node:
    def __init__(self, value):
        self.value = value
        self.parent = None

# 순환 참조 생성
a = Node(1)
b = Node(2)
a.parent = b
b.parent = a

del a
del b

# 강제 가비지 컬렉션 수행 (순환 참조 객체 회수)
collected = gc.collect()
print(f"회수된 객체 수: {collected}")
    

Example 3: weakref(약한 참조)를 활용한 순환 참조 방지

참조 횟수를 올리지 않으면서 객체에 접근하는 방법으로, 메모리 누수를 원천 차단하는 고급 기법입니다.


import weakref

class LargeObject:
    def __del__(self):
        print("객체가 소멸되었습니다.")

obj = LargeObject()
# 약한 참조 생성
weak_obj = weakref.ref(obj)

print(f"객체 존재 여부: {weak_obj()}")
del obj
print(f"삭제 후 약한 참조 상태: {weak_obj()}") # None 반환
    

Example 4: gc.set_threshold를 이용한 GC 주기 최적화

메모리 할당이 잦은 AI 애플리케이션에서 GC 실행 빈도를 조절하여 성능 병목을 해결합니다.


import gc

# 현재 임계값 확인 (700, 10, 10 이 기본값)
print(f"기존 임계값: {gc.get_threshold()}")

# 가비지 컬렉션이 너무 자주 일어나 성능이 저하된다면 임계값을 높임
gc.set_threshold(5000, 15, 15)
print(f"새로운 임계값: {gc.get_threshold()}")
    

Example 5: gc.get_objects()를 활용한 누수 객체 전수 조사

현재 힙(Heap) 영역에 살아있는 모든 객체를 분석하여 어떤 타입이 메모리를 점유하고 있는지 파악합니다.


import gc

def leak_detector():
    gc.collect()
    objects = gc.get_objects()
    type_counts = {}
    for obj in objects:
        t = type(obj)
        type_counts[t] = type_counts.get(t, 0) + 1
    
    # 상위 5개 점유 타입 출력
    sorted_types = sorted(type_counts.items(), key=lambda x: x[1], reverse=True)
    for t, count in sorted_types[:5]:
        print(f"{t}: {count}")

leak_detector()
    

Example 6: slots를 이용한 인스턴스 메모리 절약

클래스 인스턴스 생성 시 `__dict__` 생성을 억제하여 참조 오버헤드와 메모리 사용량을 획기적으로 줄입니다.


class OptimizedPoint:
    __slots__ = ['x', 'y'] # 메모리 사용량 최적화 및 속도 향상
    def __init__(self, x, y):
        self.x = x
        self.y = y

# 수백만 개의 객체 생성 시 일반 클래스 대비 메모리 40% 이상 절감
points = [OptimizedPoint(i, i) for i in range(1000000)]
    

Example 7: Context Manager를 활용한 명시적 자원 해제

파일 핸들이나 소켓 등 외부 자원이 RC 지연으로 인해 닫히지 않는 문제를 해결합니다.


from contextlib import closing
import sqlite3

# 참조 횟수에 의존하지 않고 블록이 끝날 때 자원을 즉시 반납
with closing(sqlite3.connect(":memory:")) as conn:
    with closing(conn.cursor()) as cursor:
        cursor.execute("SELECT 1")
        print("연결이 안전하게 종료됩니다.")
    

4. 고성능 파이썬 시스템을 위한 메모리 관리 전략

결론적으로, 파이썬의 메모리 관리는 자동이지만 개발자의 설계에 따라 그 효율은 천차만별입니다. 실시간 응답이 중요한 시스템에서는 `gc.disable()`을 사용하고 유휴 시간에 `gc.collect()`를 명시적으로 호출하는 전략이 유효할 수 있습니다. 또한, 순환 참조가 의심되는 부모-자식 관계의 객체 구조에서는 반드시 `weakref`를 도입하여 GC의 부하를 줄여야 합니다.


5. 내용의 출처 및 참고 자료

  • Python Software Foundation: "Garbage Collector Design" - Internal docs
  • Real Python: "Memory Management in Python" (Deep Dive)
  • PyCon Korea Tech Talk: "Effective Memory Management for Large Data"
  • Official Python Docs: "gc — Garbage Collector interface"
728x90