[파이썬] 데코레이터의 응용

데코레이터는 파이썬에서 매우 유용하게 사용되는 기능 중 하나입니다. 데코레이터는 함수나 클래스를 수정하지 않고도 기능을 확장하거나 추가할 수 있도록 도와줍니다.

이번 포스트에서는 파이썬에서 데코레이터를 활용해 다양한 응용 예제를 살펴보겠습니다.

1. 함수 실행 시간 측정

함수의 실행 시간을 측정하는 기능은 프로그램의 성능 분석이나 최적화에 매우 유용합니다. 데코레이터를 사용하여 함수의 실행 시간을 측정하는 예제를 살펴봅시다.

import time

def measure_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"Function {func.__name__} took {execution_time} seconds to execute")
        return result
    return wrapper

@measure_time
def calculate_sum(n):
    """1부터 n까지의 합을 계산하는 함수"""
    return sum(range(n+1))

result = calculate_sum(10000000)
print(result)

위 예제에서 measure_time 데코레이터 함수는 calculate_sum 함수의 실행 시간을 측정합니다. wrapper 함수는 calculate_sum 함수를 감싸고 있어서 실행 시간을 측정하고 결과를 출력한 뒤에 원래 함수를 호출합니다. 이렇게 데코레이터를 사용하면 함수에서 저렇게 시간 측정 코드를 추가하지 않고도 실행 시간을 측정할 수 있습니다.

2. 로그 출력

디버깅이나 모니터링 목적으로 로그를 출력하는 기능은 매우 중요합니다. 데코레이터를 사용하여 함수의 입력과 출력을 로그로 출력하는 예제를 살펴봅시다.

def log_calls(func):
    def wrapper(*args, **kwargs):
        args_str = ", ".join(repr(arg) for arg in args)
        kwargs_str = ", ".join(f"{key}={repr(value)}" for key, value in kwargs.items())
        signature = f"{func.__name__}({args_str}, {kwargs_str})"
        print(f"Calling {signature}")
        result = func(*args, **kwargs)
        print(f"{signature} returned {result}")
        return result
    return wrapper

@log_calls
def calculate_product(a, b):
    """두 수의 곱을 계산하는 함수"""
    return a * b

result = calculate_product(5, 7)
print(result)

위 예제에서 log_calls 데코레이터 함수는 함수의 호출을 로그로 출력합니다. wrapper 함수에서 함수의 인자와 반환값을 로그로 출력한 뒤에 원래 함수를 호출합니다. 이렇게 데코레이터를 사용하면 함수의 실행 정보를 적절히 로깅할 수 있습니다.

3. 인증 및 권한 확인

웹 애플리케이션에서 특정 기능에 대한 인증 및 권한 검사를 수행해야 할 경우가 많습니다. 데코레이터를 사용하여 인증 및 권한 검사를 자동화하는 예제를 살펴봅시다.

def requires_auth(func):
    def wrapper(*args, **kwargs):
        if not logged_in_user:
            raise Exception("User is not logged in")
        return func(*args, **kwargs)
    return wrapper

def requires_permission(permission):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if permission not in logged_in_user.permissions:
                raise Exception("User does not have the required permission")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@requires_auth
@requires_permission("admin")
def delete_user(user_id):
    """사용자를 삭제하는 함수"""
    # 사용자 삭제 로직

delete_user(123)

위 예제에서 requires_auth 데코레이터 함수는 사용자가 로그인되어 있는지 확인하고, requires_permission 데코레이터 함수는 특정 권한을 가지고 있는지 확인합니다. delete_user 함수는 이 두 데코레이터로 보호되어 사용자 인증 및 권한 검사를 자동으로 수행합니다. 이렇게 데코레이터를 사용하면 인증 및 권한 검사를 간편하게 처리할 수 있습니다.

결론

데코레이터를 사용하면 파이썬 프로그램에서 다양한 기능을 확장하거나 추가할 수 있습니다. 함수 실행 시간 측정, 로그 출력, 인증 및 권한 확인과 같은 다양한 응용 예제를 살펴보았습니다. 데코레이터를 잘 활용하면 코드의 가독성과 확장성을 향상시킬 수 있습니다.