Python/Backend

FastAPI 미들웨어(middleware) 선언 코드 예제

jimmy_AI 2025. 3. 12. 00:00
반응형

안녕하세요.

이번 시간에는 FastAPI를 사용하면서 자주 활용되는 미들웨어에 대해 쉽게 설명해보고,

예제 코드와 함께 선언 방법을 간단히 정리해 보겠습니다.

 

 

미들웨어란?

middleware는 API 서버에 들어오는 모든 요청과 나가는 응답 사이에서

공통 작업을 처리할 수 있도록 도와주는 작은 기능 모듈입니다.


즉, 요청이 실제로 처리되기 전에 전처리를 하거나 또는

클라이언트에게 응답을 보내기 전에 후처리를하는 역할을 합니다.

대표적인 사용 예시는 다음과 같습니다.

  • 요청이 들어올 때 / API 로직 처리 이후 로그를 남기는 경우
  • API 함수의 소요 시간을 기록하는 경우
  • 유저별 Rate Limit를 설정하려는 경우

 

 

데코레이터 방식의 미들웨어

가장 간단한 방법으로, 데코레이터를 사용해서 미들웨어 함수를 작성할 수 있습니다.

데코레이터는 함수 상단에 @app.middleware("http")의 형태로 추가해주시면 됩니다.
다음의 예제는 요청 소요 시간을 측정해서 응답 헤더에 추가하는 미들웨어입니다.

from fastapi import FastAPI, Request
import time

app = FastAPI()

@app.middleware("http") # 데코레이터로 미들웨어 선언
async def add_process_time_header(request: Request, call_next):
    # 요청이 들어오기 전: 시작 시간 기록
    start_time = time.time()

    # call_next를 호출하면 실제 API 함수를 실행
    response = await call_next(request)

    # API 함수 호출이 종료되고 이후의 로직이 실행
    process_time = time.time() - start_time
    print(f"요청 처리 완료: {process_time:.2f}초 소요")
    response.headers["X-Process-Time"] = f"{process_time:.2f}"
    return response

# 이제 app과 연결된 모든 함수는 위에서 구현한 로직을 통과
@app.get("/")
async def read_root():
    return {"message": "Hello, FastAPI!"}

함수 실행의 전/후는 call_next로 나뉘며, 비동기 처리를 위한 await 선언이 필요합니다.

 

 

BaseHTTPMiddleware 클래스 방식의 미들웨어

FastAPI의 근간을 이루고 있는 Starlette에서 선언된 BaseHTTPMiddleware를 상속받아

미들웨어를 구현하는 방식도 존재하는데, 확장성이 높아 많이 활용됩니다.

 

이 경우의 예시 코드 스니펫은 다음과 같습니다.

from fastapi import FastAPI, Request
from starlette.middleware.base import BaseHTTPMiddleware
import time

class MyMiddleware(BaseHTTPMiddleware):

    # dispatch라는 함수에 실행을 원하는 로직을 적어야 함
    async def dispatch(self, request: Request, call_next):
        # 요청이 들어오기 전: 시작 시간 기록
        start_time = time.time()
        
        # call_next를 호출하면 실제 API 함수를 실행
        response = await call_next(request)
        
        # API 함수 호출이 종료되고 이후의 로직이 실행
        process_time = time.time() - start_time
        print(f"Completed in {process_time:.2f} seconds")
        response.headers["X-Process-Time"] = f"{process_time:.2f}"
        return response

app = FastAPI()
app.add_middleware(MyMiddleware) # app에 해당 미들웨어를 직접 추가하여 선언

# 이제 app과 연결된 모든 함수는 위에서 구현한 로직을 통과
@app.get("/")
async def read_root():
    return {"message": "Hello, FastAPI!"}

이 방식으로 middleware를 선언하는 경우에는 dispatch 함수 내에

원하는 로직을 적어야 한다는 특징이 있습니다.

 

함수 실행의 전/후가 call_next로 나뉘며, 비동기 처리를 위한 await 선언이 필요한 점은

데코레이터 방식과 동일합니다.

 

미들웨어 함수가 실행되는 과정에서 Request 객체를 활용하면 요청 본문 정보 등을 통하여

다양한 처리를 진행할 수 있게 됩니다.

 

이 글이 FastAPI를 활용한 서버 구현을 진행하는 과정에 도움이 되셨기를 기원합니다.

잘 봐주셔서 감사합니다.