python / / 2024. 8. 18. 19:52

python에서 데코레이터(decorator)란?

Python에서 데코레이터(Decorator)는 함수나 메서드에 추가적인 기능을 부여하는 강력한 도구이다. 데코레이터는 코드의 재사용성을 높이고, 함수의 동작을 동적으로 변경할 수 있게 해준다.


1. 데코레이터란?

데코레이터는 다른 함수를 수정하지 않고, 그 함수에 새로운 기능을 추가할 수 있는 방법이다. 간단히 말해, 데코레이터는 함수를 감싸는(wrapper) 함수로, 원래의 함수에 새로운 기능을 추가하거나, 함수의 실행 결과를 수정할 수 있다. 데코레이터는 함수나 메서드를 매개변수로 받아서 새로운 함수를 반환하는 클로저 패턴을 사용한다.

2. 데코레이터의 기본 구조

데코레이터를 정의하는 기본 구조는 다음과 같습니다:

def my_decorator(func):
    def wrapper(*args, **kwargs):
        # 함수 실행 전
        result = func(*args, **kwargs)
        # 함수 실행 후
        return result
    return wrapper

여기서 my_decorator는 데코레이터 함수이며, wrapper 함수는 원래의 func 함수를 감싸는 함수이다. wrapper 함수 내에서 func를 호출하고, 그 결과를 반환한다. 데코레이터는 주로 @ 문법을 사용하여 적용된다.

3. 데코레이터의 사용 예시

간단한 데코레이터 예시를 통해 데코레이터의 동작을 알아보자.

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

@simple_decorator
def say_hello():
    print("Hello, World!")

say_hello()

출력:

함수 실행 전
Hello, World!
함수 실행 후

위 코드에서 @simple_decoratorsay_hello 함수에 데코레이터를 적용한다. say_hello 함수가 호출될 때, 실제로는 wrapper 함수가 실행되며, 그 안에서 say_hello 함수가 호출된다. 이를 통해 함수 실행 전후로 추가적인 동작을 삽입할 수 있다.

4. 데코레이터의 활용 사례

4.1. 로깅 데코레이터

로깅(logging)은 함수가 호출될 때마다 그 동작을 기록하는 것이다. 로깅 데코레이터는 함수를 호출할 때마다 로그를 남기게 한다.

def logging_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function {func.__name__} with arguments {args} and {kwargs}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} returned {result}")
        return result
    return wrapper

@logging_decorator
def add(a, b):
    return a + b

result = add(5, 3)

출력:

Calling function add with arguments (5, 3) and {}
Function add returned 8

이 데코레이터는 함수의 이름, 인자, 그리고 반환값을 출력하여 함수의 동작을 추적할 수 있다.

4.2. 실행 시간 측정 데코레이터

함수의 실행 시간을 측정하여 성능을 분석할 수 있다.

import time

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

@timer_decorator
def slow_function():
    time.sleep(2)
    print("Finished slow function")

slow_function()

출력:

Finished slow function
Function slow_function took 2.0023 seconds

이 데코레이터는 함수가 얼마나 오래 실행되는지를 측정한다. 성능 최적화가 필요한 코드에서 매우 유용하다.

4.3. 권한 검사 데코레이터

권한 검사 데코레이터는 사용자가 특정 기능에 접근할 수 있는지를 확인하는 데 사용된다.

def requires_permission(permission):
    def decorator(func):
        def wrapper(user, *args, **kwargs):
            if user.get("permissions", []) and permission in user["permissions"]:
                return func(user, *args, **kwargs)
            else:
                print(f"User {user['name']} does not have permission: {permission}")
                return None
        return wrapper
    return decorator

@requires_permission("admin")
def delete_database(user):
    print("Database deleted!")

user = {"name": "Alice", "permissions": ["user"]}
delete_database(user)

admin_user = {"name": "Bob", "permissions": ["admin"]}
delete_database(admin_user)

출력:

User Alice does not have permission: admin
Database deleted!

이 데코레이터는 사용자가 특정 권한을 가지고 있는지 확인하고, 해당 권한이 없으면 함수의 실행을 차단한다.

5. 파라미터가 있는 데코레이터

지금까지 살펴본 데코레이터는 함수에 추가적인 기능을 제공했다. 하지만, 때로는 데코레이터 자체에 파라미터를 전달해야 할 때가 있다. 이를 위해 데코레이터 함수를 또 다른 함수로 감싸는 방식으로 구현할 수 있다.

파라미터를 받는 데코레이터 예시

def repeat(num_times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

출력:

코드 복사
Hello, Alice!
Hello, Alice!
Hello, Alice!

이 예제에서 @repeat(3) 데코레이터는 greet 함수를 3번 반복 실행하도록 한다.

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유