Python 강좌 / 데코레이터와 컨텍스트 매니저 이해하기
데코레이터는 함수의 호출 동작을 감싸고 컨텍스트 매니저는 작업 전후의 자원 수명을 관리합니다. 반복되는 공통 처리를 분리할 때 유용하지만 원래 함수의 반환·예외 계약을 바꾸지 않는지 확인해야 합니다.
감싸는 동작과 수명 관리
@decorator는 정의된 함수를 데코레이터에 전달한 결과로 이름을 연결하는 문법입니다. 단순히 주석처럼 표시하는 것이 아닙니다. with는 진입·종료 처리를 호출하며 예외가 나도 필요한 정리가 수행되도록 구성할 수 있습니다.
관련 동작과 지원 조건은 데코레이터와 컨텍스트 매니저 이해하기 관련 공식 문서에서 확인할 수 있습니다.
functools.wraps는 감싼 함수의 이름·문서 같은 메타데이터 보존을 돕습니다. 원래 함수의 모든 보안·자료형 계약을 자동으로 보장하는 기능은 아닙니다.
전체 예제와 실행 결과
별도의 실습 폴더에서 아래 파일을 UTF-8로 저장합니다. 가상환경을 선택한 터미널에서 python wrappers.py 명령으로 실행합니다. macOS·Ubuntu에서 가상환경을 사용하지 않는 경우 명령 이름을 python3으로 바꿉니다.
wrappers.py 파일의 전체 내용입니다.
from functools import wraps
from contextlib import contextmanager
def announce(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("start")
return func(*args, **kwargs)
return wrapper
@contextmanager
def temporary_items():
items = []
try:
yield items
finally:
items.clear()
print("cleared")
@announce
def total(amounts):
return sum(amounts)
with temporary_items() as items:
items.extend([3500, 8000])
print(total(items))
print(total.__name__)
print(items)
예상 결과는 다음과 같습니다.
start 11500 cleared total []
예외가 생기는 지점과 전달
contextmanager 함수는 한 번 yield하여 with 본문에 값을 제공하고, 종료 시 그 뒤의 정리 코드를 진행합니다. 정리를 finally에 두어 본문에서 예외가 나도 실행되게 했습니다. 예외를 잡고 그대로 삼키면 호출자는 실패를 모를 수 있으므로 의도한 경우가 아니면 다시 전달합니다.
데코레이터에서 원래 함수 반환값을 return하지 않으면 호출 결과가 None으로 바뀝니다. 매개변수 전달과 예외 전달도 감싸기 전후 동일한지 확인하세요.
적절한 사용 범위
재시도 데코레이터는 편리해 보여도 쓰기 요청을 반복해 거래를 중복 생성할 수 있습니다. 자원 정리용 with와 작업 재시도 정책을 구분합니다. 작은 코드에서 한 번만 쓰는 처리를 무조건 추상화할 필요도 없습니다.
- with 본문에서 의도적으로 ValueError를 발생시켜 cleared가 출력되는지 확인합니다.
- 정리 후 리스트가 빈 상태인지 확인합니다.
- wrapper의 return을 빼면 결과가 바뀌는지 관찰하고 원래대로 복구합니다.




