Python 데코레이터(Decorator)

hodu·2022년 9월 28일
0

python

목록 보기
7/17
post-thumbnail

이번에는 파이썬 데코레이터에 대해 정리해봅시다.

데코레이터란?

데코레이터는 장식하다, 꾸미다라는 뜻의 decorate에 er(or)를 붙인 말로 장식해주는 것, 꾸며주는 것 이라고 생각하면 된다.

Django나 DRF 코드를 작성하다 보면 '@'가 붙어있는 코드를 볼 수가 있는데, 이 @가 바로 데코레이터를 의미한다.
말이 나왔으니 Django 데코레이터 예제를 한번 살펴보자.

from django.views.decorators.http import require_http_methods

@require_http_methods(["GET", "POST"])
def my_view(request):
    # ...
    pass

이 코드는 공식문서에서 볼 수 있다.

중간에 @require_http_methods(["GET", "POST"])가 바로 데코레이터라고 하는 것이고, 이 코드에서는 GET, POST 요청 메서드만 수락해주는 기능이다.

그럼 본격적으로 왜 써야 하는지, 어떻게 구현되어 있는지, 어떻게 동작되는지 확인해 보자.

데코레이터는 왜 쓸까?

  • 내부 수정 없이 추가기능을 구현할 때 사용한다.
    말이 좀 어려운데, 예제를 보면서 익혀보자.

함수의 시작과 끝을 print로 알려주는 함수를 작성해보겠다.

def hello():
	print('hello 함수입니다.')
	print('hello')
	print('hello 함수가 끝났습니다.')


def world():
 	print('world 함수입니다.')
	print('world')
	print('world 함수가 끝났습니다.') 

hello()
world()

이렇게 작성할 수 있을 것이다.
하지만 보다시피 코드 중복이 발생하고 코드 변경이 번거로워진다.

코드를 좀 줄여보자.

def deco(func):
    def wrapper():
        print(func.__name__, '함수 입니다.')
        func()
        print(func.__name__, '함수가 끝났습니다.')
    return wrapper


def hello():
    print('hello')
 
def world():
    print('world')
 
hello_func = deco(hello)    
hello_func()                 
world_func = deco(world)   
world_func()

wrapper라는 클로저를 이용하여 함수의 시작과 끝을 반환할 수 있도록 했다. 함수 안에서 함수를 만들고 반환한다.

(클로저란? 클로저는 자신을 둘러싼 함수 스코프의 상태값을 참조하는데, 이 값은 함수가 메모리에서 사라져도 값이 유지 된다. 더 자세한 내용은 다음 포스팅에서 다뤄보겠다.)

위 코드를 정말 데코레이터 답게 만들어보자면

# 더 간단히 표현할 수 있음
def deco(func):
    def wrapper():
        print(func.__name__, '함수 입니다.')
        func()
        print(func.__name__, '함수가 끝났습니다.')
    return wrapper


@deco
def hello():
    print('hello')
 
@deco
def world():
    print('world')

# trace_hello = deco(hello)
# trace_hello()
hello()
# trace_world = deco(world)   
# trace_world()
world()

데코레이터 문법을 사용하여 작성해 보았다.

좀 더 가독성있고 중복이 사라진 것을 확인할 수 있다.

데코레이터의 단점은 무엇일까?

  • 중첩해서 사용하게 될 경우, 가독성이 떨어지고 디버깅 난이도가 상승한다.
profile
안녕 세계!

0개의 댓글