Middleware란?
Django의 요청/응답 처리를 위한 프레임워크임
- Django의 입출력을 전역으로 변경하기 위한 가볍고, 낮은 수준의 플러그인 시스템
각 구성 요소는 특정 기능을 담당함.(ex. 사용자가 세션을 사용해 요청과 연결하는 AuthenticationMiddleware)
Django는 기본적으로 제공되는 미들웨어가 포함되어 있고 즉시 사용할 수 있음
미들웨어 활성화
미들웨어를 활성화 하려면 Django 설정의 MIDDLEWARE_CLASSES 목록에 미들웨어를 추가하면됨
각 미들웨어 구성 요소는 문자열로 표현
Hook 및 응용 프로그램 주문
Django는 요청 단계에서 뷰를 호출하기 전에 MIDDLEWARE_CLASSES에 정의된 순서로 미들웨어를 적용
요청 단계에서 사용할 수 있는 HOOK
- process_request()
- process_view()
응답 단계에서 뷰를 호출한 후 미들웨어가 아래에서 위로(역순) 적용됨
응답 단계에서 사용할 수 있는 HOOK
- process_exception()
- process_template_response()
- process_response()
미들웨어 등록 시 가장 중요한 것은 미들웨어를 등록하는 순서임
- http request 들어올 때 위에서 아래로 미들웨어 적용
- http response 나갈 때 아래서부터 위로 미들웨어 적용
process_request(request)
- request : HttpRequest 객체임
- Django가 어떤 뷰를 실행할지 결정하기 전에 각 요청에 대해 호출됨
- None을 반환하면, Django는 다른 process_request() 미들웨어를 실행한 후, process_view() 미들웨어를 실행하고 마지막으로 적절한 뷰를 실행해 이 요청을 계속 처리
- HttpResponse 객체를 반환하면, Django는 다른 요청, 뷰 또는 예외 미들웨어 또는 적절한 뷰를 호출하지 않음, 해당 HttpResponse에 응답 미들웨어를 적용하고 결과를 반환함
process_view(request, view_func, view_args, view_kwargs)
- request : HttpRequest 객체임
- view_func : Django가 사용하려는 Python 함수
- view_args : 뷰에 전달될 위치 인수 목록, request를 포함하지 않음
- view_kwargs : 뷰에 전달될 키워드 인수 사전, request를 포함하지 않음
- Django가 view를 호출하기 바로 전에 호출됨
- None을 반환하면, Django는 이 요청을 처리하고, 다른 process_view() 미들웨어를 실행한 후 적절한 뷰를 실행함
- HttpResponse 객체를 반환하면, Django는 다른 뷰 또는 예외 미들웨어 또는 적절한 뷰를 호출하지 않음, 해당 HttpResponse에 응답 미들웨어를 적용하고 결과 반환
- csrf_exempt() 및 csrf_protect() 데커레이터를 제공, CsrfViewMiddleware 클래스는 예외로 간주될 수 있음(view에서 CSRF 유효성 검사를 수행해야 하는 시점을 명시적으로 제어할 수 있도록 해줌)
process_exception(request, exception)
- request : HttpRequest 객체임
- exception : view 함수에서 발생한 예외 object
- Django는 뷰가 예외를 발생 시킬 때 이 메서드를 호출
- None을 반환하면, 기본 예외 처리가 시작됨
- HttpResponse 객체를 반환하면, 템플릿 응답 및 응답 미들웨어가 적용되고 결과 응답이 웹 브라우저에 반환됨
- 미들웨어는 응답 단계에서 역순으로 실행됨, 예외 미들웨어가 응답을 반환하면 해당 미들웨어 위의 미들웨어 클래스는 전혀 호출되지 않음
process_template_response(request, response)
- request : HttpRequest 객체임
- response : Django 뷰 또는 미들웨어에서 반환된 TemplateResponse object(동등한 object)
- response 인스턴스가 TemplateResponse 또는 이와 동등한 것을 나타내는 render() 메서드를 가지고 있다면, 뷰가 실행을 마친 직후에 호출됨
- render() 메서드를 구현하는 응답 객체를 반환해야 함
- response.template_name와 response.context_data를 변경해 주어진 응답을 변경할 수 있거나 새로운 TemplateResponse이나 이와 동등한 것을 작성해 반환할 수 있음
- 명시적으로 응답을 렌더링할 필요 없음(모든 템플릿 응답 미들웨어가 호출되면 응답이 자동으로 렌더링)
- 응답 단계에서 역순으로 실행됨
process_response(request, response)
- request : HttpRequest 객체임
- response : Django 뷰 또는 미들웨어에서 반환된 HttpResponse 또는 StreamingHttpResponse 객체임
- 웹 브라우저가 반환되기 전에 모든 응답에 대해 호출됨
- HttpResponse 또는 StreamingHttpResponse 객체를 반환해야 하고 주어진 응답을 변경하거나 새로운 HttpResponse 또는 StreamingHttpResponse를 생성하고 반환할 수 있음
- 응답 단계에서 역순으로 실행됨
스트리밍 응답 다루기
StreamingHttpResponse에는 content 특성이 없음
콘텐츠에 대한 액세스가 필요한 경우, 스트리밍 응답을 테스트하고 그에 따라 행동을 조정해야함
if response.streaming:
response.streaming_content = wrap_streaming_content(response.streaming_content)
else :
response.content = alter_content(response.content)
streaming_content는 너무 커서 메모리에 저장할 수 없다고 가정해야함, 응답 미들웨어는 새로운 생성기에서 이를 생성할 수 있지만, 메모리 소비를 하면 안됨
그래서 wrap_streaming_content는 다음과 같이 구현됨
def wrap_streaming_content(content):
for chunk in content:
yield alter_content(chunk)
# yield는 결과의 시퀀스를 반환하기 때문에, 결과를 순회하여 응용할 때 사용
# 스트리밍은 결과를 연쇄적으로 반환하는 과정이기 때문에 yield 사용
나만의 미들웨어 작성하기
미들웨어는 뷰와 마찬가지로 요청을 받고 응답을 반환하는 callable(호출 가능한 인스턴스, 함수, 메서드 등)임
미들웨어는 Python 경로 어디서나 존재할 수 있음
함수형태의 작성
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
__init__(get_response)
대부분의 미들웨어 클래스는 미들웨어 클래스가 기본적으로 process_* 메서드의 자리표시자 이기 때문에 initializer가 필요하지 않음
어떤 전역 상태가 필요한 경우 __init__을 사용해 설정 가능
주의 사항
- Django는 파라미터 없이 미들웨어를 초기화하므로 __init__를 인수가 필요하다고 정의할 수 없음
- __init__gets는 요청당 한 번 호출되는 process_* 메서드와 달리 웹 서버가 첫 번째 요청에 응답할 때 한번만 호출
미들웨어를 미사용으로 표시
- __init__ 메서드는 django.core.exceptions.MiddlewareNotUsed를 발생 시킬 수 있음
- 이 경우 Django는 프로세스에서 해당 미들웨어 일부를 제거하고, DEBUG가 True로 설정된 경우 디버그 메시지는 django.request의 logger에 기록
비동기 지원
사용가능한 미들웨어
'Back-end & Server > Django' 카테고리의 다른 글
[Django] DB서버 연결 (0) | 2023.02.06 |
---|---|
[Django] 보안 (0) | 2023.02.06 |
[Django] 캐시 프레임워크 (0) | 2023.02.04 |
[Django] 비 HTML 콘텐츠와 세션 (0) | 2023.02.01 |
[Django] 배포 (0) | 2023.01.31 |