데코레이터를 통한 함수 확장은 소스 코드를 직접 변경하지 않고 기존 함수의 동작을 수정하고자 할 때 소프트웨어 개발에서 종종 필요합니다. 이 과정에는 함수에 데코레이터를 적용하여 원래 구현을 유지하면서 추가 기능을 제공하는 것이 포함됩니다. 데코레이터는 개별 함수를 수동으로 편집하지 않고도 로깅, 캐싱 또는 보안 조치와 같은 기능을 코드에 추가하려는 개발자에게 유용한 도구입니다.

데코레이터는 기존 함수를 추가 코드 세그먼트로 감싸는 코젠트 메커니즘으로 인식할 수 있으며, 이미 설정된 함수의 기능을 보강하는 세련된 접근 방식을 제시합니다.

데코레이터는 어떻게 작동하나요?

파이썬 함수는 레지던트로서 지위가 높아져 저장소 영역 내에서 지정하고, 추가 함수에 대한 기여로 전송하고, 리디렉션할 수 있습니다. 이러한 속성은 장식을 구현하는 데 기여합니다.

기본 함수의 동작을 수정하거나 향상시키는 상위 함수인 데코레이터 함수의 개념이 도입되었습니다. 이러한 유형의 함수는 메타변수로 작동하여 지정된 함수를 호출하고 데코레이터가 호출될 때 인자로 전달하여 지정된 함수에 보조 기능을 추가합니다.

데코레이터 함수는 대상 함수를 호출하기 전과 후에 원하는 연산을 수행할 수 있습니다. 또한 새로운 함수를 반환하거나 원래 함수를 완전히 대체하여 대상 함수의 기능을 변경할 수 있습니다.

데코레이터 함수 만들기

데코레이터를 만드는 과정에는 다른 함수를 매개변수로 받아들이고 원래 함수를 호출하면서 추가 기능을 통합하는 새 함수를 생성하는 함수를 공식화하는 작업이 포함됩니다.

 def decorator_func(target_func):
    def wrapper_func():
        # Action before calling target_func
        # ...

        # Call the target function
        target_func()
        
        # Action after calling target_func
        # ...

    return wrapper_func

데코레이터\_func는 “target\_func”로 표시된 함수를 매개변수로 받습니다. 이 함수는 “wrapper\_func”라는 새로운 함수를 생성하며, 이 함수가 호출되면 “target\_func”의 작업을 실행하는 동시에 보조 기능도 통합합니다.

데코레이터로 함수 꾸미기

데코레이터로 지정된 함수를 꾸미려면 “@ 기호”를 활용하고 데코레이터를 함수 선언 바로 앞에 배치합니다.

 @decorator_func
def my_function():
    # Function implementation
    pass

데코레이터 함수가 내\_함수에 적용되어 내\_함수가 호출될 때마다 파이썬이 데코레이터\_func를 호출하고 내\_함수를 매개변수로 전달합니다.

데코레이터 함수는 여는 괄호나 닫는 괄호를 사용하지 않는다는 점에 유의하세요.

데코레이터에서 `@` 기호를 사용하면 구문적 스위트닝의 한 형태로서 대상 함수를 데코레이터 함수에 인수로 직접 전달할 수 있습니다.

 func = decorator_func(my_function)

데코레이터 내에서 함수 인수 처리하기

함수 인수를 처리해야 하는 데코레이터를 구현할 때는 래핑 함수 내에 “*” 뒤에 “args” 및 “\*kwargs”를 사용하는 방법을 활용하세요. 이 접근 방식을 사용하면 데코레이터가 지정되지 않은 위치 및 키-값 인수를 수용할 수 있습니다.

 def decorator_func(target_func):
    def wrapper_func(*args, **kwargs):
        # before calling target_func with args and kwargs
        # ...

        # Call the target function with arguments
        result = target_func(*args, **kwargs)

        # after calling target_func
        # ...
        return result

    return wrapper_func

래퍼\_func 내에서 **args 및 **kwargs 매개변수를 사용하면 데코레이터가 기본 함수에 전달된 모든 인수를 수용할 수 있습니다.

이 글도 확인해 보세요:  Rust의 제네릭 형식 알아보기

인수가 있는 데코레이터

