FastAPI - APIRouter

Kjjeddยท2026๋…„ 1์›” 14์ผ

FastAPI

๋ชฉ๋ก ๋ณด๊ธฐ
16/16
post-thumbnail

๐Ÿงฉ APIRouter โ€“ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ถ„ํ•ดํ•˜๋Š” ๊ธฐ์ˆ 


FastAPI๋กœ ๊ฐ„๋‹จํ•œ API๋ฅผ ๋งŒ๋“ค ๋•Œ๋Š” ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ๋„ ์ถฉ๋ถ„ํ•˜๋‹ค.

ํ•˜์ง€๋งŒ ํฌ๊ธฐ๊ฐ€ ์ ์  ์ปค์ง€๊ฒŒ ๋˜๋ฉด,
main.py ํŒŒ์ผ ํ•˜๋‚˜์— ์‚ฌ์šฉ์ž API, ์ƒํ’ˆ API, ์ฃผ๋ฌธ API, ์ธ์ฆ ๋กœ์ง, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์ฝ”๋“œ๊นŒ์ง€ ์ „๋ถ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.

์ˆ˜๋ฐฑ, ์ˆ˜์ฒœ ์ค„์˜ ์ฝ”๋“œ๊ฐ€ ํ•œ ํŒŒ์ผ์— ๋ชจ์ด๋ฉด

  • ์›ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ฐพ๊ธฐ ์–ด๋ ต๊ณ 
  • ์ˆ˜์ • ๋ฒ”์œ„๊ฐ€ ์ปค์ง€๊ณ 
  • ์—ฌ๋Ÿฌ ๋ช…์ด ๋™์‹œ์— ์ž‘์—…ํ•˜๋ฉด ์ถฉ๋Œ์ด ์žฆ์•„์ง„๋‹ค

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ APIRouter๋‹ค.

๊ด€๋ จ๋œ API๋“ค์„ ํŒŒ์ผ ๋‹จ์œ„๋กœ ๋ถ„๋ฆฌํ•˜๊ณ , ๋งˆ์ง€๋ง‰์— ๋ฉ”์ธ ์•ฑ์—์„œ ์กฐ๋ฆฝํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.


ํ•ต์‹ฌ ์šฉ์–ด ์ดํ•ดํ•˜๊ธฐ

๐Ÿ“ก Router (๋ผ์šฐํ„ฐ)

๐Ÿ‘‰์—ฌ๋Ÿฌ ์ปดํ“จํ„ฐ ๋„คํŠธ์›Œํฌ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฐ์ดํ„ฐ ํŒจํ‚ท์˜ ์ตœ์  ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•„ ์ „์†กํ•˜๋Š” ์žฅ๋น„

์ธํ„ฐ๋„ท์—์„œ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ๋ณด๊ณ 

"์ด ์š”์ฒญ์€ ๋ˆ„๊ตฌ์—๊ฒŒ ๋ณด๋‚ด์•ผ ํ•˜์ง€?" ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์žฅ์น˜๋‹ค.

FastAPI์˜ APIRouter๋„ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค.

HTTP ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ์–ด๋–ค ํ•จ์ˆ˜๊ฐ€ ์ฒ˜๋ฆฌํ• ์ง€ ์•ˆ๋‚ดํ•˜๋Š” ์ด์ •ํ‘œ ์—ญํ• ์„ ํ•œ๋‹ค.

๐Ÿงฑ Module (๋ชจ๋“ˆ)

๋ ˆ๊ณ  ๋ธ”๋ก์„ ๋– ์˜ฌ๋ฆฌ๋ฉด ๋œ๋‹ค.

  • ๊ฐ ๋ธ”๋ก์€ ๋…๋ฆฝ์ 
  • ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์กฐ๋ฆฝํ•˜๋ฉด ํ•˜๋‚˜์˜ ์™„์„ฑํ’ˆ

Python์—์„œ ๋ชจ๋“ˆ์€ .py ํŒŒ์ผ ํ•˜๋‚˜๋‹ค.

