[Django] Decorator 를 사용해서 Django view 꾸며보기

msung99·2023년 8월 1일
0
post-thumbnail

장식자(Decorators)

장식자(Decorators) 란 어떤 함수를 감싸는 (Wrapping) 함수를 의미합니다. 함수를 Wrapping 하는 기법으로 반복되는 코드를 줄일 수 있다는 장점이 있습니다. 물론 함수를 사용해서 줄일 수 있지만, Decorator의 사용성이 더 좋다고 할 수 있습니다. (class와 결합하여 사용 가능하기 때문이죠!)

예시

def login_required(func):
    def wrap(): #wrapping 함수                              (1)
        if user is None:
               return redirect('/login')
        return func()                                       (2)
    return wrap

(1) 에서는 wrap 함수에서 조건을 검사한 후, 조건을 통과했다면 func를 호출하도록 함수를 정의합니다. 다음으로 (2) 에서는 정의된 wrap 함수를 호출합니다.

@login_required                           (1)
def test_func():
    print('Do something')

(1) 처럼 Decorator를 지정해주면 test_func를 실행하기 전에 먼저 login_required를 검사하도록 할 수 있습니다. 다시 말해, login_required(test_func)가 실행됩니다.

클래스 CBV 기반 감싸기 방법

한 가지 더 살펴봅시다. 장식자를 사용하지 않고도 동일한 기능을 수행하게 하는 방법이 여러 가지 있습니다. 아래처럼 클래스를 상속하거나 아예 CBV를 파라미터로 감싸는 방법도 있습니다.

# views.py
class PostListView(LoginRequiredMixin, ListView): # LoginRequiredMixin 클래스 상속
    model = Post
    paginate_by = 10
    
post_list = PostListView.as_view()

# 파라미터로 전달
# post_list = login_required(ListView.as_view(model=Post, paginate_by=10))

def test_func():
  if user is None:                   # login 여부를 확인
    return redirect('/login')    # login 되어있지 않은 경우 login page로 redirect
  print('Do something')          # login이 되어 있는 경우 실행


def test_func2():
  if user is None:
    return redirect('/login')
  print('Do something2')

..... * 100                      # 이런 함수가 100여개가 있는 경우를 가정

위와 같은 예시는 쇼핑몰 사이트에서 흔하게 찾아볼 수 있습니다. 예를 들어 상품을 장바구니에 담을 때, 담긴 장바구니를 확인할 때, 장바구니에 있는 물품을 구매할 때 등과 같이 개인의 정보를 확인하려고 하는 경우 login 여부를 확인합니다.

따라서 굉장히 많은 경우 로그인을 확인하는 로직(if문)이 사용됩니다. 기능이 100개가 있는 경우에 100번의 login 로직을 사용해야하기 때문에 코드가 길어지고 복잡해집니다. 위와 같은 예시는 간단한 예시이기 때문에 느껴지지 않으실 수 있지만 다른 로직이 10줄 이상만 되더라도 굉장히 복잡해보입니다.

따라서 우리는 이런 길고 복잡한 코드를 피하기 위해서 decorator(데코레이터)를 사용합니다.

def login_required(func):   # 함수를 인자 값으로 받음(밑을 예로 들면 test_func()을 인자 값으로 받음)
    def wrap():                     # wrap() 을 실행, 만약 user가 로그인을 안했으면 로그인 페이지로 돌려줌
        if user is None:                 
            return redirect('/login')
        return func()                     # 유저가 로그인 상태면 인자값으로 받았던 함수를 실행함
    return wrap                           # 그 결과 값을 출력함


@login_required
def test_func():
    print('Do something')

@login_required
def test_func2():
    print('Do something2')

위의 예시가 decorator를 사용한 예시입니다.

우선, login 기능을 만든 후에 각 기능들에 login 기능을 한 줄로 붙여주는 것입니다. 이렇게 할 경우 무엇이 필요한지 바로바로 알게 되고, 길었던 코드도 짧아지니 관리하기가 더욱 수월해집니다.


참고

profile
블로그 이전했습니다 🙂 : https://haon.blog

0개의 댓글