Updated Feb 6, 2026
데코레이터란 무엇인가?
데코레이터(Decorator)는 함수나 클래스를 수정하지 않고 기능을 추가하거나 변경할 수 있는 파이썬의 강력한 문법입니다. @ 기호로 시작하는 이 패턴은 코드의 재사용성을 높이고, 중복을 제거하며, 가독성을 향상시킵니다.
데코레이터는 본질적으로 “함수를 받아서 함수를 반환하는 함수”입니다.
기본 구조를 살펴보겠습니다.
def my_decorator(func):
def wrapper(*args, **kwargs):
print("함수 실행 전")
result = func(*args, **kwargs)
print("함수 실행 후")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"안녕하세요, {name}님!")
say_hello("김철수")
# 출력:
# 함수 실행 전
# 안녕하세요, 김철수님!
# 함수 실행 후
내장 데코레이터 마스터하기
파이썬은 실무에서 자주 사용하는 내장 데코레이터를 제공합니다.
@property: 속성처럼 사용하는 메서드
@property는 메서드를 속성처럼 접근할 수 있게 만들어 캡슐화를 구현합니다.
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value < 0:
raise ValueError("반지름은 양수여야 합니다")
self._radius = value
@property
def area(self):
return 3.14159 * self._radius ** 2
c = Circle(5)
print(c.radius) # 5 (메서드지만 속성처럼 접근)
print(c.area) # 78.53975
c.radius = 10 # setter 호출
@staticmethod와 @classmethod
두 데코레이터의 차이를 명확히 이해하는 것이 중요합니다.
| 데코레이터 | 첫 번째 인자 | 용도 | 인스턴스 접근 | 클래스 접근 |
|---|---|---|---|---|
@staticmethod |
없음 | 유틸리티 함수 | 불가 | 불가 |
@classmethod |
cls | 팩토리 메서드, 클래스 변수 접근 | 불가 | 가능 |
class DateParser:
default_format = "%Y-%m-%d"
@staticmethod
def is_valid_date(date_string):
# 단순 유틸리티 함수
return len(date_string) == 10 and date_string[4] == '-'
@classmethod
def from_timestamp(cls, timestamp):
# 클래스 생성자 역할 (팩토리 메서드)
from datetime import datetime
return cls(datetime.fromtimestamp(timestamp))
@functools.wraps: 메타데이터 보존
데코레이터를 만들 때 원본 함수의 메타데이터를 보존하려면 @wraps를 사용해야 합니다.
from functools import wraps
def retry(max_attempts=3):
def decorator(func):
@wraps(func) # 원본 함수의 __name__, __doc__ 보존
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
print(f"재시도 {attempt + 1}/{max_attempts}")
return wrapper
return decorator
실전 커스텀 데코레이터
성능 측정 데코레이터
import time
from functools import wraps
def measure_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__} 실행 시간: {elapsed:.4f}초")
return result
return wrapper
@measure_time
def slow_function():
time.sleep(2)
return "완료"
권한 검사 데코레이터
웹 애플리케이션에서 자주 사용하는 패턴입니다.
def require_auth(permission):
def decorator(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if not hasattr(user, 'permissions'):
raise PermissionError("권한 정보가 없습니다")
if permission not in user.permissions:
raise PermissionError(f"{permission} 권한이 필요합니다")
return func(user, *args, **kwargs)
return wrapper
return decorator
@require_auth('admin')
def delete_user(user, target_id):
print(f"사용자 {target_id} 삭제")
캐싱 데코레이터
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)) # 즉시 계산 (캐시 덕분)
클래스 데코레이터
함수뿐만 아니라 클래스 전체를 데코레이트할 수도 있습니다.
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 DatabaseConnection:
def __init__(self):
print("DB 연결 생성")
db1 = DatabaseConnection() # "DB 연결 생성" 출력
db2 = DatabaseConnection() # 출력 없음 (같은 인스턴스)
print(db1 is db2) # True
데코레이터 체이닝
여러 데코레이터를 동시에 적용할 수 있습니다. 아래에서 위로 적용됩니다.
@retry(max_attempts=3)
@measure_time
@require_auth('user')
def api_call(user, endpoint):
# 실제 실행 순서:
# 1. require_auth 검사
# 2. measure_time으로 시간 측정 시작
# 3. retry로 최대 3번 재시도
pass
데코레이터 활용 시 주의사항
@wraps항상 사용: 디버깅과 문서화를 위해 필수- 과도한 중첩 피하기: 3개 이상 체이닝은 가독성 저하
- 상태 관리 주의: 데코레이터 내부 변수는 모든 호출에서 공유됨
- 인자가 있는 데코레이터: 3중 중첩 함수 구조 필요 (데코레이터 팩토리 → 데코레이터 → wrapper)
마무리
데코레이터는 파이썬의 핵심 기능으로, 코드의 재사용성, 가독성, 유지보수성을 극대화합니다. 핵심 포인트를 정리하면:
@property로 깔끔한 인터페이스 설계@staticmethod/@classmethod로 명확한 책임 분리@wraps로 메타데이터 보존 필수- 커스텀 데코레이터로 횡단 관심사(로깅, 캐싱, 권한) 분리
- 클래스 데코레이터로 싱글톤 등 패턴 구현
실무에서 반복되는 패턴을 발견하면 데코레이터로 추상화하는 습관을 들이세요. 처음엔 어렵게 느껴지지만, 익숙해지면 파이썬 코드의 품질이 한 단계 도약할 것입니다.
Did you find this helpful?
☕ Buy me a coffee
Leave a Reply