๊ฐ ํŒŒ์ผ์€ ๋…๋ฆฝ์ ์ธ ์ฝ”๋“œ ๋‹จ์œ„์ด๊ณ , ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์„ ์กฐํ•ฉํ•ด ํ•˜๋‚˜์˜ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ ๋‹ค.

๐Ÿ“ฆ Package (ํŒจํ‚ค์ง€)

๋ ˆ๊ณ  ๋ธ”๋ก๋“ค์„ ๋‹ด์•„๋‘๋Š” ์ƒ์ž๋‹ค.

Python์—์„œ ํŒจํ‚ค์ง€๋Š” ๋ชจ๋“ˆ๋“ค์„ ๋‹ด๊ณ  ์žˆ๋Š” ํด๋”๋‹ค.

๋‹จ, ์ผ๋ฐ˜ ํด๋”์™€ ๋‹ค๋ฅธ ์ ์ด ํ•˜๋‚˜ ์žˆ๋‹ค.

ํŒจํ‚ค์ง€ ์กฐ๊ฑด

โ€ข ํด๋” ์•ˆ์— __init__.py ํŒŒ์ผ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค
โ€ข ๋‚ด์šฉ์€ ๋น„์–ด ์žˆ์–ด๋„ ๋œ๋‹ค
โ€ข โ€œ์ด ํด๋”๋Š” ํŒจํ‚ค์ง€๋‹คโ€๋ผ๋Š” ํ‘œ์‹์ด๋‹ค

์˜ˆ์ œ ์ฝ”๋“œ

Step 1. ํ”„๋กœ์ ํŠธ ํด๋”์™€ ํŒŒ์ผ ์ƒ์„ฑ

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

Step 2. users.py ์ž‘์„ฑ

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()๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค

Step 3. main.py ์ž‘์„ฑ

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๋ฅผ ์•ฑ์— ๊ฒฐํ•ฉํ•œ๋‹ค.

Step 4. ์„œ๋ฒ„ ์‹คํ–‰ ๋ฐ ํ™•์ธ

fastapi dev app/main.py

๋ธŒ๋ผ์šฐ์ €์—์„œ ์•„๋ž˜ ์ฃผ์†Œ๋กœ ์ด๋™ํ•œ๋‹ค.

http://127.0.0.1:8000/docs

Swagger UI์—์„œ ๋‹ค์Œ ์—”๋“œํฌ์ธํŠธ๋“ค์ด ๋ณด์ด๋ฉด ์„ฑ๊ณต์ด๋‹ค.

  • GET /
  • GET /users/
  • GET /users/{username}
์ง€๊ธˆ ์ผ์–ด๋‚œ ์ผ ์ •๋ฆฌ

1. users.py์—์„œ APIRouter๋ฅผ ๋งŒ๋“ค๊ณ  API๋ฅผ ๋“ฑ๋กํ–ˆ๋‹ค
2. main.py์—์„œ include_router()๋กœ ๊ฒฐํ•ฉํ–ˆ๋‹ค
3. ์—ฌ๋Ÿฌ ํŒŒ์ผ์˜ API๊ฐ€ ํ•˜๋‚˜์˜ ์•ฑ์ฒ˜๋Ÿผ ๋™์ž‘ํ•œ๋‹ค

APIRouter ์ดํ•ดํ•˜๊ธฐ

APIRouter๋Š” FastAPI์˜ ์ถ•์†ŒํŒ

APIRouter๋Š” FastAPI์™€ ์‚ฌ์šฉ๋ฒ•์ด ๊ฑฐ์˜ ๊ฐ™๋‹ค.

์ฐจ์ด์ ์€ ๋‹จ ํ•˜๋‚˜๋‹ค.

๊ตฌ๋ถ„ FastAPI APIRouter
์—ญํ•  ๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ API ๊ทธ๋ฃน ๋ถ€ํ’ˆ
๋…๋ฆฝ ์‹คํ–‰ ๊ฐ€๋Šฅ ๋ถˆ๊ฐ€๋Šฅ
๋ฐ์ฝ”๋ ˆ์ดํ„ฐ @app.get() @router.get()

