
FastAPI์์ Body ํ๋ผ๋ฏธํฐ๋ ๋จ์ํ โ์์ฒญ์ JSON์ ๋ด๋๋คโ ์์ค์ ๋์ด์ API ์ค๊ณ์ ๊ตฌ์กฐ ์์ฒด๋ฅผ ๊ฒฐ์ ํ๋ ์์๋ค.
์ด๋ฒ ๊ธ์์๋ Request Body์ ์ฌ๋ฌ ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ด๋ ๊ฒฝ์ฐ, FastAPI๊ฐ ์ด๋ฅผ ์ด๋ป๊ฒ ํด์ํ๊ณ ์ฒ๋ฆฌํ๋์ง๋ฅผ ๋จ๊ณ์ ์ผ๋ก ์ ๋ฆฌํ๋ค.
Body๋ ์์ด๋ก ๋ชธํต์ ์๋ฏธํ๋ค. HTTP ์์ฒญ๋ ์ฌ๋์ฒ๋ผ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋ค.
| ๊ตฌ์ฑ ์์ | ์ญํ | ์ฌ๋์ผ๋ก ๋น์ ํ๋ฉด |
|---|---|---|
| Header | ์์ฒญ์ ๋ฉํ ์ ๋ณด | ๋จธ๋ฆฌ (์๊ฐ, ํ๋จ) |
| Body | ์ค์ ์ ๋ฌ ๋ฐ์ดํฐ | ๋ชธํต (ํต์ฌ ๋ด์ฉ๋ฌผ) |
Parameter๋ ํจ์์ ์ ๋ฌ๋๋ ์ ๋ ฅ๊ฐ์ด๋ค.
| ํ๋ผ๋ฏธํฐ ์ ํ | ์ ๋ฌ ์์น | ํ๋ฐฐ ๋น์ |
|---|---|---|
| Path | /items/{item_id} | ๋ฐฐ์ก์ง ์ฃผ์ |
| Query | ?q=๊ฒ์์ด | ๋ฐฐ์ก ์์ฒญ์ฌํญ |
| Body | HTTP ์์ฒญ ๋ณธ๋ฌธ | ์์ ์ ๋ด์ฉ๋ฌผ |
์ด๋ฒ ๊ธ์ ํต์ฌ์ โBody ์์ ์ฌ๋ฌ ๊ฐ์ ์์๋ฅผ ๋ฃ์ผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?โ์ด๋ค.
# ํ๋ก์ ํธ ํด๋ ์์ฑ
mkdir fastapi-body-params
cd fastapi-body-params
# ๊ฐ์ํ๊ฒฝ ์์ฑ
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# FastAPI ์ค์น
pip install "fastapi[standard]"
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
return {
"item_id": item_id,
"item": item
}
โข ํด๋ผ์ด์ธํธ๋ JSON ๊ฐ์ฒด๋ฅผ ๋ณด๋ด์ผ ํ๋ค
โข ํ์ ํ๋: name, price
โข ์ ํ ํ๋: description, tax
โข ํ์
์ด ๋ค๋ฅด๋ฉด ์์ฒญ ๋จ๊ณ์์ ์๋์ผ๋ก ๊ฑฐ๋ถ๋จ
ํ ์คํธ: Swagger UI์์ ํด๋น Request Body ์ ๋ ฅ ํ "Try it out" ํด๋ฆญ
{
"name": "๋
ธํธ๋ถ",
"description": "๊ฐ๋ฐ์ฉ ๋งฅ๋ถ",
"price": 2500000,
"tax": 250000
}
๊ฒฐ๊ณผ:
โ 1. Path ํ๋ผ๋ฏธํฐ ์ ์ ์์
โ URL์ {item_id}๊ฐ ์ ํํ ๋งคํ๋จ
โ 2. Request Body๊ฐ ๋ชจ๋ธ๋ก ํ์ฑ๋จ
โ JSON โ Item ๊ฐ์ฒด โ ๋ค์ JSON
์ด์ Body ํ๋ผ๋ฏธํฐ๋ฅผ ํ๋ ๋ ์ถ๊ฐํด๋ณด์.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
class User(BaseModel):
username: str
full_name: str | None = None
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Item,
user: User
):
return {
"item_id": item_id,
"item": item,
"user": user
}
Swagger UI์์ ํ์ธํ๋ฉด Request Body์ ํํ๊ฐ ๋ฌ๋ผ์ง ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ณ๊ฒฝ๋ Request Body๊ตฌ์กฐ:
{
"item": {
"name": "๋
ธํธ๋ถ",
"description": "๊ฐ๋ฐ์ฉ ๋งฅ๋ถ",
"price": 2500000,
"tax": 250000
},
"user": {
"username": "Jay",
"full_name": "๊น์ข
์ธ"
}
}
๊ฒฐ๊ณผ:

