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

[PYTHON] 클로저(Closure) 형성의 3가지 조건과 __closure__ 속성 활용 방법 및 일반 함수와의 차이

by Papa Martino V 2026. 3. 1.
728x90

클로저(Closure) 형성
클로저 (Closure) 형성

 

파이썬 프로그래밍에서 '함수'는 단순히 코드를 묶어놓은 단위를 넘어섭니다. 특히 클로저(Closure)는 함수가 정의된 환경을 런타임에 보존하는 강력한 메커니즘을 제공합니다. 이는 데코레이터(Decorator)의 기초가 되며, 데이터 은닉과 상태 유지를 위해 객체 지향 프로그래밍의 대안으로도 널리 사용됩니다. 본 포스팅에서는 클로저가 형성되는 엄격한 3가지 성립 조건과 그 환경을 물리적으로 저장하는 __closure__ 속성의 내부 동작 원리를 심층적으로 분석합니다.


1. 클로저(Closure)란 무엇인가?

클로저는 '자신을 둘러싼 외부 범위(Scope)의 상태를 기억하고 있는 함수'를 말합니다. 일반적인 함수는 실행이 끝나면 내부의 지역 변수가 메모리에서 사라지지만, 클로저는 외부 함수의 실행이 종료된 후에도 그 환경을 유지합니다. 이는 파이썬 인터프리터가 해당 변수를 '자유 변수(Free Variable)'로 식별하여 별도의 공간에 캡슐화하기 때문입니다.


2. 클로저가 형성되기 위한 3가지 필수 성립 조건

파이썬에서 어떤 함수가 클로저로 인정받기 위해서는 다음의 3가지 조건을 동시에 만족해야 합니다. 이 중 하나라도 누락되면 이는 단순한 중첩 함수에 불과합니다.

[비교] 일반 중첩 함수 vs 클로저의 구조적 차이

조건 항목 상세 내용 미충족 시 발생하는 현상
01. 중첩 구조 반드시 함수 내부에 또 다른 함수가 정의되어야 함 단일 스코프로 처리되어 상태 보존 불가
02. 자유 변수 참조 내부 함수가 외부 함수의 지역 변수를 참조해야 함 단순 함수 호출로 처리되어 환경 바인딩 생략
03. 반환(Return) 외부 함수가 내부 함수 자체를 반환해야 함 외부 함수 종료 시 내부 함수의 생명주기도 종료

3. __closure__ 속성의 정체와 역할 해결

파이썬 함수 객체는 __closure__라는 특수 속성을 가집니다. 이 속성은 클로저가 포착한 외부 환경의 'Cell' 객체들로 구성된 튜플입니다. 만약 함수가 클로저가 아니라면 이 값은 None을 반환합니다.

  • Cell 객체: 여러 스코프에서 공유되는 변수를 저장하는 상자 역할을 합니다.
  • cell_contents: Cell 객체 내부의 실제 값에 접근할 수 있게 해주는 속성입니다.

4. Sample Example: 클로저 추적 및 내부 값 수정 방법

다음 예제는 숫자를 누적해서 더하는 클로저를 구현하고, __closure__ 속성을 통해 저장된 상태를 확인하는 방법을 보여줍니다.


def make_accumulator(start_value):
    # 외부 함수의 지역 변수
    count = [start_value]
    
    def accumulator(amount):
        # 외부 함수의 변수 count를 참조 (자유 변수)
        count[0] += amount
        return count[0]
    
    # 내부 함수 자체를 반환
    return accumulator

# 클로저 인스턴스 생성
acc = make_accumulator(10)

print(f"결과 1: {acc(5)}")  # 15
print(f"결과 2: {acc(10)}") # 25

# __closure__ 속성 확인
if acc.__closure__:
    for i, cell in enumerate(acc.__closure__):
        print(f"Cell {i} 내용: {cell.cell_contents}")
else:
    print("이 함수는 클로저가 아닙니다.")

코드 분석 및 해결 방법

위 코드에서 acc 함수는 make_accumulator의 실행이 끝났음에도 count 리스트를 기억합니다. acc.__closure__[0].cell_contents를 호출하면 현재 누적된 값인 25를 확인할 수 있습니다. 만약 정수형(immutable) 변수를 직접 수정하고 싶다면 내부 함수 내에서 nonlocal 키워드를 사용하여 스코프 문제를 해결할 수 있습니다.


5. 전문적인 시각: 왜 클래스 대신 클로저를 사용하는가?

현업 전문가들은 메서드가 하나뿐인 클래스를 설계할 때 대신 클로저를 사용하여 메모리 오버헤드를 줄이고 코드 가독성을 높입니다. 클래스는 인스턴스 딕셔너리(__dict__)를 생성하여 메모리를 점유하지만, 클로저는 필요한 최소한의 자유 변수만을 'Cell'에 담아 바인딩하기 때문에 훨씬 가볍고 빠릅니다. 또한, 함수형 프로그래밍의 불변성(Immutability) 원칙을 지키기에 매우 유리한 구조를 갖추고 있습니다.


6. 결론: 클로저 이해의 가치

파이썬의 클로저는 단순히 흥미로운 문법적 설탕이 아닙니다. 인터프리터가 변수와 메모리를 관리하는 방식을 깊이 이해할 수 있는 창구입니다. __closure__ 속성을 통해 내부 상태를 투영해 보는 습관을 가지면, 복잡한 데코레이터나 비동기 프로그래밍에서 발생하는 스코프 버그를 해결하는 데 결정적인 지식을 얻게 될 것입니다.


내용의 출처 및 전문 자료

  • Python.org - The Python Standard Library: Data Model (Section 3.2)
  • "Fluent Python" by Luciano Ramalho - Chapter 7: Function Decorators and Closures
  • "Expert Python Programming" by Michał Jaworski - Advanced Functional Programming Techniques
  • Stack Overflow Official Python Documentation Archives - Understanding __closure__ and Cells
728x90