prefix๋กœ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ ๋ถ™์ด๊ธฐ

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}
prefix ๊ทœ์น™

โ€ข /๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค
โ€ข ๋์— /๋ฅผ ๋ถ™์ด๋ฉด ์•ˆ ๋œ๋‹ค

O: /users
X: /users/, users

tags๋กœ API ๋ฌธ์„œ ๊ทธ๋ฃนํ™”ํ•˜๊ธฐ

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๋กœ ๋ถ„๋ฆฌ


๐Ÿ›  Step 1. items ๋ผ์šฐํ„ฐ ์ƒ์„ฑ

touch app/routers/items.py

๐Ÿงฑ Step 2. 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) ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ
โ€ข ๋ผ์šฐํ„ฐ๋Š” ์ž๊ธฐ ๋„๋ฉ”์ธ๋งŒ ์‹ ๊ฒฝ ์“ฐ๋ฉด ๋œ๋‹ค

๐Ÿงฒ Step 3. main.py์—์„œ ๋ผ์šฐํ„ฐ ๊ฒฐํ•ฉ

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/**

๐Ÿ“ฆ import ๋ฐฉ์‹ ์ดํ•ดํ•˜๊ธฐ

1๏ธโƒฃ ์ƒ๋Œ€ ๊ฒฝ๋กœ import

from .routers import users

. ์€ ํ˜„์žฌ ํŒจํ‚ค์ง€(app)๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
ํŒจํ‚ค์ง€ ๋‚ด๋ถ€ ์ฐธ์กฐ์— ๊ฐ•ํ•˜์ง€๋งŒ, ๋‹จ๋… ์‹คํ–‰์—๋Š” ์•ฝํ•˜๋‹ค.

2๏ธโƒฃ ์ ˆ๋Œ€ ๊ฒฝ๋กœ import

from app.routers import users

๊ฒฝ๋กœ๊ฐ€ ๋ช…ํ™•ํ•˜๊ณ  IDE ์ž๋™์™„์„ฑ์ด ๊ฐ•๋ ฅํ•˜๋‹ค.
์‹ค๋ฌด์—์„œ๋Š” ์ด ๋ฐฉ์‹์„ ๋” ๋งŽ์ด ์“ด๋‹ค.

๊ตฌ๋ถ„ ์ƒ๋Œ€ import ์ ˆ๋Œ€ import
๊ฐ€๋…์„ฑ ์ค‘์ฒฉ ์‹œ ๋‚˜๋น ์ง ๋ช…ํ™•
IDE ์ง€์› ์•ฝํ•จ ๊ฐ•ํ•จ
์‹ค๋ฌด ์„ ํ˜ธ ๋‚ฎ์Œ ๋†’์Œ

๐Ÿง  ๊ณตํ†ต ์˜์กด์„ฑ ๋ถ„๋ฆฌํ•˜๊ธฐ

์ธ์ฆ, ๊ถŒํ•œ, ํ† ํฐ ๊ฒ€์ฆ ๊ฐ™์€ ๋กœ์ง์€
๋ผ์šฐํ„ฐ๋งˆ๋‹ค ๋ฐ˜๋ณตํ•˜๋ฉด ๋งํ•œ๋‹ค.

Step 1. dependencies.py

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"
        )

Step 2. ๋ผ์šฐํ„ฐ ์ „์ฒด์— ์ ์šฉ

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 ํ•จ์ˆ˜

โš ๏ธ import ์ด๋ฆ„ ์ถฉ๋Œ ๋ฐฉ์ง€

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 ์กฐ๋ฆฝ๋งŒ ๋‹ด๋‹น (๋กœ์ง ๊ธˆ์ง€)
profile
Gongbuhaja

0๊ฐœ์˜ ๋Œ“๊ธ€