Django Docs | Middleware

Jihun Kim·2022년 3월 16일
0

Django Docs

목록 보기
4/9
post-thumbnail

Middleware

Middleware는 장고의 요청/응답 프로세스에 대한 Hook Framework로, 가벼운 low-level의 플러그인 시스템이다. 이를 통해 장고로 들어오는 모든 input과 output을 글로벌 하게 변경하는 것이 가능하며 이 때 각 middleware component는 특정 함수를 실행하는 역할을 한다.

장고에는 이미 내장된 middleware가 있는데 대표적으로 AuthenticationMiddleware가 있다. 이는 세션을 사용해 사용자를 요청과 연결 한다.


커스텀 middleware 만들기

middleware factory(아래의 예시에서는 simple_middleware)는 get_response를 인자로 받아 middleware를 리턴하는 하는 callable이다. middleware 함수는 request를 인자로 받아 response를 리턴한다.

아래의 예시와 같이 사용할 수 있다.


함수형

def simple_middleware(get_response):
    # One-time configuration and initialization.

    def middleware(request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

    return middleware

클래스형

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response
  • 클래스형으로 쓸 경우 인스턴스를 호출할 수 있다.

  • 실제로 django deprecation.py에 있는 MiddlewareMixin은 아래와 같이 생겼다.
    - MiddlewareMixindeprecation.py에 있는데 deprecation.py는 old-style을 new-style로 바꾸어 주는 역할을 한다. 장고의 middleware 스타일이 중간에 한 번 바뀌었기 때문에 이전 스타일의 middleware를 새로운 스타일로 변환시켜 주기 위해 사용하는 것이다(요약하자면, 하위 호환을 위한 것이다).

    - 하위 호환은 MiddlewareMixin__call__ 함수를 호출함으로써 가능한데 이는 이전 스타일의 def middleware(request)를 모방해서 새로운 스타일에 적용할 수 있도록 만들어 준다(스택 오버플로우에 자세한 설명이 나와 있다).

    class MiddlewareMixin:
        def __init__(self, get_response=None):
            self.get_response = get_response
            super().__init__()
    
        def __call__(self, request):
            response = None
            if hasattr(self, 'process_request'):
                response = self.process_request(request)
            response = response or self.get_response(request)
            if hasattr(self, 'process_response'):
                response = self.process_response(request, response)
            return response
    

get_response parameter

  • get_response는 settings에 정의된 middleware 중 가장 마지막 원소이거나 middleware chain 중 현재 middleware의 다음 middleware에 해당하는 것이어야 한다.
    - 즉, 현재 middleware 다음에 오는 어떤 middleware든 get_response가 될 수 있다.
    - 또한, get_response는 실제 뷰에 해당한다.

  • 실제로 middleware chain 중 가장 마지막에 오는 것은 실제 뷰는 아니며 handler의 wrapper 메소드로, view middleware를 관리하는 것에 해당한다.
    - 즉, 적절한 URL 인자로 뷰를 호출하고 template-response와 exception middleware를 적용하는 역할을 한다.



Middleware 활성화 하기

  • Middleware를 활성화 하려면 settings.py의 MIDDLEWARE 환경 변수의 리스트에 middleware component를 추가하기만 하면 된다.

  • 장고를 설치할 때 middleware는 비어 있어도 되지만 적어도 CommonMiddleware 즉 'django.middleware.common.CommonMiddleware'는 추가되어 있는 것이 좋다.

  • MIDDLEWARE에서 순서는 중요한데 왜냐하면 하나의 middleware가 다른 middleware에 의존할 수도 있기 때문이다.
    - 예를 들어, AuthenticationMiddleware의 경우 인증된 유저를 세션에 저장하기 때문에 SessionMiddleware 다음에 실행 되어야 한다.
    - 즉, 아래와 같이 MIDDLEWARE가 정의되어 있다면 0번째 원소 -> 1번째 원소 -> ... 순으로 middleware가 실행 된다.

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

Middleware order와 layering

  • request가 일어나면 뷰를 호출하기 전에 장고는 MIDDLEWARE에 정의된 순서대로(top-down) 미들웨어를 적용한다.
    - 장고 독스에서 말하길 양파와 같은 것이다...
  • 각 middleware class는 중심에 있는 view를 감싸고 있는 하나의 layer이다.
    - 따라서, 요청이 들어오면 이는 모든 middleware layer를 지나게 되고 응답을 할 때는 역순으로(down-top) middleware layer를 거쳐 나가게 된다.
  • 만약 layers 중 하나가 get_response를 호출해 다른 middleware를 호출하는 과정을 거치지 않고 바로 응답을 반환하기로 한다면 view를 포함한 내부에 있는 layer들은 요청 또는 응답을 확인할 수 없게 된다.
    - 즉, 응답은 요청이 들어갔던 middleware만을 거쳐 다시 나가게 된다.
profile
쿄쿄

0개의 댓글