๐ ํ์๊ฐ ๊ฐ์ธ์ ์ผ๋ก ๊ณต๋ถํ๊ณ ๋จ๊ธฐ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ ๋ณด๊ฐ ๋ฏธํกํ ์ ์์ต๋๋ค. ์๋ชป๋ ๋ด์ฉ์ด ์์๊ฒฝ์ฐ ์ง์ ํด์ฃผ์ ๋ค๋ฉด ๊ฐ์ฌํ ๋ฐ๊ฒ ์ต๋๋ค.
FastAPI์์ API Request์ Response๋ฅผ ๋ก๊ทธ๋ก ๋จ๊ฒจ์ผ ํ๋ค.
FastAPI๋ก loggingํ๋ ๋ฐฉ๋ฒ์ ๋ํ์ ์ผ๋ก 2๊ฐ์ง๊ฐ ์กด์ฌํ๋ค.
์ด๋ฒ ๊ธ์ ์ด ๋์ ์ด์ฉํด log๋ฅผ ๋จ๊ธฐ๋ ๋ฐฉ๋ฒ์ ๊ณต์ ํ๊ณ ์ ํ๋ค.
Middleware๋ ์ ํ๋ฆฌ์ผ์ด์ ์ HTTP ์์ฒญ ๋ฐ ์๋ต์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์ค๊ฐ์ ๊ฐ์ ํ์ฌ ์ถ๊ฐ์ ์ธ ๋ก์ง์ ์ํํ๋ ์ํํธ์จ์ด ์ปดํฌ๋ํธ๋ค. FastAPI๋ Middlewareํจํด์ผ๋ก ๊ตฌ์ฑ๋์ด์๋ค. APIํธ์ถ ์ ๊ณผ ํ์ ํ๋์ ์ฝ๋ฐฑํจ์๊ฐ ์คํ๋๊ณ API๋ก ์์ฒญ์ ๋๊ธด๋ค. ์ด๋ ์ด ์ฝ๋ฐฑํจ์๋ Request์ Response์ ์ฒ๋ฆฌ ๊ณผ์ ์ ์ฌ์ฉ์ ์ ์ ๋ก์ง์ ์ํํ ์ ์๋๋ก ๋์์ค๋ค.
FastAPI์์ ์ ๊ณตํ๋ Middleware๋ฅผ ์ฌ์ฉํ์ฌ API Request์ Response์ ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ๋ค.
from fastapi import FastAPI, Response, Request
from starlette.background import BackgroundTask
from typing import Dict, Any
import logging
app = FastAPI()
# ๋ก๊ทธ ํ์ผ์ ์์ฑ (์๊ฐ๋ณด๋ค ๋ก๊ทธ๋ก ์๋ฒ๊ฐ ์์ฃผ ํฐ์ง๋๋ผ๊ตฌ์..ใ
)
logging.basicConfig(filename='info.log', level=logging.DEBUG)
def log_info(req_body, res_body):
logging.info(req_body)
logging.info(res_body)
@app.middleware('http')
async def some_middleware(request: Request, call_next):
req_body = await request.body()
response = await call_next(request)
res_body = b''
async for chunk in response.body_iterator:
res_body += chunk
task = BackgroundTask(log_info, req_body, res_body)
return Response(content=res_body, status_code=response.status_code,
headers=dict(response.headers), media_type=response.media_type, background=task)
@app.post('/')
def main(payload: Dict[Any, Any]):
return {"Hello": "World"}
Middleware๋ฅผ ์ฌ์ฉํ๋ฉด Request๊ฐ ์๋ํฌ์ธํธ์ ๋๋ฌํ๊ธฐ ์ ์ ์ค๊ฐ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๊ณ ์๋ํฌ์ธํธ๊ฐ ๋ฐํํ Response๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌ๋๊ธฐ ์ ์ ์ค๊ฐ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๋ค.
์์ ์ฝ๋๋ฅผ ์คํํ๋ฉด FastAPI ์ ํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋๋ฉด์ Request์ Response์ ๋ํ ๋ก๊ทธ๊ฐ ์ถ๋ ฅ๋๋ค.
APIRoute๋ FastAPI์์ ์๋ํฌ์ธํธ๋ฅผ ๋ ์ธ๋ถ์ ์ผ๋ก ์ ์ดํ ์ ์๊ฒ ํด์ฃผ๋ ํด๋์ค์ด๋ค. ์ด ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ํฌ์ธํธ์ ๋์์ ๋์ฑ ์ ์ฐํ๊ฒ ์ ์ํ๊ณ ์ปค์คํฐ๋ง์ด์งํ ์ ์๋ค.
from fastapi import FastAPI, HTTPException, APIRouter, Request, Depends
from fastapi.responses import JSONResponse
import logging
app = FastAPI()
router = APIRouter()
# ๋ก๊น
์ ์ํ ํจ์ ์ ์
def custom_logger(request: Request, response: JSONResponse, logger: logging.Logger = Depends()):
logger.info(f"Request: {request.method} {request.url}")
logger.info(f"Response: {response.status_code}")
return response
# APIRoute๋ฅผ ์ฌ์ฉํ ์๋ํฌ์ธํธ ์ ์
@router.get("/", response_class=JSONResponse, dependencies=[Depends(custom_logger)])
async def read_root():
return {"Hello": "World"}
# FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ APIRouter ๋ฑ๋ก
app.include_router(router, prefix="/api")
# ๋ก๊ฑฐ ์ค์
logger = logging.getLogger("uvicorn")
logger.setLevel(logging.INFO)
์์ ์ฝ๋๋ฅผ ์คํํ๋ฉด FastAPI ์ ํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋๋ฉด์ APIRoute๋ฅผ ์ฌ์ฉํ ์๋ํฌ์ธํธ์ ๋ํ Request์ Response์ ๋ํ ๋ก๊ทธ๊ฐ ์ถ๋ ฅ๋๋ค.
ํนํ APIRoute๋ฅผ ํ์ฉํ๋ฉด ์๋ํฌ์ธํธ์ ๋ํ ๋ก๊น ์ ๋์ฑ ์ธ๋ฐํ๊ฒ ์กฐ์ ํ ์ ์๊ณ , ๊ฐ ์๋ํฌ์ธํธ๋ง๋ค ๋ค๋ฅธ ๋ก๊น ๋ก์ง์ ์ ์ฉํ ์ ์๋ค.
์๋ ํ์ธ์! ๋ ๋ฐฉ๋ฒ์ ๊ฐ์ด ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ fastapi์์ ์๋์?