본문 바로가기
개발 언어/Python

파이썬 고급 1강: 데코레이터의 마법: 함수와 클래스 변경하기

by 주호파파 2025. 5. 26.
728x90
반응형

 

파이썬 고급 1강: 데코레이터의 마법

함수와 클래스 변경하기

1 개요 및 중요성

데코레이터(Decorator)는 파이썬에서 가장 우아하고 강력한 기능 중 하나입니다. @ 기호로 시작하는 이 마법같은 문법은 기존 함수나 클래스의 코드를 수정하지 않고도 그들의 동작을 확장하거나 변경할 수 있게 해줍니다.

로깅, 권한 검사, 성능 측정, 캐싱 등 횡단 관심사(Cross-cutting Concerns)를 처리할 때 데코레이터를 사용하면 코드의 중복을 줄이고 관심사를 깔끔하게 분리할 수 있습니다.

💡 핵심 아이디어

데코레이터 = 함수를 받아서 새로운 함수를 반환하는 함수

2 데코레이터의 작동 원리

기본 구조 이해하기

데코레이터는 본질적으로 고차 함수(Higher-order Function)입니다. 다른 함수를 인자로 받아서 새로운 함수를 반환하는 함수죠.


# 데코레이터 없이 함수 감싸기
def my_decorator(func):
    def wrapper():
        print("함수 실행 전")
        result = func()
        print("함수 실행 후")
        return result
    return wrapper

def say_hello():
    print("안녕하세요!")

# 수동으로 데코레이팅
say_hello = my_decorator(say_hello)
                    

@ 문법 사용하기

파이썬의 @ 문법은 위의 과정을 더 우아하게 만들어줍니다:


@my_decorator
def say_hello():
    print("안녕하세요!")

# 위는 아래와 완전히 동일합니다:
# say_hello = my_decorator(say_hello)
                    

3 매개변수가 있는 함수 다루기

실제로는 함수들이 다양한 매개변수를 가지므로, *args**kwargs를 사용해야 합니다:


def my_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"함수 {func.__name__} 실행 중...")
        result = func(*args, **kwargs)
        print(f"함수 {func.__name__} 완료!")
        return result
    return wrapper

@my_decorator
def greet(name, greeting="안녕"):
    print(f"{greeting}, {name}님!")
                    

데코레이터 실습: 간단한 타이머 구현

이번 강의에서 학습한 내용을 바탕으로 함수의 실행 시간을 측정하는 @timer 데코레이터를 직접 만들어보겠습니다.


import time
import functools

def timer(func):
    """함수 실행 시간을 측정하는 데코레이터"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        print(f"⏰ 함수 '{func.__name__}' 시작...")
        
        # 실제 함수 실행
        result = func(*args, **kwargs)
        
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"✅ 함수 '{func.__name__}' 완료! 실행 시간: {execution_time:.4f}초")
        
        return result
    return wrapper

# == 사용 예시 ==

@timer
def slow_calculation(n):
    """느린 계산을 시뮬레이션하는 함수"""
    print(f"  📊 {n}까지 숫자 합계 계산 중...")
    total = 0
    for i in range(n + 1):
        total += i
        # 의도적으로 느리게 만들기
        time.sleep(0.0001)
    return total

@timer
def quick_greeting(name):
    """빠른 인사 함수"""
    message = f"안녕하세요, {name}님! 🎉"
    print(f"  💬 {message}")
    return message
                    

코드 실행 방법 및 결과

위 코드를 Python 파일에 저장하고 다음과 같이 실행해보세요:


# 함수 실행 테스트
if __name__ == "__main__":
    print("=== 데코레이터 테스트 시작 ===")
    
    # 빠른 함수 테스트
    result1 = quick_greeting("김개발")
    
    print()  # 줄바꿈
    
    # 느린 함수 테스트
    result2 = slow_calculation(1000)
    print(f"  📈 계산 결과: {result2}")
                    

💻 예상 출력 결과:

=== 데코레이터 테스트 시작 ===
⏰ 함수 'quick_greeting' 시작...
  💬 안녕하세요, 김개발님! 🎉
✅ 함수 'quick_greeting' 완료! 실행 시간: 0.0001초

⏰ 함수 'slow_calculation' 시작...
  📊 1000까지 숫자 합계 계산 중...
✅ 함수 'slow_calculation' 완료! 실행 시간: 0.1205초
  📈 계산 결과: 500500

🔍 코드 포인트 설명:

  • @functools.wraps(func): 원본 함수의 메타데이터를 보존
  • time.time(): 현재 시간을 초 단위로 반환
  • *args, **kwargs: 모든 종류의 매개변수를 받을 수 있도록 함
  • 함수 실행 전후로 시간을 측정하여 실행 시간 계산

4 실제 활용 사례

🗂️ 로깅 데코레이터


def log_calls(func):
    def wrapper(*args, **kwargs):
        print(f"호출: {func.__name__}")
        return func(*args, **kwargs)
    return wrapper
                            

🔒 권한 검사 데코레이터


def require_auth(func):
    def wrapper(*args, **kwargs):
        if not user_authenticated():
            raise PermissionError
        return func(*args, **kwargs)
    return wrapper
                            

📝 마무리

이번 강의에서는 파이썬 데코레이터의 기본 개념부터 실제 활용까지 살펴보았습니다. 데코레이터는 코드의 재사용성을 높이고, 관심사를 깔끔하게 분리할 수 있는 강력한 도구입니다.

💡 핵심 요약:

  • 데코레이터는 함수를 받아서 새로운 함수를 반환하는 고차 함수
  • @ 문법으로 깔끔하게 적용 가능
  • *args, **kwargs로 모든 함수에 적용 가능
  • 로깅, 권한 검사, 성능 측정 등 다양한 용도로 활용

다음 강의에서는 제너레이터와 이터레이터를 다루며, 메모리 효율적인 프로그래밍 기법에 대해 학습하겠습니다.

728x90
반응형