이미지 로딩 중...

Python 데코레이터 완벽 가이드 - 슬라이드 1/13
C

CodeDeck AI

2025. 11. 8. · 1 Views

Python 데코레이터 완벽 가이드

파이썬 데코레이터의 기초부터 고급 활용까지 단계별로 학습합니다. 함수 데코레이터, 클래스 데코레이터, 파라미터가 있는 데코레이터 등 실무에서 자주 사용되는 패턴을 다룹니다.


카테고리:Python
언어:Python
난이도:intermediate
메인 태그:#Python
서브 태그:
#Decorators#Functions#AdvancedFeatures#MetaProgramming

들어가며

이 글에서는 Python 데코레이터 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. 기본_데코레이터_개념
  2. 함수_인자를_받는_데코레이터
  3. 파라미터가_있는_데코레이터
  4. functools_wraps_활용
  5. 클래스_기반_데코레이터
  6. 클래스_메서드_데코레이터
  7. property_데코레이터
  8. 여러_데코레이터_체이닝
  9. 캐싱_데코레이터_구현
  10. 실행_시간_측정_데코레이터
  11. 클래스_데코레이터
  12. 조건부_데코레이터_실행

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

#Python#Decorators#Functions#AdvancedFeatures#MetaProgramming

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.