Skip to content

๋ฏธ๋“ค์›จ์–ด

๋ฏธ๋“ค์›จ์–ด๋ฅผ FastAPI ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

"๋ฏธ๋“ค์›จ์–ด"๋Š” ํŠน์ • ๊ฒฝ๋กœ ์ž‘๋™์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋˜๊ธฐ ์ „, ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด์„œ ๋™์ž‘ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ชจ๋“  ์‘๋‹ต์ด ๋ฐ˜ํ™˜๋˜๊ธฐ ์ „์—๋„ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฏธ๋“ค์›จ์–ด๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์˜ค๋Š” ์š”์ฒญ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • ์š”์ฒญ ๋˜๋Š” ๋‹ค๋ฅธ ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์š”์ฒญ์„ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ๋กœ ์ž‘๋™์œผ๋กœ ์ „๋‹ฌํ•˜์—ฌ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฒฝ๋กœ ์ž‘์—…์—์„œ ์ƒ์„ฑํ•œ ์‘๋‹ต๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.
  • ์‘๋‹ต ๋˜๋Š” ๋‹ค๋ฅธ ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ๋™์ž‘์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‘๋‹ต๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ

๋งŒ์•ฝ yield๋ฅผ ์‚ฌ์šฉํ•œ ์˜์กด์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๋‚œ ํ›„์— exit์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ (๋‚˜์ค‘์— ๋ฌธ์„œ์—์„œ ๋‹ค๋ฃฐ) ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…์ด ์žˆ๋‹ค๋ฉด, ๋ชจ๋“  ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๋‚œ ํ›„์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋ฏธ๋“ค์›จ์–ด ๋งŒ๋“ค๊ธฐ

๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ•จ์ˆ˜ ์ƒ๋‹จ์— @app.middleware("http") ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋Š” ๋‹ค์Œ ํ•ญ๋ชฉ๋“ค์„ ๋ฐ›์Šต๋‹ˆ๋‹ค:

  • request.
  • request๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” call_next ํ•จ์ˆ˜.
    • ์ด ํ•จ์ˆ˜๋Š” request๋ฅผ ํ•ด๋‹นํ•˜๋Š” ๊ฒฝ๋กœ ์ž‘์—…์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
    • ๊ทธ๋Ÿฐ ๋‹ค์Œ, ๊ฒฝ๋กœ ์ž‘์—…์— ์˜ํ•ด ์ƒ์„ฑ๋œ response ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • response๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์— ์ถ”๊ฐ€๋กœ response๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
import time

from fastapi import FastAPI, Request

app = FastAPI()


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    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

ํŒ

์‚ฌ์šฉ์ž ์ •์˜ ํ—ค๋”๋Š” 'X-' ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋งŒ์•ฝ ํด๋ผ์ด์–ธํŠธ์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ—ค๋”๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๊ทธ๊ฒƒ๋“ค์„ CORS ์„ค์ •(CORS (Cross-Origin Resource Sharing))์— Starlette CORS ๋ฌธ์„œ์— ๋ช…์‹œ๋œ expose_headers ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ํ—ค๋”๋“ค์„ ์ถ”๊ฐ€ํ•˜์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ์ˆ ์  ์„ธ๋ถ€์‚ฌํ•ญ

from starlette.requests import request๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

FastAPI๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ ํŽธ์˜๋ฅผ ์œ„ํ•ด ์ด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Starlette์—์„œ ์ง์ ‘ ํŒŒ์ƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

response์˜ ์ „๊ณผ ํ›„

๊ฒฝ๋กœ ์ž‘๋™์„ ๋ฐ›๊ธฐ ์ „ request์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  response ๋˜ํ•œ ์ƒ์„ฑ๋œ ํ›„ ๋ฐ˜ํ™˜๋˜๊ธฐ ์ „์— ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‘๋‹ต์„ ์ƒ์„ฑํ•˜๋Š”๋ฐ ๊นŒ์ง€ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” X-Process-Time ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ •์˜ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import time

from fastapi import FastAPI, Request

app = FastAPI()


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    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

๋‹ค๋ฅธ ๋ฏธ๋“ค์›จ์–ด

๋ฏธ๋“ค์›จ์–ด์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ •๋ณด๋Š” ์ˆ™๋ จ๋œ ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ: ํ–ฅ์ƒ๋œ ๋ฏธ๋“ค์›จ์–ด์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ถ€๋ถ„์—์„œ ๋ฏธ๋“ค์›จ์–ด์™€ ํ•จ๊ป˜ CORS๋ฅผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃจ๋Š”์ง€์— ๋Œ€ํ•ด ํ™•์ธํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.