
파이썬 데코레이터 활용법: 로깅부터 권한 검증까지 완벽 가이드
1. 파이썬 데코레이터: 강력한 프로그래밍 도구
파이썬 데코레이터는 프로그래머가 원래 함수 정의를 수정하지 않고도 함수에 추가 기능을 부여할 수 있는 매우 강력한 도구입니다.
이 기능 덕분에 코드 유지보수와 확장이 한결 수월해지는데요.
동시에 코드 가독성과 재사용성도 크게 향상됩니다.
데코레이터는 로깅, 성능 테스트, 트랜임 처리, 캐싱, 권한 검증 등 다양한 분야에서 활용되고 있습니다.
이번 글에서는 구체적인 예시를 통해 파이썬에서 데코레이터를 어떻게 활용할 수 있는지 자세히 알아보겠습니다.
2. 로깅
소프트웨어 개발 과정에서 로깅은 매우 중요한 작업입니다.
로깅을 통해 개발자는 코드의 실행 흐름을 추적하고, 오류를 진단하며, 시스템의 운영 상태를 모니터링할 수 있습니다.
데코레이터를 활용하면 각 함수에 일일이 로깅 코드를 추가하지 않아도 함수에 로깅 기능을 쉽게 추가할 수 있습니다.
이는 코드 중복을 줄여주고, 코드 구조를 더욱 명확하게 만들어 줍니다.
import logging
def log_decorator(func):
def wrapper(*args, **kwargs):
logging.info(f"'{func.__name__}' 함수를 인수 {args}, {kwargs}와 함께 실행합니다.")
return func(*args, **kwargs)
return wrapper
@log_decorator
def say_hello(name):
print(f"안녕하세요, {name}님!")
say_hello("앨리스")
코드 해설
위 코드는 log_decorator
라는 데코레이터 함수를 정의합니다.
이 함수는 func
라는 함수를 매개변수로 받아 새로운 함수 wrapper
를 반환합니다.
wrapper
함수에서는 먼저 logging.info
를 사용해 호출된 함수의 이름과 전달된 인수를 기록한 후, 원래 함수 func
를 호출하고 그 실행 결과를 반환합니다.
say_hello
함수 정의 위에 @log_decorator
를 배치함으로써, say_hello
함수는 이 데코레이터의 적용을 받게 됩니다.
따라서 say_hello
함수가 호출될 때마다 자동으로 로깅이 기록됩니다.
3. 성능 테스트
성능 최적화를 할 때는 코드의 실행 시간을 측정하여 성능 병목 지점을 찾아내고 최적화하는 작업이 자주 필요합니다.
데코레이터를 활용하면 이 과정을 자동화하고 표준화할 수 있어, 서로 다른 함수의 성능을 비교하고 분석하기가 훨씬 수월해집니다.
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 함수가 실행되는 데 {end_time - start_time:.4f}초 걸렸습니다.")
return result
return wrapper
@timing_decorator
def slow_function(delay_time):
time.sleep(delay_time)
slow_function(2)
코드 해설
이 코드는 timing_decorator
데코레이터를 정의합니다.
wrapper
함수 내부에서는 time.time()
을 사용해 함수가 실행되기 전과 후의 시간을 기록합니다.
두 시간의 차이를 계산하여 함수의 실행 시간을 출력합니다.
이렇게 하면 timing_decorator
로 장식된 함수가 호출될 때마다 함수의 실행 시간이 자동으로 출력됩니다.
4. 결과 캐싱
시간이 많이 소요되는 계산, 특히 입력과 출력이 고정된 함수의 경우, 같은 결과를 다시 계산하는 것은 시간과 자원을 낭비하는 일입니다.
데코레이터를 사용해 결과를 캐싱하면 성능을 크게 향상시키고 불필요한 반복 계산을 피할 수 있습니다.
from functools import lru_cache
@lru_cache(maxsize=32)
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(10)) # 55
코드 해설
여기서는 functools
모듈의 lru_cache
데코레이터를 사용했습니다.
lru_cache
는 Least Recently Used(최소 최근 사용) 캐시를 의미하며, 함수의 호출 결과를 자동으로 캐싱합니다.
동일한 매개변수로 다시 호출되면 캐시된 결과를 바로 반환하므로 함수를 다시 실행하지 않습니다.
maxsize
매개변수는 캐시의 최대 용량을 지정합니다.
캐시가 이 용량에 도달하면 가장 최근에 사용되지 않은 캐시 항목이 제거됩니다.
5. 권한 검증
웹 개발에서는 사용자의 권한을 검증하여 해당 권한을 가진 사용자만 특정 작업을 수행할 수 있도록 해야 하는 경우가 많습니다.
데코레이터를 활용하면 권한 검증 로직을 비즈니스 로직과 분리하여 코드의 유지보수성을 높일 수 있습니다.
from functools import wraps
def permission_required(permission):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
user_permission = kwargs.get('user_permission')
if user_permission != permission:
raise Exception("권한이 없습니다.")
return func(*args, **kwargs)
return wrapper
return decorator
@permission_required('admin')
def delete_user(user_id, user_permission):
print(f"사용자 {user_id}가 삭제되었습니다.")
delete_user(1, user_permission='admin') # 성공
delete_user(1, user_permission='guest') # 예외 발생: 권한이 없습니다.
코드 해설 permission_required
는 데코레이터 팩토리 함수로, 필요한 권한을 나타내는 permission
매개변수를 받습니다.
내부의 decorator
함수는 func
함수를 매개변수로 받아 새로운 wrapper
함수를 반환합니다.
wrapper
함수에서는 kwargs
에 user_permission
이 포함되어 있는지, 그리고 이 권한이 필요한 권한과 일치하는지 확인합니다.
일치하지 않으면 Permission denied
예외를 발생시키고, 일치하면 원래 함수 func
를 실행합니다.
6. 파라미터 검증
데코레이터는 함수의 파라미터를 검증하여 특정 조건을 충족하는지 확인하는 데도 사용할 수 있습니다.
이를 통해 함수 실행 전에 파라미터 오류를 감지하고, 함수 내부에서 불필요한 작업을 피하며, 코드의 견고성을 높일 수 있습니다.
from functools import wraps
def type_check(correct_type):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
if not all([isinstance(arg, correct_type) for arg in args]):
raise ValueError("잘못된 인수 타입입니다.")
return func(*args, **kwargs)
return wrapper
return decorator
@type_check(str)
def string_repeat(string, times):
return string * times
print(string_repeat("hello", 3)) # "hellohellohello"
string_repeat("hello", "3") # ValueError 발생
코드 해설 type_check
데코레이터 팩토리 함수는 예상되는 파라미터 타입을 나타내는 correct_type
매개변수를 받습니다.
wrapper
함수에서는 isinstance
함수를 사용해 모든 위치 인수가 지정된 타입인지 확인합니다.
인수 타입이 일치하지 않으면 ValueError
예외를 발생시키고, 일치하면 원래 함수 func
를 실행합니다.
7. 마무리
데코레이터는 최소한의 코드 변경으로 함수의 기능을 확장할 수 있는 효율적이고 우아한 방법을 제공합니다.
이번 글에서 살펴본 예시를 통해 실제 개발에서 데코레이터의 강력한 기능과 유연한 활용법을 확인할 수 있었습니다.
데코레이터를 적절히 활용하면 코드를 더욱 간결하고 유지보수하기 쉽게 만들 수 있으며, 코드 가독성과 사용성도 향상됩니다.
일상적인 프로그래밍에서 데코레이터를 유연하게 활용하여 코드 구조를 최적화하고 개발 효율을 높여보세요!
'Python' 카테고리의 다른 글
파이썬 비동기 함수 Mocking, 더 이상 어렵지 않아요! (0) | 2025.03.22 |
---|---|
파이썬 PDF (Portable Document Format) 처리, Fitz (PyMuPDF) 하나면 끝! (0) | 2025.03.22 |
Python tile-tools 시작하기: Mapbox 타일 작업, 이제 어렵지 않아요! (1) | 2025.03.22 |
파이썬 Switch 문, 이제 이렇게 쓰세요! (2025년 최신 가이드) - Switch Case 완벽 예제 (0) | 2025.03.22 |
FastAPI 핵심 탐구: Starlette 깊이 파헤쳐보기 (0) | 2025.03.22 |