프로그래밍백엔드 개발자

파이썬에서 메모리 관리가 어떻게 작동하는지 설명하고, 가비지 수집기에 대해 설명하세요. 순환 참조란 무엇이며, 파이썬은 이를 어떻게 처리합니까?

Hintsage AI 어시스턴트로 면접 통과

응답

파이썬에서는 메모리가 자동으로 관리됩니다: 객체가 생성되면 메모리가 할당되고, 더 이상 다른 객체가 그 객체를 참조하지 않으면 메모리가 해제됩니다. 기본 전략은 참조 카운트입니다: 각 객체에는 참조 카운터가 연결되어 있으며, 카운터가 0이 되면 객체가 삭제됩니다.

하지만 순환 참조가 발생할 수 있습니다. 객체들이 서로를 참조할 때, 외부 코드로부터의 참조가 제거되더라도 그들의 참조 카운터가 절대 0이 되지 않습니다.

이를 해결하기 위해 파이썬(CPython)에는 가비지 수집기 (garbage collector, GC)가 있어, 루트에서 도달할 수 없는 객체들 간의 순환을 감지하고 삭제합니다. 가비지 수집기는 gc 모듈을 통해 관리할 수 있습니다.

순환의 예:

class Node: def __init__(self): self.ref = None n1 = Node() n2 = Node() n1.ref = n2 n2.ref = n1 del n1, n2 # 객체는 여전히 살아있음 (순환 참조 때문에!)

함정 질문

질문: "만약 del obj를 호출하면 메모리가 항상 즉시 해제되나요?"
응답: 아닙니다! del 작업은 객체에 대한 참조를 하나만 제거합니다. 다른 참조가 어디에선가 남아 있다면 (명시적으로나 순환적으로) 참조 카운터가 0이 될 때까지 및/또는 GC가 순환을 제거할 때까지 메모리는 해제되지 않습니다. 예:

import gc class A: pass x = A() y = x del x # y에 여전히 참조가 남아있음, 객체가 살아있음! del y # 이제야 객체가 삭제될 수 있음

주제의 미세한 내용 때문에 발생하는 실제 오류 사례


이야기

대량 파일 처리 시스템에서 메모리에 연결된 객체를 유지하고 있었습니다. 외부 참조를 삭제한 후에도 메모리가 여전히 해제되지 않았습니다. 원인은 순환 참조로, 즉시 정리되지 않거나 경우에 따라 소멸자 __del__의 존재로 인해 전혀 정리되지 않았습니다.


이야기

장기 실행 서버 프로세스에서 순환 그래프를 가진 큰 임시 구조가 자주 생성되었습니다. 개발자들은 GC의 임시 디버그 출력을 비활성화하지 않았고, 이로 인해 가끔씩 느린 느린 속도가 발생했습니다. "성능 저하"로 진단되었습니다. 원인은 가비지 수집기가 자주 실행되어 발생한 문제였습니다.


이야기

대규모 프로젝트를 PyPy(대체 인터프리터)로 포팅할 때, 이전 코드는 참조 카운트를 통한 즉각적인 메모리 청소에 대한 CPython의 특정 동작에 의존했으며, PyPy에서는 객체가 즉시 삭제되고 청소되지 않고 GC의 "원하는 대로" 삭제되었기 때문에 열린 파일과 네트워크 연결에서 예측할 수 없는 동작을 초래했습니다.