
FastAPI๋ก ๊ฐ๋จํ API๋ฅผ ๋ง๋ค ๋๋ ํ๋์ ํ์ผ๋ก๋ ์ถฉ๋ถํ๋ค.
ํ์ง๋ง ํฌ๊ธฐ๊ฐ ์ ์ ์ปค์ง๊ฒ ๋๋ฉด,
main.py ํ์ผ ํ๋์ ์ฌ์ฉ์ API, ์ํ API, ์ฃผ๋ฌธ API, ์ธ์ฆ ๋ก์ง,
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ฝ๋๊น์ง ์ ๋ถ ๋ค์ด๊ฐ๊ฒ ๋๋ค.
์๋ฐฑ, ์์ฒ ์ค์ ์ฝ๋๊ฐ ํ ํ์ผ์ ๋ชจ์ด๋ฉด
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ด ๋ฐ๋ก APIRouter๋ค.
๊ด๋ จ๋ API๋ค์ ํ์ผ ๋จ์๋ก ๋ถ๋ฆฌํ๊ณ , ๋ง์ง๋ง์ ๋ฉ์ธ ์ฑ์์ ์กฐ๋ฆฝํ๋ ๋ฐฉ์์ด๋ค.
๐์ฌ๋ฌ ์ปดํจํฐ ๋คํธ์ํฌ๋ฅผ ์ฐ๊ฒฐํ๊ณ ๋ฐ์ดํฐ ํจํท์ ์ต์ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ ์ ์กํ๋ ์ฅ๋น
์ธํฐ๋ท์์ ๋ค์ด์ค๋ ์์ฒญ์ ๋ณด๊ณ
"์ด ์์ฒญ์ ๋๊ตฌ์๊ฒ ๋ณด๋ด์ผ ํ์ง?" ๋ฅผ ๊ฒฐ์ ํ๋ ์ฅ์น๋ค.
FastAPI์ APIRouter๋ ๊ฐ์ ์ญํ ์ ํ๋ค.
HTTP ์์ฒญ์ด ๋ค์ด์ค๋ฉด ์ด๋ค ํจ์๊ฐ ์ฒ๋ฆฌํ ์ง ์๋ดํ๋ ์ด์ ํ ์ญํ ์ ํ๋ค.
๋ ๊ณ ๋ธ๋ก์ ๋ ์ฌ๋ฆฌ๋ฉด ๋๋ค.
Python์์ ๋ชจ๋์ .py ํ์ผ ํ๋๋ค.
๊ฐ ํ์ผ์ ๋ ๋ฆฝ์ ์ธ ์ฝ๋ ๋จ์์ด๊ณ , ์ฌ๋ฌ ๋ชจ๋์ ์กฐํฉํด ํ๋์ ํ๋ก๊ทธ๋จ์ ๋ง๋ ๋ค.
๋ ๊ณ ๋ธ๋ก๋ค์ ๋ด์๋๋ ์์๋ค.
Python์์ ํจํค์ง๋ ๋ชจ๋๋ค์ ๋ด๊ณ ์๋ ํด๋๋ค.
๋จ, ์ผ๋ฐ ํด๋์ ๋ค๋ฅธ ์ ์ด ํ๋ ์๋ค.
__init__.py ํ์ผ์ด ์์ด์ผ ํ๋คmkdir -p app/routers touch app/__init__.py touch app/main.py touch app/routers/__init__.py touch app/routers/users.py
์์ฑ๋ ํด๋ ๊ตฌ์กฐ๋ ์๋์ ๊ฐ๋ค.
app/
โโโ __init__.py # app ํจํค์ง ์ ์ธ
โโโ main.py # FastAPI ์ฑ ์ง์
์
โโโ routers/
โโโ __init__.py # routers ํจํค์ง ์ ์ธ
โโโ users.py # ์ฌ์ฉ์ ๊ด๋ จ API
from fastapi import APIRouter
router = APIRouter() # ํต์ฌ ๊ฐ์ฒด
@router.get("/users/")
async def read_users():
return [{"username": "jay"}, {"username": "์ฒ ์"}]
@router.get("/users/{username}")
async def read_user(username: str):
return {"username": username}
์ฌ๊ธฐ์ ์ค์ํ ํฌ์ธํธ
FastAPI()๊ฐ ์๋๋ผAPIRouter()๋ฅผ ์ฌ์ฉํ๋คfrom fastapi import FastAPI
from .routers import users
app = FastAPI()
app.include_router(users.router)
@app.get("/")
async def root():
return {"message": "Hello!"}
include_router() ํ ์ค๋ก
์ธ๋ถ ํ์ผ์ API๋ฅผ ์ฑ์ ๊ฒฐํฉํ๋ค.
fastapi dev app/main.py
๋ธ๋ผ์ฐ์ ์์ ์๋ ์ฃผ์๋ก ์ด๋ํ๋ค.
http://127.0.0.1:8000/docs
Swagger UI์์ ๋ค์ ์๋ํฌ์ธํธ๋ค์ด ๋ณด์ด๋ฉด ์ฑ๊ณต์ด๋ค.
GET /GET /users/GET /users/{username}APIRouter๋ FastAPI์ ์ฌ์ฉ๋ฒ์ด ๊ฑฐ์ ๊ฐ๋ค.
์ฐจ์ด์ ์ ๋จ ํ๋๋ค.
| ๊ตฌ๋ถ | FastAPI | APIRouter |
|---|---|---|
| ์ญํ | ๋ฉ์ธ ์ ํ๋ฆฌ์ผ์ด์ | API ๊ทธ๋ฃน ๋ถํ |
| ๋ ๋ฆฝ ์คํ | ๊ฐ๋ฅ | ๋ถ๊ฐ๋ฅ |
| ๋ฐ์ฝ๋ ์ดํฐ | @app.get() | @router.get() |
users.py๋ฅผ ๋ณด๋ฉด /users๊ฐ ๊ณ์ ๋ฐ๋ณต๋๋ค.
/users/
/users/{username}
prefix๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ๋ฐ๋ณต์ ์ ๊ฑฐํ ์ ์๋ค.
from fastapi import APIRouter
router = APIRouter(prefix="/users")
@router.get("/")
async def read_users():
return [{"username": "jay"}, {"username": "์ฒ ์"}]
@router.get("/{username}")
async def read_user(username: str):
return {"username": username}
/๋ก ์์ํด์ผ ํ๋ค/๋ฅผ ๋ถ์ด๋ฉด ์ ๋๋ค/users/users/, users
Swagger UI์์ API๋ฅผ ๋ณด๊ธฐ ์ข๊ฒ ๋ฌถ์ ์ ์๋ค.
router = APIRouter(
prefix="/users",
tags=["users"]
)
์ค์ ํ๋ก์ ํธ์์๋ ํ๋์ ๋ผ์ฐํฐ๋ก๋ ์ ๋ ๋ถ์กฑํ๋ค.
๋๋ฉ์ธ(๊ธฐ๋ฅ) ๋จ์๋ก ๋ผ์ฐํฐ๋ฅผ ๋ถ๋ฆฌํ๊ณ , ๋ฉ์ธ ์ฑ์์ ์กฐ๋ฆฝํ๋ ๊ตฌ์กฐ๊ฐ ๊ธฐ๋ณธ์ด๋ค.
app/
โโโ main.py โ FastAPI ์ฑ ์ง์
์
โโโ dependencies.py โ ๊ณตํต ์์กด์ฑ (์ธ์ฆ, ๊ถํ ๋ฑ)
โโโ routers/
โโโ __init__.py
โโโ users.py โ ์ฌ์ฉ์ ๋๋ฉ์ธ
โโโ items.py โ ์ํ ๋๋ฉ์ธ
๐ ํต์ฌ ์์น
โข ๋ผ์ฐํฐ = ๋๋ฉ์ธ ๋จ์
โข main.py = ์กฐ๋ฆฝ๋ง ๋ด๋น
โข ๊ณตํต ๋ก์ง = dependencies๋ก ๋ถ๋ฆฌ
touch app/routers/items.py
from fastapi import APIRouter
router = APIRouter(
prefix="/items",
tags=["items"]
)
fake_items_db = {
"๋ฌผ์ด": {"name": "๋ฌผ์ด", "price": 32000.0},
"์๋ฅํ": {"name": "์๋ฅํ", "price": 19900.0}
}
@router.get("/")
async def read_items():
return fake_items_db
@router.get("/{item_id}")
async def read_item(item_id: str):
if item_id not in fake_items_db:
return {"error": "Item not found"}
return fake_items_db[item_id]
prefix โ URL ์ฑ
์์ ๋ผ์ฐํฐ๋ก ์์tags โ ๋ฌธ์(Swagger) ๊ฐ๋
์ฑ ํฅ์from fastapi import FastAPI
from .routers import users, items
app = FastAPI()
app.include_router(users.router)
app.include_router(items.router)
@app.get("/")
async def root():
return {"message": "Hello!"}
์์ฒญ ํ๋ฆ (๋ผ์ฐํฐ ๊ฒฐํฉ ๊ตฌ์กฐ) Client โ FastAPI app โโ users.router โ /users/** โโ items.router โ /items/**
from .routers import users
. ์ ํ์ฌ ํจํค์ง(app)๋ฅผ ์๋ฏธํ๋ค.
ํจํค์ง ๋ด๋ถ ์ฐธ์กฐ์ ๊ฐํ์ง๋ง, ๋จ๋
์คํ์๋ ์ฝํ๋ค.
from app.routers import users
๊ฒฝ๋ก๊ฐ ๋ช
ํํ๊ณ IDE ์๋์์ฑ์ด ๊ฐ๋ ฅํ๋ค.
์ค๋ฌด์์๋ ์ด ๋ฐฉ์์ ๋ ๋ง์ด ์ด๋ค.
| ๊ตฌ๋ถ | ์๋ import | ์ ๋ import |
|---|---|---|
| ๊ฐ๋ ์ฑ | ์ค์ฒฉ ์ ๋๋น ์ง | ๋ช ํ |
| IDE ์ง์ | ์ฝํจ | ๊ฐํจ |
| ์ค๋ฌด ์ ํธ | ๋ฎ์ | ๋์ |
์ธ์ฆ, ๊ถํ, ํ ํฐ ๊ฒ์ฆ ๊ฐ์ ๋ก์ง์
๋ผ์ฐํฐ๋ง๋ค ๋ฐ๋ณตํ๋ฉด ๋งํ๋ค.
from typing import Annotated
from fastapi import Header, HTTPException
async def verify_token(
x_token: Annotated[str, Header()]
):
if x_token != "fake-super-secret-token":
raise HTTPException(
status_code=400,
detail="X-Token header invalid"
)
from fastapi import APIRouter, Depends
from ..dependencies import verify_token
router = APIRouter(
prefix="/items",
tags=["items"],
dependencies=[Depends(verify_token)]
)
์์ฒญ ์ฒ๋ฆฌ ํ๋ฆ Client โ verify_token (๊ณตํต ์์กด์ฑ) โ items router โ endpoint ํจ์
from .routers.users import router from .routers.items import router # ์์ router ๋ฎ์ด์
ํญ์ ๋ชจ๋ ๋จ์๋ก import
from .routers import users, items app.include_router(users.router) app.include_router(items.router)
| ๊ฐ๋ | ํต์ฌ ์๋ฏธ |
|---|---|
| APIRouter | ๋๋ฉ์ธ ๋จ์ API ๋ฌถ์ |
| prefix | URL ์ฑ ์์ ๋ผ์ฐํฐ๋ก ์์ |
| tags | ๋ฌธ์ ๊ฐ๋ ์ฑ + ํ์ ํจ์จ |
| dependencies | ๊ณตํต ๋ก์ง ์ค์ ์ง์คํ |
| main.py | ์กฐ๋ฆฝ๋ง ๋ด๋น (๋ก์ง ๊ธ์ง) |