이미지 로딩 중...
CodeDeck AI
2025. 11. 8. · 1 Views
Python 데코레이터 완벽 가이드
파이썬 데코레이터의 기초부터 고급 활용까지 단계별로 학습합니다. 함수 데코레이터, 클래스 데코레이터, 파라미터가 있는 데코레이터 등 실무에서 자주 사용되는 패턴을 다룹니다.
들어가며
이 글에서는 Python 데코레이터 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- 기본_데코레이터_개념
- 함수_인자를_받는_데코레이터
- 파라미터가_있는_데코레이터
- functools_wraps_활용
- 클래스_기반_데코레이터
- 클래스_메서드_데코레이터
- property_데코레이터
- 여러_데코레이터_체이닝
- 캐싱_데코레이터_구현
- 실행_시간_측정_데코레이터
- 클래스_데코레이터
- 조건부_데코레이터_실행
1. 기본_데코레이터_개념
개요
데코레이터는 함수를 감싸서 기능을 추가하는 패턴입니다. @기호를 사용하여 간단하게 적용할 수 있습니다.
코드 예제
def my_decorator(func):
def wrapper():
print("함수 실행 전")
func()
print("함수 실행 후")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
설명
@my_decorator는 say_hello 함수를 wrapper로 감싸서 실행 전후에 추가 동작을 수행합니다.
2. 함수_인자를_받는_데코레이터
개요
*args와 **kwargs를 사용하면 어떤 인자든 받을 수 있는 범용 데코레이터를 만들 수 있습니다.
코드 예제
def logger(func):
def wrapper(*args, **kwargs):
print(f"호출: {func.__name__}")
result = func(*args, **kwargs)
print(f"결과: {result}")
return result
return wrapper
@logger
def add(a, b):
return a + b
add(3, 5)
설명
wrapper가 모든 인자를 받아서 원본 함수에 전달하고, 실행 과정을 로깅합니다.
3. 파라미터가_있는_데코레이터
개요
데코레이터 자체에 설정값을 전달하려면 3단계 중첩 함수를 사용합니다.
코드 예제
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(times=3)
def greet(name):
print(f"안녕하세요, {name}님!")
greet("철수")
설명
repeat(3)이 decorator를 반환하고, 이것이 greet 함수를 3번 실행하도록 감쌉니다.
4. functools_wraps_활용
개요
@wraps를 사용하면 원본 함수의 메타데이터(이름, 독스트링 등)를 보존할 수 있습니다.
코드 예제
from functools import wraps
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"TRACE: {func.__name__}")
return func(*args, **kwargs)
return wrapper
@trace
def calculate(x, y):
"""두 수를 곱합니다"""
return x * y
print(calculate.__name__) # calculate
설명
@wraps 없이는 함수 이름이 wrapper로 바뀌지만, 사용하면 원본 이름을 유지합니다.
5. 클래스_기반_데코레이터
개요
클래스의 call 메서드를 구현하면 클래스를 데코레이터로 사용할 수 있습니다.
코드 예제
class Counter:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"호출 횟수: {self.count}")
return self.func(*args, **kwargs)
@Counter
def say_hi():
print("Hi!")
say_hi()
say_hi()
설명
Counter 클래스가 함수 호출 횟수를 추적하며, __call__이 실제 함수 실행을 담당합니다.
6. 클래스_메서드_데코레이터
개요
클래스 메서드에 데코레이터를 적용할 때는 self 인자를 고려해야 합니다.
코드 예제
def method_logger(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
print(f"{self.__class__.__name__}.{func.__name__} 호출")
return func(self, *args, **kwargs)
return wrapper
class Calculator:
@method_logger
def add(self, a, b):
return a + b
calc = Calculator()
calc.add(10, 20)
설명
wrapper의 첫 번째 인자로 self를 받아서 인스턴스 메서드에 적용 가능합니다.
7. property_데코레이터
개요
@property는 메서드를 속성처럼 접근할 수 있게 하는 내장 데코레이터입니다.
코드 예제
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def area(self):
return 3.14 * self._radius ** 2
circle = Circle(5)
print(circle.area) # 괄호 없이 접근
설명
area 메서드를 속성처럼 사용할 수 있어서 코드가 더 직관적이고 깔끔해집니다.
8. 여러_데코레이터_체이닝
개요
하나의 함수에 여러 데코레이터를 적용할 수 있으며, 아래에서 위로 실행됩니다.
코드 예제
def bold(func):
def wrapper():
return f"<b>{func()}</b>"
return wrapper
def italic(func):
def wrapper():
return f"<i>{func()}</i>"
return wrapper
@bold
@italic
def text():
return "Hello"
print(text()) # <b><i>Hello</i></b>
설명
@italic이 먼저 적용되고 그 결과를 @bold가 감싸서 HTML 태그가 중첩됩니다.
9. 캐싱_데코레이터_구현
개요
함수 결과를 저장해서 같은 입력에 대해 재계산을 방지하는 메모이제이션 패턴입니다.
코드 예제
def memoize(func):
cache = {}
@wraps(func)
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@memoize
def fibonacci(n):
if n < 2: return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(100))
설명
계산된 결과를 cache 딕셔너리에 저장하여 중복 계산을 막아 성능을 크게 향상시킵니다.
10. 실행_시간_측정_데코레이터
개요
함수의 실행 시간을 자동으로 측정하여 성능 분석에 활용할 수 있습니다.
코드 예제
import time
from functools import wraps
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__}: {end-start:.4f}초")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
slow_function()
설명
함수 실행 전후의 시간을 측정하여 소요 시간을 자동으로 출력합니다.
11. 클래스_데코레이터
개요
함수뿐만 아니라 클래스 전체를 감싸서 기능을 추가할 수 있습니다.
코드 예제
def singleton(cls):
instances = {}
@wraps(cls)
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self):
print("DB 연결")
db1 = Database()
db2 = Database() # 같은 인스턴스
설명
singleton 패턴을 구현하여 클래스의 인스턴스가 하나만 생성되도록 보장합니다.
12. 조건부_데코레이터_실행
개요
특정 조건에서만 데코레이터 기능을 활성화하는 방법입니다.
코드 예제
def debug_mode(enabled=True):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
if enabled:
print(f"DEBUG: {func.__name__} 호출")
return func(*args, **kwargs)
return wrapper
return decorator
@debug_mode(enabled=False)
def process_data(data):
return data * 2
process_data(5) # DEBUG 메시지 없음
설명
enabled 파라미터로 디버그 로깅을 켜고 끌 수 있어서 개발/운영 환경을 쉽게 전환합니다.
마치며
이번 글에서는 Python 데코레이터 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#Python #Decorators #Functions #AdvancedFeatures #MetaProgramming