ํ๋ผ๋ฏธํฐ๊ฐ 2๊ฐ๊ฐ ๋๋๊น ๊ฐ ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ด key๊ฐ ๋๊ณ , ๊ทธ ์์ ๋ชจ๋ธ์ ํ๋๊ฐ ๋ค์ด๊ฐ๋ค. ๐ FastAPI๊ฐ ์๋์ผ๋ก ์ด๋ ๊ฒ ์ฒ๋ฆฌํด์ค!
| Body ํ๋ผ๋ฏธํฐ ๊ฐ์ | JSON ๊ตฌ์กฐ |
|---|---|
| 1๊ฐ | ๋ชจ๋ธ ํ๋๊ฐ ์ต์์ |
| 2๊ฐ ์ด์ | ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ด ํค๊ฐ ๋จ |
์ด ๋์์ ์ต์ ์ด ์๋๋ผ FastAPI์ ๊ธฐ๋ณธ ๊ท์น์ด๋ค.
์ด์ โ์ FastAPI๊ฐ ์ด๋ ๊ฒ ๋์ํ๋์งโ๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ์ ๋ฆฌํด๋ณด์. ํต์ฌ์ FastAPI์ ํ๋ผ๋ฏธํฐ ์๋ ์ธ์ ๊ท์น์ด๋ค.
FastAPI๋ ํจ์์ ์๊ทธ๋์ฒ๋ง ๋ณด๊ณ ๊ฐ ํ๋ผ๋ฏธํฐ๋ฅผ ์ด๋์์ ๊ฐ์ ธ์ฌ์ง ์๋์ผ๋ก ๊ฒฐ์ ํ๋ค.
| ํ๋จ ๊ธฐ์ค | ํ๋ผ๋ฏธํฐ ์ ํ |
|---|---|
| URL ๊ฒฝ๋ก์ {์ด๋ฆ}์ด ์กด์ฌ | Path Parameter |
| Pydantic ๋ชจ๋ธ ํ์ | Body Parameter |
| ๋จ์ ํ์ (int, str, float ๋ฑ) | Query Parameter |
ํ๋์ API์์ Path ยท Query ยท Body๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ ์์ ๋ฅผ ๋ณด์.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.put("/items/{item_id}")
async def update_item(
item_id: int, # Path
item: Item, # Body
q: str | None = None # Query
):
result = {
"item_id": item_id,
"item": item
}
if q:
result["q"] = q
return result
FastAPI๋ ๋ค์๊ณผ ๊ฐ์ด ํด์ํ๋ค.
item_id โ URL์ ์์ผ๋ฏ๋ก Pathitem โ Pydantic ๋ชจ๋ธ์ด๋ฏ๋ก Bodyq โ ๋จ์ ํ์
+ ๊ธฐ๋ณธ๊ฐ โ Query์ Body ํ๋ผ๋ฏธํฐ๊ฐ 2๊ฐ ์ด์์ด๋ฉด JSON ๊ตฌ์กฐ๊ฐ ๋ฐ๋๊น?
์ด์ ๋ ๋จ์ํ๋ค.
Body ํ๋ผ๋ฏธํฐ๊ฐ 1๊ฐ์ผ ๋๋ ๋ชจํธํ์ง ์๋ค.
{
"name": "๋
ธํธ๋ถ",
"price": 2500000
}
ํ์ง๋ง Body ํ๋ผ๋ฏธํฐ๊ฐ 2๊ฐ๋ผ๋ฉด?
{
"name": "๋
ธํธ๋ถ",
"price": 2500000,
"username": "jay"
}
์ด ๊ตฌ์กฐ์์๋ ์ด๋๊น์ง๊ฐ Item์ด๊ณ , ์ด๋๋ถํฐ User์ธ์ง ๊ตฌ๋ถํ ์ ์๋ค.
๊ทธ๋์ FastAPI๋ ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ JSON์ ํค๋ก ์ฌ์ฉํ๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก int, str ๊ฐ์ ๋จ์ ํ์
์
Query ํ๋ผ๋ฏธํฐ๋ก ์ธ์๋๋ค.
ํ์ง๋ง ๋จ์ ๊ฐ๋ Body์ ๋ฃ๊ณ ์ถ๋ค๋ฉด
Body()๋ฅผ ์ฌ์ฉํ๋ค.
from fastapi import FastAPI, Body
from pydantic import BaseModel
from typing import Annotated
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Item,
importance: Annotated[int, Body()]
):
return {
"item_id": item_id,
"item": item,
"importance": importance
}
์์ฒญ Body๋ ๋ค์๊ณผ ๊ฐ๋ค.
{
"item": {
"name": "๋
ธํธ๋ถ",
"price": 2500000
},
"importance": 5
}
Body ํ๋ผ๋ฏธํฐ๊ฐ 1๊ฐ์ผ ๋๋
JSON์ ํค๋ก ๊ฐ์ธ๊ณ ์ถ๋ค๋ฉด embed=True๋ฅผ ์ฌ์ฉํ๋ค.
from fastapi import FastAPI, Body
from pydantic import BaseModel
from typing import Annotated
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Annotated[Item, Body(embed=True)]
):
return {
"item_id": item_id,
"item": item
}
์์ฒญ JSON ๋น๊ต:
| ์ต์ | JSON ๊ตฌ์กฐ |
|---|---|
| embed=False (๊ธฐ๋ณธ) | |
| embed=True | |
| ๊ฐ๋ | ํต์ฌ ์์ฝ |
|---|---|
| Body 1๊ฐ | ๋ชจ๋ธ ํ๋๊ฐ ์ต์์ |
| Body 2๊ฐ ์ด์ | ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ผ๋ก ์๋ ๊ฐ์ |
| ๋จ์ ํ์ | ๊ธฐ๋ณธ์ Query |
| Body() | ๋จ์ ํ์ ์ Body๋ก ์ฒ๋ฆฌ |
| embed=True | ๋จ์ผ Body๋ ํค๋ก ๊ฐ์ |