WeniVooks

검색

FastAPI 베이스캠프

미들웨어 사용

1. 미들웨어 소개

미들웨어는 요청이 라우트 핸들러에 도달하기 전이나 응답이 클라이언트에게 반환되기 전에 실행되는 함수입니다. 미들웨어를 사용하면 모든 요청이나 응답에 대해 공통적인 작업을 수행할 수 있습니다. 예를 들어, 로깅, 인증, CORS(Cross-Origin Resource Sharing) 처리 등을 미들웨어로 구현할 수 있습니다.

2. 간단한 커스텀 미들웨어 작성

FastAPI에서 커스텀 미들웨어를 작성하는 방법을 알아보겠습니다.

from fastapi import FastAPI, Request
 
app = FastAPI()
 
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    import time
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response
 
@app.get("/")
async def root():
    return {"message": "Hello World"}
from fastapi import FastAPI, Request
 
app = FastAPI()
 
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    import time
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response
 
@app.get("/")
async def root():
    return {"message": "Hello World"}

이 예제에서는 모든 요청에 대해 처리 시간을 계산하고, 이를 응답 헤더에 추가하는 미들웨어를 구현했습니다.

3. CORS 미들웨어 사용하기

CORS(Cross-Origin Resource Sharing)는 웹 브라우저에서 다른 도메인의 리소스에 접근할 때 필요한 보안 메커니즘입니다. FastAPI는 CORS를 쉽게 처리할 수 있는 미들웨어를 제공합니다.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
 
app = FastAPI()
 
origins = [
    "http://localhost",
    "http://localhost:8080",
]
 
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
 
@app.get("/")
async def main():
    return {"message": "Hello World"}
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
 
app = FastAPI()
 
origins = [
    "http://localhost",
    "http://localhost:8080",
]
 
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
 
@app.get("/")
async def main():
    return {"message": "Hello World"}

이 설정은 지정된 origins에서의 요청만을 허용하며, 모든 HTTP 메서드와 헤더를 허용합니다.

4. 요청 ID 미들웨어

각 요청에 고유한 ID를 할당하는 미들웨어를 만들어 보겠습니다. 이는 로깅이나 디버깅에 유용할 수 있습니다.

import uuid
from fastapi import FastAPI, Request
 
app = FastAPI()
 
@app.middleware("http")
async def add_request_id(request: Request, call_next):
    request_id = str(uuid.uuid4())
    request.state.request_id = request_id
    response = await call_next(request)
    response.headers["X-Request-ID"] = request_id
    return response
 
@app.get("/")
async def root(request: Request):
    return {"message": "Hello World", "request_id": request.state.request_id}
import uuid
from fastapi import FastAPI, Request
 
app = FastAPI()
 
@app.middleware("http")
async def add_request_id(request: Request, call_next):
    request_id = str(uuid.uuid4())
    request.state.request_id = request_id
    response = await call_next(request)
    response.headers["X-Request-ID"] = request_id
    return response
 
@app.get("/")
async def root(request: Request):
    return {"message": "Hello World", "request_id": request.state.request_id}

이 미들웨어는 각 요청에 고유한 ID를 생성하고, 이를 요청 객체와 응답 헤더에 추가합니다.

5. 에러 처리 미들웨어

전역적으로 에러를 잡아 처리하는 미들웨어를 만들어 보겠습니다.

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
 
app = FastAPI()
 
@app.middleware("http")
async def catch_exceptions_middleware(request: Request, call_next):
    try:
        return await call_next(request)
    except Exception as e:
        return JSONResponse(status_code=500, content={"message": str(e)})
 
@app.get("/error")
async def cause_error():
    raise ValueError("This is a deliberate error")
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
 
app = FastAPI()
 
@app.middleware("http")
async def catch_exceptions_middleware(request: Request, call_next):
    try:
        return await call_next(request)
    except Exception as e:
        return JSONResponse(status_code=500, content={"message": str(e)})
 
@app.get("/error")
async def cause_error():
    raise ValueError("This is a deliberate error")

이 미들웨어는 애플리케이션에서 발생하는 모든 예외를 잡아 500 Internal Server Error 응답으로 변환합니다.

연습문제

  1. 모든 요청에 대해 사용자의 IP 주소를 로그로 기록하는 미들웨어를 작성해보세요.

  2. 특정 URL 패턴(예: "/admin/*")에 대한 요청만 처리하는 미들웨어를 만들어보세요. 이 미들웨어는 요청이 관리자 페이지에 대한 것인지 확인하고, 그렇지 않다면 403 Forbidden 응답을 반환해야 합니다.

  3. 요청 헤더에 "X-API-Key"가 있는지 확인하고, 없다면 401 Unauthorized 응답을 반환하는 미들웨어를 구현해보세요.

  4. 응답 크기를 측정하여 로그로 기록하는 미들웨어를 작성해보세요. 응답 헤더의 "Content-Length"를 사용할 수 있습니다.

5.1 에러 처리와 예외 관리5.3 파일 업로드 및 처리