Backend Framework/FastAPI

03. FastAPI - Request Body(JSON), Form(HTML) 처리

Python Developer 2025. 4. 22. 21:26

FastAPI - Request Body 및 Form 데이터 처리

FastAPI에서는 클라이언트로부터 데이터를 받을 때, 전송 방식에 따라 JSON(Request Body) 또는 Form(FormData)으로 분리하여 처리할 수 있다. 요청 방식에 따라 HTTP 요청 헤더의 Content-Type이 달라지고, FastAPI는 이를 기반으로 적절하게 데이터를 파싱한다.


📦 Request Body 처리 (application/json)

✅ 기본 사용: Pydantic 모델 기반 요청

from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None

@app.post("/items/")
async def create_item(item: Item):
    return item

 

요청 예시 (curl)

curl -X 'POST' 'http://localhost:8000/items/' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Laptop",
    "price": 999.99,
    "tax": 10.0
}'

 

응답 예시

{
  "name": "Laptop",
  "description": null,
  "price": 999.99,
  "tax": 10.0
}

✅ 계산 포함 응답 처리

@app.post("/items/with-tax/")
async def create_item_with_tax(item: Item):
    item_dict = item.model_dump()
    if item.tax:
        item_dict["price_with_tax"] = item.price + item.tax
    return item_dict

 

요청

curl -X 'POST' 'http://localhost:8000/items/with-tax/' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Desk",
    "price": 150.0,
    "tax": 15.0
}'

 

응답

{
  "name": "Desk",
  "description": null,
  "price": 150.0,
  "tax": 15.0,
  "price_with_tax": 165.0
}

✅ Path + Query + Request Body 함께 사용

@app.put("/items/{item_id}/")
async def update_item(item_id: int, item: Item, q: Optional[str] = None):
    result = {"item_id": item_id, **item.model_dump()}
    if q:
        result["q"] = q
    return result

 

요청

curl -X 'PUT' 'http://localhost:8000/items/1/?q=search-keyword' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Tablet",
    "price": 299.99
}'

 

응답

{
  "item_id": 1,
  "name": "Tablet",
  "description": null,
  "price": 299.99,
  "tax": null,
  "q": "search-keyword"
}

✅ 다중 Request Body 처리

class User(BaseModel):
    username: str
    full_name: Optional[str] = None

@app.put("/items/{item_id}/with-user/")
async def update_item_with_user(item_id: int, item: Item, user: User):
    return {"item_id": item_id, "item": item, "user": user}

 

요청

curl -X 'PUT' 'http://localhost:8000/items/5/with-user/' \
  -H 'Content-Type: application/json' \
  -d '{
    "item": {
      "name": "Monitor",
      "price": 199.99
    },
    "user": {
      "username": "johndoe",
      "full_name": "John Doe"
    }
}'

 

응답

{
  "item_id": 5,
  "item": {
    "name": "Monitor",
    "description": null,
    "price": 199.99,
    "tax": null
  },
  "user": {
    "username": "johndoe",
    "full_name": "John Doe"
  }
}

📝 Form 데이터 처리 (application/x-www-form-urlencoded)

✅ 기본 Form 처리

from fastapi import FastAPI, Form
from typing import Annotated

app = FastAPI()

@app.post("/login/")
async def login(
    username: str = Form(),
    email: str = Form(),
    country: Annotated[str, Form()] = None
):
    return {
        "username": username,
        "email": email,
        "country": country
    }

 

요청 예시

curl -X 'POST' 'http://localhost:8000/login/' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'username=alice&email=alice@example.com&country=KR'

 

응답

{
  "username": "alice",
  "email": "alice@example.com",
  "country": "KR"
}

✅ Path + Query + Form 혼합 사용

@app.post("/login/{login_type}/")
async def login_with_path_query(
    login_type: int,
    q: Optional[str] = None,
    username: str = Form(),
    email: str = Form(),
    country: Annotated[str, Form()] = None
):
    return {
        "login_type": login_type,
        "q": q,
        "username": username,
        "email": email,
        "country": country
    }

 

요청 예시

curl -X 'POST' 'http://localhost:8000/login/2/?q=fastapi' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'username=bob&email=bob@example.com&country=US'

 

응답

{
  "login_type": 2,
  "q": "fastapi",
  "username": "bob",
  "email": "bob@example.com",
  "country": "US"
}

✅ 요약

요청 방식 Content-Type 처리 방식
JSON Body application/json Pydantic 모델 사용
Form application/x-www-form-urlencoded Form() 사용
  • 요청의 Content-Type에 따라 적절한 파라미터 처리 방식이 필요하다.
  • FastAPI는 타입 힌트를 기반으로 자동 유효성 검사 및 문서 생성을 지원한다.