FastAPI - Form Data

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

FastAPI

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

๐Ÿ“ Form Data โ€“ ํผ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

์›น์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์€ ํ•˜๋‚˜๊ฐ€ ์•„๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” JSON ์™ธ์—๋„, ์˜ค๋ž˜์ „๋ถ€ํ„ฐ ์ง€๊ธˆ๊นŒ์ง€ ๊ณ„์† ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ์‹์ด ์žˆ๋‹ค.

๋ฐ”๋กœ Form Data๋‹ค.

Form Data๋Š” ๋‹จ์ˆœํ•œ ์˜›๋‚  ๋ฐฉ์‹์ด ์•„๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž…, ํŒŒ์ผ ์—…๋กœ๋“œ์ฒ˜๋Ÿผ ์ง€๊ธˆ๋„ ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ์ด๋Š” ํ•ต์‹ฌ ๋ฐ์ดํ„ฐ ์ „์†ก ๋ฐฉ์‹์ด๋‹ค.


๐Ÿ“Œ 1. Form์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€

Form์€ ๋ง ๊ทธ๋Œ€๋กœ โ€œ์–‘์‹โ€์ด๋‹ค.

์€ํ–‰์—์„œ ๊ณ„์ขŒ๋ฅผ ๋งŒ๋“ค ๋•Œ๋ฅผ ๋– ์˜ฌ๋ ค๋ณด์ž.

  • ์ด๋ฆ„
  • ์ „ํ™”๋ฒˆํ˜ธ
  • ์ฃผ์†Œ

์ •ํ•ด์ง„ ์นธ์— ๊ฐ’์„ ์ฑ„์›Œ์„œ ์ œ์ถœํ•œ๋‹ค. ์›น์˜ Form๋„ ์ •ํ™•ํžˆ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค.

๐Ÿ’ก Form์€
์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ๋ฅผ
์ •ํ•ด์ง„ ํ˜•์‹์œผ๋กœ ์„œ๋ฒ„์— ์ „๋‹ฌํ•˜๋Š” ๋„๊ตฌ๋‹ค

HTML์˜ <form> ํƒœ๊ทธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Form Data ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•œ๋‹ค.


โš™๏ธ 2. FastAPI์—์„œ Form Data ์ง์ ‘ ๋ฐ›์•„๋ณด๊ธฐ

FastAPI์—์„œ Form ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ์ถ”๊ฐ€ ํŒจํ‚ค์ง€ ํ•˜๋‚˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๐Ÿ“ฆ ํ•„์ˆ˜ ํŒจํ‚ค์ง€ ์„ค์น˜

pip install python-multipart

FastAPI๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์ด ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•ด Form ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•œ๋‹ค.

โš ๏ธ ์ด ํŒจํ‚ค์ง€๊ฐ€ ์—†์œผ๋ฉด
Form Data ์š”์ฒญ์€ ์•„์˜ˆ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค

๐Ÿงช ์ฒซ ๋ฒˆ์งธ Form API

from typing import Annotated
from fastapi import FastAPI, Form
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.get("/", response_class=HTMLResponse)
async def read_root():
    with open("login.html", "r", encoding="utf-8") as f:
        return f.read()

@app.post("/login/")
async def login(
    username: Annotated[str, Form()],
    password: Annotated[str, Form()]
):
    return {"username": username}
โœ… Annotated[ํƒ€์ž…, Form()]
โ†’ ์ด ๊ฐ’์€ Form Data๋กœ ๋“ค์–ด์˜จ๋‹ค

๐Ÿงญ ์‹ค์ œ๋กœ ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์งˆ๊นŒ?

๋ธŒ๋ผ์šฐ์ €์—์„œ ๋กœ๊ทธ์ธ ํผ์„ ์ œ์ถœํ•˜๋ฉด ์š”์ฒญ์€ ์ด๋ ‡๊ฒŒ ์ „์†ก๋œ๋‹ค.

POST /login/
Content-Type: application/x-www-form-urlencoded

username=jay&password=1234

FastAPI ๋‚ด๋ถ€์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ™˜๋œ๋‹ค.

login(username="jay", password="1234")

๐Ÿง  3. Form ๋ฐ์ดํ„ฐ์˜ ์›๋ฆฌ

์„œ๋ฒ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๋‹ค.

๊ตฌ๋ถ„ JSON Form Data
Content-Type application/json application/x-www-form-urlencoded
๋ฐ์ดํ„ฐ ํ˜•ํƒœ {"username": "jeff"} username=jeff&password=1234
์ฃผ ์‚ฌ์šฉ์ฒ˜ API ํ†ต์‹ , SPA HTML ํผ, ๋กœ๊ทธ์ธ

