Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬 가비지 컬렉션(Garbage Collection) 완벽 가이드 – 참조 카운트와 소멸자 이해하기

파이썬(Python)은 더 이상 필요하지 않은 객체(내장 타입이나 클래스 인스턴스)를 자동으로 삭제하여 메모리 공간을 확보합니다. 이처럼 파이썬이 주기적으로 사용되지 않는 메모리 블록을 해제하고 회수하는 과정을 가비지 컬렉션(Garbage Collection)이라고 부릅니다.

참조 카운트(Reference Count) 기반의 메모리 관리

파이썬의 가비지 컬렉터는 프로그램 실행 도중에 동작하며, 객체의 참조 카운트가 0에 도달하는 순간 트리거됩니다. 객체의 참조 카운트는 해당 객체를 가리키는 별칭(alias)의 개수가 변할 때마다 함께 변경됩니다.

객체에 새로운 이름을 할당하거나 리스트·튜플·딕셔너리 같은 컨테이너에 넣으면 참조 카운트가 증가합니다. 반대로 del 키워드로 객체를 삭제하거나, 참조가 다른 대상으로 재할당되거나, 참조가 스코프(scope)를 벗어나면 참조 카운트가 감소합니다. 참조 카운트가 0이 되면 파이썬은 해당 객체를 자동으로 수집합니다.

a = 40      # 객체 <40> 생성
b = a       # <40>의 참조 카운트 증가
c = [b]     # <40>의 참조 카운트 증가
del a       # <40>의 참조 카운트 감소
b = 100     # <40>의 참조 카운트 감소
c[0] = -1   # <40>의 참조 카운트 감소

소멸자(Destructor) __del__() 메서드

일반적으로 가비지 컬렉터가 고아(orphaned) 인스턴스를 소멸시키고 공간을 회수하는 시점은 눈에 띄지 않습니다. 하지만 클래스에서 특수 메서드인 __del__(), 즉 소멸자(destructor)를 구현하면 인스턴스가 곧 소멸될 때 이 메서드가 호출됩니다. 이 메서드는 파일 핸들, 네트워크 연결 등 인스턴스가 사용 중이던 메모리 외부 자원을 정리하는 용도로 활용할 수 있습니다.

예제

다음 예제의 __del__() 소멸자는 곧 소멸될 인스턴스의 클래스 이름을 출력합니다.

#!/usr/bin/python3

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __del__(self):
        class_name = self.__class__.__name__
        print(class_name, "destroyed")

pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1), id(pt2), id(pt3))  # 객체들의 id 출력
del pt1
del pt2
del pt3

실행 결과

위 코드를 실행하면 다음과 같은 결과가 출력됩니다.

3083401324 3083401324 3083401324
Point destroyed

추가로 알아두면 좋은 점

참조 카운트 방식만으로는 서로를 참조하는 순환 참조(circular reference) 상황을 처리하기 어렵습니다. 이를 보완하기 위해 CPython은 세대별 가비지 컬렉터(generational GC)를 함께 사용하여, 순환 참조로 인해 회수되지 못한 쓰레기 객체도 주기적으로 탐지하고 해제합니다. 따라서 실제 파이썬의 메모리 관리는 '참조 카운팅 + 세대별 GC' 두 가지 메커니즘이 협력하는 구조라고 이해하면 좋습니다.