
์น์์ ๋ฐ์ดํฐ๋ฅผ ์๋ฒ๋ก ๋ณด๋ด๋ ๋ฐฉ์์ ํ๋๊ฐ ์๋๋ค. ์ฐ๋ฆฌ๊ฐ ํํ ์ฌ์ฉํ๋ JSON ์ธ์๋, ์ค๋์ ๋ถํฐ ์ง๊ธ๊น์ง ๊ณ์ ์ฌ์ฉ๋๋ ๋ฐฉ์์ด ์๋ค.
๋ฐ๋ก Form Data๋ค.
Form Data๋ ๋จ์ํ ์๋ ๋ฐฉ์์ด ์๋๋ค. ๋ก๊ทธ์ธ, ํ์๊ฐ์ , ํ์ผ ์ ๋ก๋์ฒ๋ผ ์ง๊ธ๋ ๊ฐ์ฅ ๋ง์ด ์ฐ์ด๋ ํต์ฌ ๋ฐ์ดํฐ ์ ์ก ๋ฐฉ์์ด๋ค.
Form์ ๋ง ๊ทธ๋๋ก โ์์โ์ด๋ค.
์ํ์์ ๊ณ์ข๋ฅผ ๋ง๋ค ๋๋ฅผ ๋ ์ฌ๋ ค๋ณด์.
์ ํด์ง ์นธ์ ๊ฐ์ ์ฑ์์ ์ ์ถํ๋ค. ์น์ Form๋ ์ ํํ ๊ฐ์ ์ญํ ์ ํ๋ค.
HTML์ <form> ํ๊ทธ๋
๊ธฐ๋ณธ์ ์ผ๋ก Form Data ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๋ค.
FastAPI์์ Form ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ค๋ฉด ์ถ๊ฐ ํจํค์ง ํ๋๊ฐ ํ์ํ๋ค.
pip install python-multipart
FastAPI๋ ๋ด๋ถ์ ์ผ๋ก ์ด ํจํค์ง๋ฅผ ์ฌ์ฉํด Form ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ๋ค.
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}
๋ธ๋ผ์ฐ์ ์์ ๋ก๊ทธ์ธ ํผ์ ์ ์ถํ๋ฉด ์์ฒญ์ ์ด๋ ๊ฒ ์ ์ก๋๋ค.
POST /login/
Content-Type: application/x-www-form-urlencoded
username=jay&password=1234
FastAPI ๋ด๋ถ์์๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณํ๋๋ค.
login(username="jay", password="1234")
์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๋ ๋ฐฉ์์ ํฌ๊ฒ ๋ ๊ฐ์ง๋ค.
| ๊ตฌ๋ถ | 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 ํ์์ผ๋ก ์ ์กํ๋ค.
FastAPI๋ ํ๋ผ๋ฏธํฐ์ ์ถ์ฒ๋ฅผ ๋งค์ฐ ์๊ฒฉํ๊ฒ ๊ตฌ๋ถํ๋ค.
# โ ์ด๋ ๊ฒ ์ฐ๋ฉด Query ํ๋ผ๋ฏธํฐ๋ก ์ธ์
async def login(username: str, password: str):
...
# โ
Form Data๋ก ๋ฐ์ผ๋ ค๋ฉด ๋ฐ๋์ Form() ํ์
async def login(
username: Annotated[str, Form()],
password: Annotated[str, 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}
์ด ๋ชจ๋ ๊ฒ์ด 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
FastAPI๋ ์์ฒญ์ ๋ฐ์๋ง์ Content-Type์ ๋จผ์ ํ์ธํ๋ค.
application/x-www-form-urlencoded์ด๋ ๋ด๋ถ์ ์ผ๋ก python-multipart๊ฐ ๋์ํ๋ค.
์๋ํฌ์ธํธ ํจ์๊ฐ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์ด ์๋ค๋ฉด,
async def login(
username: Annotated[str, Form()],
password: Annotated[str, Form()]
):
...
FastAPI๋ ์๋์ผ๋ก ์ด๋ ๊ฒ ํธ์ถํ๋ค.
login(username="jay", password="1234")
๊ฐ๋ฐ์๊ฐ ์ง์ ํ์ฑํ ํ์๋ ์ ํ ์๋ค.
ํจ์์ ๋ฐํ๊ฐ์ ๋ค์ HTTP ์๋ต์ผ๋ก ๋ณํ๋์ด ๋ธ๋ผ์ฐ์ ๋ก ์ ๋ฌ๋๋ค.
HTTP 200 OK { "username": "jay" } ์ด ๋ชจ๋ ๊ณผ์ ์ ์๋์ผ๋ก ์ฒ๋ฆฌ๋๋ค.
Form Data๋ฅผ ๋ฐฐ์ฐ๋ค ๋ณด๋ฉด ๋ฐ๋์ ํ ๋ฒ์ ์ด๋ฐ ์ง๋ฌธ์ด ๋์จ๋ค.
โForm์ผ๋ก username ๋ฐ๊ณ , JSON์ผ๋ก ๋ค๋ฅธ ๋ฐ์ดํฐ๋ ๊ฐ์ด ๋ฐ์ผ๋ฉด ์ ๋๋์?โ
์ ๋ต์ โ ๋ถ๊ฐ๋ฅ์ด๋ค.
HTTP ์์ฒญ์ Body๋ ํ๋์ Content-Type๋ง ๊ฐ์ง ์ ์๋ค.
| ๊ตฌ๋ถ | Content-Type |
|---|---|
| JSON | application/json |
| Form Data | application/x-www-form-urlencoded |
์ฆ,
python-multipart ์ค์นfrom fastapi import FormAnnotated[ํ์
, Form()] ์ฌ์ฉ| ์ํฉ | ์ด์ |
|---|---|
| ๋ก๊ทธ์ธ / ํ์๊ฐ์ | HTML Form ํ์ค |
| OAuth2 ์ธ์ฆ | ์คํ์์ Form ์ฌ์ฉ |
| ํ์ผ ์ ๋ก๋ | multipart/form-data ํ์ |
| ๋ ๊ฑฐ์ ์์คํ | JSON ๋ฏธ์ง์ ํ๊ฒฝ |