HTML์˜ <form> ํƒœ๊ทธ๋Š” ๋ฌด์กฐ๊ฑด Form Data ํ˜•์‹์œผ๋กœ ์ „์†กํ•œ๋‹ค.

โ“ ์™œ Form()์„ ๊ผญ ์จ์•ผ ํ• ๊นŒ?

FastAPI๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ถœ์ฒ˜๋ฅผ ๋งค์šฐ ์—„๊ฒฉํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•œ๋‹ค.

# โŒ ์ด๋ ‡๊ฒŒ ์“ฐ๋ฉด Query ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ธ์‹
async def login(username: str, password: str):
    ...

# โœ… Form Data๋กœ ๋ฐ›์œผ๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ Form() ํ•„์š”
async def login(
    username: Annotated[str, Form()],
    password: Annotated[str, Form()]
):
    ...
โš ๏ธ Form()์„ ์ƒ๋žตํ•˜๋ฉด
FastAPI๋Š” ์ด ๊ฐ’์„ Query ๋˜๋Š” JSON์œผ๋กœ ํ•ด์„ํ•œ๋‹ค

๐Ÿ”ฌ Form ํด๋ž˜์Šค์˜ ์ •์ฒด

Form์€ ๋‚ด๋ถ€์ ์œผ๋กœ Body๋ฅผ ์ƒ์†ํ•œ๋‹ค.

๊ทธ๋ž˜์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ต์…˜๋“ค์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

async def signup(
    username: Annotated[str, Form(min_length=3, max_length=20)],
    user_email: Annotated[str, Form(alias="email")],
    nickname: Annotated[str | None, Form()] = None
):
    return {"username": username, "email": user_email}
  • ๊ธธ์ด ์ œํ•œ
  • ํ•„๋“œ ์ด๋ฆ„ ๋งคํ•‘(alias)
  • ์„ ํƒ ๊ฐ’(None)

์ด ๋ชจ๋“  ๊ฒƒ์ด Form Data์—์„œ๋„ ๊ทธ๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค.

๐Ÿ“ค ์ „์ฒด ์š”์ฒญ ํ๋ฆ„

 [๋ธŒ๋ผ์šฐ์ €]
   |
   | POST /login/
   | Content-Type: application/x-www-form-urlencoded
   | Body: username=jeff&password=1234
   v
[FastAPI]
   |
   | python-multipart
   | โ†’ Form ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ
   v
[์—”๋“œํฌ์ธํŠธ ํ•จ์ˆ˜]
   |
   | login(username="jeff", password="1234")
   v
[์‘๋‹ต ๋ฐ˜ํ™˜]
   |
   | HTTP 200 OK
   | {"username": "jeff"}
   v
[๋ธŒ๋ผ์šฐ์ €]

๐Ÿงฉ ๋‹จ๊ณ„๋ณ„๋กœ ๋œฏ์–ด๋ณด๊ธฐ

โ‘  ๋ธŒ๋ผ์šฐ์ € โ†’ ์„œ๋ฒ„ ์š”์ฒญ

HTML <form> ํƒœ๊ทธ๋ฅผ ํ†ตํ•ด ์ „์†ก๋œ ์š”์ฒญ์€ ํ•ญ์ƒ Form Data ํ˜•์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

POST /login/ 
Content-Type: application/x-www-form-urlencoded 
username=jay&password=1234 
  • JSON ์•„๋‹˜
  • Key=Value ํ˜•ํƒœ
  • & ๋กœ ํ•„๋“œ ์—ฐ๊ฒฐ

โ‘ก FastAPI ๋‚ด๋ถ€ ์ฒ˜๋ฆฌ

FastAPI๋Š” ์š”์ฒญ์„ ๋ฐ›์ž๋งˆ์ž Content-Type์„ ๋จผ์ € ํ™•์ธํ•œ๋‹ค.

  • application/x-www-form-urlencoded
  • โ†’ Form Data ์š”์ฒญ์ด๋ผ๊ณ  ํŒ๋‹จ

์ด๋•Œ ๋‚ด๋ถ€์ ์œผ๋กœ python-multipart๊ฐ€ ๋™์ž‘ํ•œ๋‹ค.

๐Ÿ’ก python-multipart์˜ ์—ญํ• 
Form์œผ๋กœ ๋“ค์–ด์˜จ ๋ฌธ์ž์—ด์„
FastAPI๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜

โ‘ข ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ž๋™ ์ฃผ์ž…

