Django 미들웨어란?
Django 미들웨어는 요청과 응답 사이에 위치하여 처리 과정을 가로채거나 수정할 수 있는 강력한 시스템입니다. 이를 통해 인증, 로깅, 보안 검사 등 다양한 기능을 뷰(View) 코드에 영향을 주지 않고도 구현할 수 있습니다. 미들웨어는 애플리케이션의 전반적인 흐름에 개입하면서도 모듈화된 방식으로 동작하므로 유지보수가 용이합니다.
미들웨어의 주요 메서드
Django 미들웨어 클래스는 특정 단계에서 자동으로 호출되는 여러 훅(hook) 메서드를 제공합니다. 각 메서드는 HTTP 처리 파이프라인의 특정 지점에서 실행됩니다.
- __init__(self): 서버가 시작된 후 첫 번째 요청 시 한 번만 실행됩니다. 미들웨어 초기화나 활성화 여부를 결정하는 데 사용됩니다.
def __init__(self):
self.enabled = True
- process_request(self, request): URL 라우팅 이전에 호출되며,
request객체가 생성된 직후 실행됩니다. 여기서HttpResponse를 반환하면 이후 단계는 생략되고 바로 응답이 전달됩니다.
def process_request(self, request):
print(f"요청 수신: {request.path}")
- process_view(self, request, view_func, view_args, view_kwargs): URL 매칭 후, 실제 뷰 함수가 호출되기 전에 실행됩니다. 이 메서드에서도 응답 객체를 반환하면 뷰는 실행되지 않습니다.
def process_view(self, request, view_func, view_args, view_kwargs):
print(f"호출될 뷰: {view_func.__name__}")
- process_response(self, request, response): 뷰에서 응답이 반환된 후, 클라이언트에 전송되기 전에 반드시 호출됩니다. 응답 객체를 수정하거나 로깅 목적으로 사용할 수 있으며, 항상 응답 객체를 반환해야 합니다.
def process_response(self, request, response):
print("응답 전송 완료")
return response
- process_exception(self, request, exception): 뷰에서 예외가 발생했을 때 호출됩니다. 오류 로깅이나 사용자 정의 오류 페이지 처리에 유용합니다. 반환값이
HttpResponse라면 해당 응답이 클라이언트에 전달됩니다.
def process_exception(self, request, exception):
print(f"예외 발생: {exception}")
커스텀 미들웨어 작성 예제
예를 들어, 요청 처리 시간을 측정하고 로그를 출력하는 미들웨어를 만들어보겠습니다.
- 프로젝트 내 임의의 앱 디렉터리 (예:
booktest)에middleware.py파일을 생성합니다.
import time
class TimingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
duration = time.time() - start_time
print(f"요청 처리 소요 시간: {duration:.2f}초")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print(f"[VIEW] {view_func.__module__}.{view_func.__name__} 호출 준비")
def process_exception(self, request, exception):
print(f"[ERROR] {type(exception).__name__}: {exception}")
- 설정 파일
settings.py의MIDDLEWARE리스트에 새 미들웨어를 추가합니다.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
# ... 기타 미들웨어
'booktest.middleware.TimingMiddleware', # 커스텀 미들웨어 등록
]
- 테스트용 뷰를 수정하여 동작 확인:
from django.http import HttpResponse
def index(request):
print("뷰 함수 실행 중...")
return HttpResponse("Hello, Middleware!")
- 개발 서버를 실행하고 요청을 보내면, 콘솔에 아래와 같은 출력이 나타납니다:
뷰 함수 실행 중... [VIEW] booktest.views.index 호출 준비 요청 처리 소요 시간: 0.01초
예외 처리 미들웨어의 실행 순서
여러 개의 미들웨어가 process_exception 메서드를 정의하고 있을 경우, 설정 파일의 MIDDLEWARE 리스트에서 더 아래에 위치한 미들웨어부터 먼저 호출됩니다. 즉, 등록 순서의 역순으로 실행됩니다. 따라서 예외 핸들링은 가장 마지막에 등록된 미들웨어가 우선 처리하게 됩니다.
예를 들어, 다음과 같이 두 개의 예외 미들웨어가 등록되어 있다면:
class LogErrorMiddleware:
def process_exception(self, request, exception):
print("[Log] 오류 기록됨")
class HandleErrorMiddleware:
def process_exception(self, request, exception):
print("[Handle] 오류 처리 시작")
return HttpResponse("오류가 발생했습니다.", status=500)
실제로는 HandleErrorMiddleware가 먼저 실행되고, 거기서 응답을 반환하면 LogErrorMiddleware는 호출되지 않습니다.