데코레이터 사용하기

Tasker_Jang·2026년 2월 27일

1. 데코레이터란?

데코레이터는 함수를 감싸는 형태로 구성되어, 기존 함수를 수정하지 않으면서 추가 기능을 구현할 때 사용합니다. 이전에 배운 클로저를 기반으로 동작합니다.

# 데코레이터 없이 — 함수를 직접 감싸는 방식
def my_decorator(func):
    def wrapper():
        print("함수 실행 전")
        func()
        print("함수 실행 후")
    return wrapper

def hello():
    print("Hello!")

hello = my_decorator(hello)  # 감싸기
hello()
# 함수 실행 전
# Hello!
# 함수 실행 후

@ 문법을 사용하면 위 코드를 훨씬 간결하게 표현할 수 있습니다.

def my_decorator(func):
    def wrapper():
        print("함수 실행 전")
        func()
        print("함수 실행 후")
    return wrapper

@my_decorator          # hello = my_decorator(hello)와 동일
def hello():
    print("Hello!")

hello()
# 함수 실행 전
# Hello!
# 함수 실행 후

2. 매개변수와 반환값을 처리하는 데코레이터

원본 함수의 매개변수와 반환값을 그대로 처리하려면 wrapper 함수에도 매개변수를 지정하고 반환값을 전달해줘야 합니다.

def decorator(func):
    def wrapper(x, y):           # 원본 함수와 동일한 매개변수
        print(f"입력값: {x}, {y}")
        result = func(x, y)
        print(f"반환값: {result}")
        return result            # 반환값 전달
    return wrapper

@decorator
def add(x, y):
    return x + y

add(3, 5)
# 입력값: 3, 5
# 반환값: 8

3. 가변 인수 함수에 사용하는 데코레이터

어떤 함수에든 범용으로 적용할 수 있는 데코레이터를 만들려면 *args**kwargs를 활용합니다.

def universal_decorator(func):
    def wrapper(*args, **kwargs):    # 어떤 인수든 받을 수 있음
        print(f"함수명: {func.__name__}")
        print(f"위치 인수: {args}")
        print(f"키워드 인수: {kwargs}")
        result = func(*args, **kwargs)
        return result
    return wrapper

@universal_decorator
def introduce(name, age, city="서울"):
    print(f"이름: {name}, 나이: {age}, 도시: {city}")

introduce("홍길동", 25, city="부산")
# 함수명: introduce
# 위치 인수: ('홍길동', 25)
# 키워드 인수: {'city': '부산'}
# 이름: 홍길동, 나이: 25, 도시: 부산

4. 매개변수가 있는 데코레이터

데코레이터 자체에 매개변수를 전달하려면 데코레이터를 반환하는 함수를 한 겹 더 감쌉니다.

def repeat(count):               # 데코레이터 매개변수
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(count):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)                       # 함수를 3번 반복 실행
def hello():
    print("Hello!")

hello()
# Hello!
# Hello!
# Hello!

5. 클래스로 데코레이터 만들기

함수 대신 클래스로 데코레이터를 만들 수도 있습니다. __init__에서 함수를 받고, __call__에서 추가 기능을 구현합니다.

class MyDecorator:
    def __init__(self, func):
        self.func = func         # 원본 함수 저장

    def __call__(self, *args, **kwargs):   # 호출 시 실행
        print("함수 실행 전")
        result = self.func(*args, **kwargs)
        print("함수 실행 후")
        return result

@MyDecorator
def hello():
    print("Hello!")

hello()
# 함수 실행 전
# Hello!
# 함수 실행 후

클래스로 매개변수가 있는 데코레이터 만들기

매개변수가 있는 클래스 데코레이터는 __init__에서 매개변수를 받고, __call__에서 함수를 받아 wrapper를 반환합니다.

class Repeat:
    def __init__(self, count):       # 데코레이터 매개변수 받기
        self.count = count

    def __call__(self, func):        # 원본 함수 받기
        def wrapper(*args, **kwargs):
            for _ in range(self.count):
                result = func(*args, **kwargs)
            return result
        return wrapper

@Repeat(3)
def hello():
    print("Hello!")

hello()
# Hello!
# Hello!
# Hello!

6. 실전 활용 — 디버깅용 데코레이터

데코레이터는 함수의 실행 시간을 측정하거나 호출 정보를 로깅하는 디버깅 목적으로 자주 활용됩니다. 기존 함수를 전혀 수정하지 않아도 되기 때문에 특히 유용합니다.

import time

def timer(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)
    print("작업 완료!")

slow_function()
# 작업 완료!
# [slow_function] 실행 시간: 1.0012초

정리

데코레이터 유형구현 방식핵심 포인트
기본 데코레이터wrapper 함수@데코레이터명
매개변수·반환값 처리wrapper(*args, **kwargs)return result 필수
매개변수 있는 데코레이터함수 3중 중첩@데코레이터(값)
클래스 데코레이터__init__ + __call____call__이 wrapper 역할
클래스 + 매개변수__init__(매개변수) + __call__(함수)두 단계로 분리
profile
ML Engineer 🧠 | AI 모델 개발과 최적화 경험을 기록하며 성장하는 개발자 🚀 The light that burns twice as bright burns half as long ✨

0개의 댓글