[파이썬] 데코레이터 패턴과 객체 동적 확장

데코레이터 패턴은 객체 지향 소프트웨어 디자인 패턴 중 하나로, 객체의 동작을 확장하거나 수정하지 않고도 객체의 기능을 추가하거나 변경할 수 있는 방법을 제공합니다. 이 패턴은 객체를 래핑하고, 런타임에 동적으로 기능을 추가하거나 수정함으로써 객체의 동작을 확장합니다.

Python은 데코레이터 패턴을 구현하기 위해 특별한 문법과 기능을 제공합니다. 먼저, 데코레이터 함수는 다른 함수를 인자로 받아 기능을 추가하고 반환하는 함수입니다. 이런 데코레이터 함수는 @ 기호를 사용하여 적용될 함수 위에 표시됩니다.

데코레이터 패턴의 예제

다음은 데코레이터 패턴을 사용하여 객체에 기능을 동적으로 추가하는 예제 코드입니다.

def logging_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function: {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

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

result = add_numbers(3, 5)
print(result)  # 8

위의 예제에서 logging_decorator라는 데코레이터 함수는 add_numbers 함수를 감싸고 있습니다. 데코레이터 함수는 wrapper라는 함수를 정의하고, 이 함수 내부에서 전달받은 함수를 호출하기 전에 “Calling function: [함수명]”이라는 메시지를 출력합니다. 그리고 실제 함수를 실행한 뒤 결과값을 반환합니다.

@logging_decorator라인은 add_numbers 함수 위에 데코레이터를 적용하는 구문입니다. 런타임에 add_numbers 함수가 호출될 때, logging_decorator 함수가 add_numbers 함수로 대체되어 호출됩니다. 이를 통해 add_numbers 함수의 동작을 확장하는 것이 가능해집니다.

위의 예제를 실행하면 8이 출력됩니다. 그리고 추가로 “Calling function: add_numbers”라는 로깅 메시지도 출력됩니다.

데코레이터 패턴의 이점

데코레이터 패턴은 많은 이점을 제공합니다:

  1. 확장성: 객체에 동적으로 기능을 추가하거나 수정할 수 있으므로, 기능의 변화에 유연하게 대응할 수 있습니다.
  2. 단일 책임 원칙 (Single Responsibility Principle, SRP): 기능을 데코레이터로 분리하여, 객체의 주요 동작과 실제 기능을 분리할 수 있습니다.
  3. 재사용성: 데코레이터는 독립적인 객체로 존재하므로, 다른 객체에도 동일한 기능을 적용할 수 있습니다.
  4. 원본 객체의 수정 없음: 데코레이터는 객체를 감싸기만 하고, 기존 객체의 동작을 수정하지 않습니다.

마무리

데코레이터 패턴은 객체 지향 소프트웨어 디자인에서 중요한 역할을 하는 패턴 중 하나입니다. Python의 데코레이터는 다른 함수를 인자로 받아 기능을 추가하거나 수정할 수 있도록 도와줍니다. 이를 통해 객체의 동작을 확장하고, 코드의 가독성과 재사용성을 높일 수 있습니다.