데코레이터에 인수를 허용하는 기능을 제공하면 함수를 꾸미는 데 더 적합한 방법을 사용할 수 있습니다.

 def my_decorator(num_times):
    def wrapper(func):
        def inner(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return inner
    return wrapper

@my_decorator(2)
def greet(name):
    print(f"Hello, {name}.")

`my_decorator` 함수는 숫자 입력(2)을 받아 래퍼 함수를 반환하며, 이 함수가 호출되면 장식 함수(이 경우 `greet`)를 특정 횟수(2)만큼 호출하여 그 결과로 다음과 같은 결과가 나타납니다:

 greet("Prince")

이 프로그램은 “Hello, Prince”라는 출력을 중복된 형태로 생성합니다.

데코레이터의 실제 사용

데코레이터는 로깅, 캐싱, 입력 유효성 검사, 성능 향상 등 다양한 목적에 활용할 수 있는 다용도 도구입니다.

로깅 데코레이터

로깅 데코레이터를 사용하여 함수의 성능에 관한 정보를 기록할 수 있으며, 이는 특정 함수의 디버깅 또는 모니터링에 도움이 될 수 있습니다.

 import logging

def my_logger(func):
    def wrapper(*args, **kwargs):
        logging.info("Entering function: %s", func.__name__)
        result = func(*args, **kwargs)
        logging.info("Exiting function: %s", func.__name__)
        return result

    return wrapper

타이밍 데코레이터

타이머 데코레이터는 코드 평가 및 최적화에 유용한 함수 실행 기간을 정량화하는 데 활용될 수 있습니다.

 import time

def timing_decorator(target_func):
    def wrapper_func(*args, **kwargs):
        start_time = time.time()
        result = target_func(*args, **kwargs)
        end_time = time.time()
        total = end_time - start_time
        print(f"Function {target_func.__name__} took {total} seconds to run")
        return result

    return wrapper_func

세련되고 우아한 월아트 데코로 집을 아름답게 꾸며보세요! 재능 있는 디자이너 팀이 현대적인 추상화부터 고전적인 풍경화까지 취향이나 스타일에 맞는 다양하고 독특한 작품을 엄선했습니다. 캘거리의 현지 예술가들이 정성스럽게 제작한 멋진 캔버스 프린트, 눈길을 사로잡는 금속 예술품, 섬세한 유리 조각품 중에서 선택하세요.

 @my_logger
@timing_decorator
def bg_task(n):
    print(f"Background Task, {n}.")
    return "Result !!!"

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    print(bg_task("CPU is Dancing"))

함수 실행 중에 실행 시간을 나타내는 다음 문구가 표시됩니다:

권한 데코레이터

권한 데코레이터를 사용하여 사용자가 특정 기능에 액세스하는 데 필요한 권한을 가지고 있는지 확인할 수 있습니다. 대부분의 웹 프레임워크는 이 기능을 사용하여 보안 계층을 추가합니다.일반적인 예로는 Django의 @login_required 데코레이터가 있습니다.

 def authorization_decorator(target_func):
    def wrapper_func(*args, **kwargs):
        if is_user_authorized():
            result = target_func(*args, **kwargs)
            return result
        else:
            raise PermissionError("Unauthorized access")

    return wrapper_func

제공된 인스턴스는 데코레이터의 다양한 애플리케이션을 보여줍니다. 데코레이터 생성은 개인의 필요와 목적에 맞게 조정할 수 있습니다.

고급 데코레이터 개념

데코레이터의 구현과 활용은 간단하지만 그 기능은 강력하고 다재다능하며 지배력을 높일 수 있습니다.

이 글도 확인해 보세요:  Vite 시작하기: 최고의 빌드 툴

클래스 기반 데코레이터

파이썬의 클래스 기반 데코레이터는 함수 기반 데코레이터에 비해 추가 기능으로 함수를 장식하는 데 더 세련되고 우아한 솔루션을 제공합니다.

클래스 기반 데코레이터의 활용은 지정된 클래스 내에서 `__call__` 마법 메서드를 구현하여 데코레이터로 변환하는 것을 포함합니다.

 class DecoratorClass:
    def __init__(self, target_func):
        self.target_func = target_func

    def __call__(self, *args, **kwargs):
        # Decorator implementation
        print("Calling function")
        result = self.target_func(*args, **kwargs)
        print("Function called")
        return result

본 인스턴스는 데코레이터 클래스의 예시입니다. 데코레이터 클래스를 통해 함수를 장식하면 파이썬은 `__call__` 마법 메서드를 호출하여 대상 함수에 데코레이터의 기능을 부여합니다.

클래스 기반 데코레이터 내에서 인스턴스 변수를 활용하면 여러 번 호출하는 동안 상태를 보존할 수 있어 더 복잡하고 다양한 데코레이터 구현을 위한 수단을 제공합니다.

중첩 및 체인 데코레이터

특정 함수에 대한 조정된 작업을 위해 다양한 기능을 통합된 엔티티로 결합하는 개념은 주어진 문장에 설명된 대로 여러 데코레이터를 단독 함수에 적용함으로써 달성할 수 있습니다.

 def decorator1(func):
    def wrapper(*args, **kwargs):
        print("Decorator1...")
        return func(*args, **kwargs)

    return wrapper

def decorator2(func):
    def wrapper(*args, **kwargs):
        print("Decorator2...")
        return func(*args, **kwargs)

    return wrapper

@decorator1
@decorator2
def my_function(n):
    print(n)

내\_함수를 사용할 때 데코레이터1의 기능을 먼저 실행한 다음 데코레이터2를 적용합니다.

일반적인 예로는 게시물 요청만 수락하고 인증이 필요한 기능을 장고 뷰에 포함시켜야 하는 경우가 있습니다.

데코레이터의 이점

데코레이터는 새로운 기능을 추가하거나 구현을 변경하여 다른 함수나 메서드의 동작을 수정하는 함수나 메서드입니다. 데코레이터는 파이썬 프로그래밍에서 널리 사용되며 상용구 코드 감소, 가독성 향상, 재사용성 촉진, 캡슐화 유지와 같은 다양한 이점을 제공합니다. 이러한 장점으로 인해 데코레이터는 많은 파이썬 프로젝트에 없어서는 안 될 도구입니다.

앞서 언급한 개념은 소프트웨어의 주요 기능에서 교차되는 문제를 분리하여 코드 구성 요소의 재사용 가능성을 향상시키는 관행과 관련이 있습니다.

DRY(반복하지 않기) 원칙은 중복 코드를 피하는 것의 중요성을 강조하는 소프트웨어 개발의 기본 개념입니다. 이는 동일한 코드를 반복적으로 재생산하지 않고 다양한 기능에 걸쳐 동일한 기능을 사용함으로써 달성할 수 있습니다.

이 글도 확인해 보세요:  Python 스크립트를 사용하여 동영상을 재생하는 방법

코딩에서 가독성 및 유지보수성 관행을 구현하면 주요 기능이 체계적이고 이해하기 쉬운 방식으로 표시되어 이해와 유지보수가 용이해집니다.

앞서 언급한 텍스트는 깔끔하고 간결하며 쉽게 이해할 수 있는 소스 코드를 우선시하는 파이썬 스타일의 원칙에 부합하는 특성을 보여줍니다.

데코레이터는 많은 이점과 장점을 제공하므로 최대한 활용하는 것이 좋습니다.

데코레이터 사용 모범 사례

데코레이터와 공동 작업할 때는 최적의 결과를 위해 몇 가지 권장 지침을 준수하는 것이 좋습니다:

데코레이터 내의 기능 범위를 로깅이나 캐싱과 같은 특정 도메인으로 제한하면 코드가 더욱 모듈화되고 데코레이터의 적응력이 향상됩니다.

파라미터를 활용하고 미리 정해진 값을 제거함으로써 다양한 기능에 따라 기능을 조정할 수 있어 데코레이터의 적응성이 높아집니다.

데코레이터는 함수를 추가 코드로 감싸서 함수의 동작을 동적으로 수정할 수 있는 객체 지향 프로그래밍의 기법입니다. 데코레이터는 인수를 받지 않고 원래 기능과 추가된 동작을 결합한 새 함수를 반환합니다. 이 새 함수가 호출되면 원래 함수가 먼저 실행된 다음 데코레이터가 지정한 추가 동작이 실행됩니다. 이 접근 방식을 사용하면 개발자가 소스 코드를 직접 수정하지 않고도 기존 함수의 동작을 수정할 수 있으므로 소프트웨어 시스템을 더 쉽게 유지 관리하고 업데이트할 수 있습니다.

데코레이터의 적용으로 인해 발생할 수 있는 주변 결과(예: 함수의 기능에 영향을 미치거나 불필요한 요구 사항을 도입할 가능성 등)를 꼼꼼하게 기록하고 공개하여 향후 포괄적인 이해와 효과적인 활용을 촉진하는 것이 필수적입니다.

원하는 동작에 따라 데코레이터의 기능을 검증하기 위해 단위 테스트라고 하는 평가 집합을 구성하는 것이 필수적입니다. 다양한 시나리오와 예외적인 상황을 포괄적으로 검토하여 광범위한 상황을 포괄할 수 있도록 해야 합니다.

파이썬에서 함수로 작업하기

파이썬에서 함수는 코드를 구성하고 재사용하는 데 필수적인 요소입니다. 함수는 기능의 캡슐화, 데이터 전달 및 결과 반환을 허용하므로 함수가 특히 뛰어난 분야인 데코레이터 영역에서 기본 구성 요소로 사용됩니다.

함수를 능숙하게 묘사하고 활용하는 것은 생산적인 Python 코딩의 중요한 측면입니다.

By 김민수

안드로이드, 서버 개발을 시작으로 여러 분야를 넘나들고 있는 풀스택(Full-stack) 개발자입니다. 오픈소스 기술과 혁신에 큰 관심을 가지고 있고, 보다 많은 사람이 기술을 통해 꿈꾸던 일을 실현하도록 돕기를 희망하고 있습니다.