์—”๋“œํฌ์ธํŠธ ํ•จ์ˆ˜๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋˜์–ด ์žˆ๋‹ค๋ฉด,

async def login(
    username: Annotated[str, Form()],
    password: Annotated[str, Form()]
):
    ...

FastAPI๋Š” ์ž๋™์œผ๋กœ ์ด๋ ‡๊ฒŒ ํ˜ธ์ถœํ•œ๋‹ค.

 login(username="jay", password="1234") 

๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ํŒŒ์‹ฑํ•  ํ•„์š”๋Š” ์ „ํ˜€ ์—†๋‹ค.


โ‘ฃ ์‘๋‹ต ๋ฐ˜ํ™˜ โ†’ ๋ธŒ๋ผ์šฐ์ €

ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์€ ๋‹ค์‹œ HTTP ์‘๋‹ต์œผ๋กœ ๋ณ€ํ™˜๋˜์–ด ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „๋‹ฌ๋œ๋‹ค.

 HTTP 200 OK { "username": "jay" } 

์ด ๋ชจ๋“  ๊ณผ์ •์€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค.


โš ๏ธ Form๊ณผ JSON์„ ํ•จ๊ป˜ ์“ธ ์ˆ˜ ์—†๋Š” ์ด์œ 

Form Data๋ฅผ ๋ฐฐ์šฐ๋‹ค ๋ณด๋ฉด ๋ฐ˜๋“œ์‹œ ํ•œ ๋ฒˆ์€ ์ด๋Ÿฐ ์งˆ๋ฌธ์ด ๋‚˜์˜จ๋‹ค.

โ€œForm์œผ๋กœ username ๋ฐ›๊ณ , JSON์œผ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋„ ๊ฐ™์ด ๋ฐ›์œผ๋ฉด ์•ˆ ๋˜๋‚˜์š”?โ€

์ •๋‹ต์€ โŒ ๋ถˆ๊ฐ€๋Šฅ์ด๋‹ค.

๐Ÿšซ ์™œ ๋ถˆ๊ฐ€๋Šฅํ• ๊นŒ?

HTTP ์š”์ฒญ์˜ Body๋Š” ํ•˜๋‚˜์˜ Content-Type๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

๊ตฌ๋ถ„ Content-Type
JSON application/json
Form Data application/x-www-form-urlencoded

์ฆ‰,

  • Form ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด โ†’ Form ์š”์ฒญ
  • JSON Body๋ฅผ ๋™์‹œ์— ๋ฐ›์„ ์ˆ˜ ์—†์Œ
โš ๏ธ ์ด๊ฒƒ์€ FastAPI์˜ ์ œํ•œ์ด ์•„๋‹ˆ๋ผ
HTTP ํ”„๋กœํ† ์ฝœ ์ž์ฒด์˜ ์ œ์•ฝ์ด๋‹ค

๐Ÿง  ์ถ”๊ฐ€๋กœ ๋ฐ˜๋“œ์‹œ ์•Œ์•„์•ผ ํ•  ํ•ต์‹ฌ ๊ฐœ๋…

โœ” Form ์‚ฌ์šฉ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • โ˜‘ python-multipart ์„ค์น˜
  • โ˜‘ from fastapi import Form
  • โ˜‘ Annotated[ํƒ€์ž…, Form()] ์‚ฌ์šฉ
  • โ˜‘ JSON Body์™€ ํ˜ผ์šฉํ•˜์ง€ ์•Š๊ธฐ

โœ” ์–ธ์ œ Form์„ ์‚ฌ์šฉํ• ๊นŒ?

์ƒํ™ฉ ์ด์œ 
๋กœ๊ทธ์ธ / ํšŒ์›๊ฐ€์ž… HTML Form ํ‘œ์ค€
OAuth2 ์ธ์ฆ ์ŠคํŽ™์—์„œ Form ์‚ฌ์šฉ
ํŒŒ์ผ ์—…๋กœ๋“œ multipart/form-data ํ•„์š”
๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ JSON ๋ฏธ์ง€์› ํ™˜๊ฒฝ

๐Ÿ“Œ 5. ์ตœ์ข… ์ •๋ฆฌ

  • Form Data๋Š” HTML์˜ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ์ „์†ก ๋ฐฉ์‹์ด๋‹ค
  • FastAPI์—์„œ๋Š” Form()์„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค
  • Form ์š”์ฒญ์€ python-multipart๊ฐ€ ํŒŒ์‹ฑํ•œ๋‹ค
  • Form๊ณผ JSON์€ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค
profile
Gongbuhaja

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