AboutPython

[Python] 데코레이터(Decorator)

scone 2025. 4. 28. 18:55

개요

테디 노트님 Decorator 강의를 너무 재밌게 봐서 이렇게 블로그 글로 다시 작성하게 되었습니다.

https://www.youtube.com/watch?v=03r7sloAyOY

 

1. func을 받아서, wrap을 씌워서 뭔가를 처리를 해주고 ( = wrapper)

2. 사용자가 호출할 시에는, 다른 코드 수정 없이 그냥 평소 처럼 func을 호출

3. 그럼 적용되는 게 Decorator인 것 같습니다.

 

wrapper를 담고 있는 decorator만 만들어주면,

decorator 기능에 대해 서로 다른 여러 func에 적용할 수 있습니다. (재사용성)

 

다시 말해서,

함수 호출 부분 코드는 전혀 건들지 않은 상태에서

함수 구현부만 수정하면, 사용자에게 색다른 경험을 선사할 수 있다는 겁니다.

 

이해를 돕기 위한 설명 코드

# func을 받아서 wrapping
def my_decorator(func):
    def wrapper():
        print("함수 호출 전")
        func()
        print("함수 호출 후")

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

# 기존 func에 decorator를 한 func을 덮어 씌움
say_hello = my_decorator(say_hello)

# 사용자는 평소 처럼 say_hello()를 호출
say_hello()

'''
함수 호출 전
안녕하세요!
함수 호출 후
'''

 

실제 decorator

def my_decorator(func):
    def wrapper():
        print("함수 호출 전")
        func()
        print("함수 호출 후")
    
    return wrapper

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

'''
함수 호출 전
안녕하세요!
함수 호출 후
'''

 

 

사례

1. func 실행 전에 무언가를 하는 경우

2. func 실행 후에 무언가를 하는 경우

3. func을 변형하는 경우

 

위 세가지로 Decorator의 사용을 나누는 것 같습니다.

 

 

Logging

import time

def timing_decorator(fucn):
    def wrapper(*arg, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        
        print(
            f"[알림] 함수명: <{func.__name__}> 실행에 {end_time - start_time:.6f} 초 소요되었습니다.")
        return result
    return wrapper

@timing_decorator
def foo(n):
    ...
    return ...

 

Valid Check

중복 데코레이터도 가능합니다.

def valid_positive(func):
    def wrapper(arg):
        if arg <0:
            raise ValueError("인자는 0보다 커야 합니다.")
        return func(arg)
    return wrapper

def valid_integer(func):
    def wrapper(arg):
        if not isinstance(arg, int):
            raise ValueError("인자는 정수여야 합니다.")
        return func(arg)
    return wrapper

@valid_positive
@valid_integer
def process_number(num):
    print(f"숫자 {num}은 자연수")

 

Authentification

def auth_decorator(func):
    def wrapper(user):
        if user.is_authenticated:
            return func(user)
        else:
            raise PermissionError("로그인이 필요합니다.")

@auth_decorator
def view_profile(user):
    # 프로필 조회 로직

 

Path Operation Decorators

URL 경로와 HTTP 메서드 매핑

  • @app.get(path)
  • @app.post(path)
  • @app.put(path)
  • @app.delete(path)
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello World"}

 

 

Reference

- https://www.youtube.com/watch?v=03r7sloAyOY

- https://fastapi.tiangolo.com/ko/tutorial/first-steps/#_8

- https://smart-worker.tistory.com/48