프로그래밍백엔드 개발자

파이썬의 고阶 함수 데코레이터란 무엇이며, 이를 통해 '포장' 패턴을 구현하는 방법과 함수 메타데이터/문서 작업 시 고려해야 할 점은 무엇인가요?

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

답변.

파이썬에서 고阶 함수 데코레이터란 다른 함수(또는 클래스)를 인자로 받아 새로운 함수(또는 수정된 클래스를 반환하는 함수)입니다. 데코레이터는 기존 함수의 원본 코드를 변경하지 않고 추가 로직(예: 로깅, 캐싱, 권한 검사 등)을 추가할 수 있게 해주는 '포장' 패턴을 구현하는 데 자주 사용됩니다.

원본 함수의 이름, 문서 및 기타 메타데이터를 유지하기 위해 functools.wraps 함수를 사용하는 것이 좋습니다:

import functools def log_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(f'Calling {func.__name__}') return func(*args, **kwargs) return wrapper @log_decorator def add(a, b): """두 숫자를 더합니다""" return a + b print(add(2, 3)) # 출력: Calling add 5 print(add.__name__) # 출력: add print(add.__doc__) # 출력: 두 숫자를 더합니다

핵심 사항: functools.wraps 없이는 포장된 함수가 원래의 이름, 문서 및 기타 메타데이터를 잃게 되어, 이는 디버깅과 자동 문서 생성에 부정적인 영향을 미칩니다.

헛갈리는 질문.

functools.wraps 없이 함수를 데코레이터로 장식하면 namedoc 속성이 어떻게 되나요?

답답: 그들은 내부 래퍼 함수(보통 'wrapper')로부터 상속받게 되며, 원래의 메타데이터를 잃게 됩니다.

def simple_decorator(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @simple_decorator def f(): """이것은 docstring입니다""" pass print(f.__name__) # 출력: 'wrapper' (아니면 'f') print(f.__doc__) # 출력: None (이것은 '이것은 docstring입니다'가 아님)

주제의 미세한 부분을 몰라서 발생한 실제 오류 사례.


이야기

프로젝트에서 API 엔드포인트 로깅을 위한 복잡한 데코레이터 시스템을 구현했지만 functools.wraps를 사용하지 않았습니다. 결과적으로 문서 자동 생성(Swagger/OpenAPI)과 도구가 모든 엔드포인트의 이름을 'wrapper'로 표시하고 문서가 사라졌습니다. 이는 유지 보수, 테스트 및 지원을 매우 어렵게 만들었습니다.


이야기

pytest로 단위 테스트를 작성하는 도중, 테스트 함수가 데코레이터 없이 wraps 없이 데코레이터됨으로 인해 자동 발견이 실패했습니다. 왜냐하면 이러한 함수의 __name__이 올바르지 않았기 때문입니다. 이유는 pytest가 이름으로 함수를 찾기 때문입니다.


이야기

예외 스택(traceback)을 추적하는 동안 스택 크래시가 항상 'wrapper'를 가리켰고, 어떤 함수가 오류를 발생시킨 것인지 이해할 수 없었습니다. 왜냐하면 루트 메타데이터가 사용자 정의 데코레이터에 functools.wraps가 없어서 사라졌기 때문입니다.