나만의 커스텀 미들웨어로 API 로깅과 모니터링 구현하기
Django 미들웨어를 직접 구현하여 API 요청과 응답 과정을 기록하고 모니터링하는 시스템 구축
미들웨어 개념과 필요성
미들웨어(Middleware) 는 Django의 요청-응답 처리 과정에 개입하는 훅 시스템으로, 웹 요청이 뷰에 도달하기 전과 뷰가 생성한 응답이 클라이언트에게 전달되기 전에 특정 작업 수행
중앙 집중식 관리: 여러 뷰에서 반복되는 로직을 한 곳에서 관리
API 성능 측정: 모든 API 요청의 처리 시간을 정확하게 측정하여 병목 지점 파악
풍부한 컨텍스트 로깅: 요청의 IP, 사용자 정보, 헤더와 응답 상태 등을 종합한 상세 로그 생성
요청/응답 데이터 정제: 조건에 따른 요청 데이터 가공 및 응답 형식 일괄 처리
커스텀 미들웨어 구현
1. 기본 미들웨어 구조 생성
# your_app/middleware.py
import time
import logging
from uuid import uuid4
logger = logging.getLogger(__name__)
class APILoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 요청 전 실행 코드
response = self.get_response(request)
# 응답 후 실행 코드
return response2. 요청 추적 및 성능 측정
def __call__(self, request):
# 고유한 요청 ID 생성
request.id = str(uuid4())
# 요청 처리 시작 시간 기록
start_time = time.time()
response = self.get_response(request)
# 처리 시간 계산 및 헤더 추가
duration = time.time() - start_time
response['X-Response-Time-ms'] = str(round(duration * 1000, 2))
return response3. 상세 로깅 구현
def __call__(self, request):
request.id = str(uuid4())
start_time = time.time()
# 요청 본문 처리
request_body = request.body
if request_body:
try:
request_body = json.loads(request_body)
except (json.JSONDecodeError, UnicodeDecodeError):
request_body = "Could not decode body"
response = self.get_response(request)
duration = time.time() - start_time
response_time_ms = round(duration * 1000, 2)
response['X-Response-Time-ms'] = str(response_time_ms)
# 사용자 정보 추출
user = "anonymous"
if request.user and request.user.is_authenticated:
user = request.user.username
# 로깅 데이터 구조화
log_data = {
'request_id': request.id,
'user': user,
'method': request.method,
'path': request.path,
'query_params': request.GET.dict(),
'request_headers': dict(request.headers),
'request_body': request_body,
'remote_addr': request.META.get('REMOTE_ADDR'),
'status_code': response.status_code,
'response_time_ms': response_time_ms,
}
# 에러 시 응답 본문 포함
if response.status_code >= 400 and response.content:
try:
log_data['response_body'] = json.loads(response.content)
except (json.JSONDecodeError, UnicodeDecodeError):
log_data['response_body'] = "Could not decode body"
logger.info("API Request/Response", extra=log_data)
return response4. 미들웨어 등록
# settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'your_app.middleware.APILoggingMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
# ... 기타 미들웨어
]실무 고려사항
보안 및 성능
민감 정보 마스킹: 비밀번호, API 키, 개인정보는 반드시 로그에서 제외 또는 마스킹 처리
성능 최적화: 미들웨어는 모든 요청마다 실행되므로 무거운 작업 금지
선택적 로깅: 특정 경로(
/health-check,/admin)는 로깅에서 제외
def __call__(self, request):
if request.path.startswith('/admin') or request.path == '/health-check':
return self.get_response(request)
# ... 로깅 로직모니터링 시스템 연동
구조화된 로그 데이터를 Datadog, ELK Stack, Grafana Loki 등의 도구로 전송하여 실시간 대시보드 구축 및 API 성능 지속 모니터링
Last updated
