
FastAPI์์ Path Parameter๋ URL ๊ฒฝ๋ก ์์ฒด์ ๋ณ์๋ฅผ ํฌํจํด ๋์ ์ผ๋ก ๋ค๋ฅธ ๋ฆฌ์์ค๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํต์ฌ ๊ธฐ๋ฅ์ด๋ค.
๊ฐ๋ ์ ์ธ์ ๋ ์ด๋ฆ๋ถํฐ ์ดํดํ๋ฉด ๊ฐ์ฅ ๋น ๋ฅด๋ค.
์ปดํจํฐ์์ ํ์ผ์ ์ฐพ์ ๋
/home/user/file.txt
์ฒ๋ผ โ์ด๋๋ก ๊ฐ์ผ ํ๋์งโ๋ฅผ ๊ฒฝ๋ก(Path)๋ก ํํํ๋ฏ, ์น์์๋ ํน์ ๋ฆฌ์์ค๋ฅผ ์ฐพ๊ธฐ ์ํด URL ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ ๊ฒฝ๋ก ์์ ๋ณํ ์ ์๋ ๊ฐ์ ๋ฃ๋ ๊ฒ์ด ๋ฐ๋ก Path Parameter๋ค.
Path Parameter๋ Python์ ๋ฌธ์์ด ํฌ๋งทํ ๊ณผ ๊ฑฐ์ ๊ฐ์ ๊ฐ๋ ์ด๋ค.
name = "์ฒ ์"
print(f"Hello {name}")
์ค๊ดํธ ์์ {name} ์์น์ ๊ฐ์ด ๋ค์ด๊ฐ๋ฏ,
/users/{user_id}
์ฌ๊ธฐ์ {user_id} ์๋ฆฌ์ ์ค์ ๊ฐ์ด ๋ค์ด์จ๋ค.
๋ง๋ก๋ง ๋ณด๋ฉด ๊ฐ์ด ์ ์จ๋ค. ๊ฐ์ฅ ๋จ์ํ ์์ ๋ถํฐ ๋ฐ๋ก ์คํํด๋ณด์.
from fastapi import FastAPI
app = FastAPI()
# {item_id} ๊ฐ Path Parameter๋ค
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
์ฌ๊ธฐ์ ์ค์ํ ํฌ์ธํธ๋ ๋ฑ ๋ ๊ฐ์ง๋ค.
{item_id}๊ฐ ์๋คitem_id๋ก ๋์ผํ๋ค์๋ฒ๋ฅผ ์คํํ ๋ค ๋ธ๋ผ์ฐ์ ์์ ์๋ ์ฃผ์๋ค์ ์ ์ํด๋ณด์.
/items/abc โ {"item_id": "abc"}/items/123 โ {"item_id": "123"}/items/jeff โ {"item_id": "jeff"}
URL์ {item_id} ์์น์ ๋ฌด์์ ๋ฃ๋ ,
๊ทธ ๊ฐ์ด ๊ทธ๋๋ก ํจ์์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋๋ค.
๐ URL ๊ฒฝ๋ก = ํจ์ ์ธ์ ์ ๋ฌ ํต๋ก
์ง๊ธ๊น์ง์ ์์ ์์๋ item_id๊ฐ ๋ฌธ์์ด๋ก ๋ค์ด์๋ค.
ํ์ง๋ง FastAPI์์๋ ํ์ ํํธ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ๊ฐ์ด ์๋์ผ๋ก ๋ณํ๋๋ค.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
์ด์ item_id๋ ๋ฌธ์์ด์ด ์๋๋ผ
์ ์(int)๋ก ์ฒ๋ฆฌ๋๋ค.
/items/3 โ {"item_id": 3}"3" โ ์ ์ 3์ผ๋ฐ์ ์ธ ์น ํ๋ ์์ํฌ๋ผ๋ฉด ๋ณดํต ์ด๋ฐ ์ฝ๋๊ฐ ํ์ํ๋ค.
item_id = int(item_id)
ํ์ง๋ง FastAPI์์๋
ํ์ ํํธ ํ ์ค๋ก "๋ณํ + ๊ฒ์ฆ"๊น์ง ๋ชจ๋ ์๋์ผ๋ก ์ฒ๋ฆฌ๋๋ค.ํ์ ์ ์ ์ธํ๋ฉด, ์๋ชป๋ ๊ฐ์ด ๋ค์ด์์ ๋๋ FastAPI๊ฐ ์์์ ์ฒ๋ฆฌํ๋ค.
์๋ ์์ฒญ์ ๋ณด๋ด๋ณด์.
/items/foo
item_id๋ int๋ก ์ ์ธ๋์ด ์๋๋ฐ,
๋ฌธ์์ด "foo"๊ฐ ๋ค์ด์๋ค.
์ด ๊ฒฝ์ฐ FastAPI๋
{
"detail": [
{
"type": "int_parsing",
"loc": ["path", "item_id"],
"msg": "Input should be a valid integer",
"input": "foo"
}
]
}
ํ์ ํํธ ํ๋๋ง ์ถ๊ฐํ์ ๋ฟ์ธ๋ฐ, API ๋ฌธ์๊น์ง ์๋์ผ๋ก ๋ฐ๋๋ค.
/docs/redoc๋ฌธ์ ํ๋ฉด์์ ํ์ธํ ์ ์๋ ๋ณํ:
item_id๊ฐ int ํ์
์ผ๋ก ํ์Path Parameter๋ฅผ ์ฐ๋ค ๋ณด๋ฉด โ์ ์ด ์๋ํฌ์ธํธ๊ฐ ์ ํ์ง?โ ๊ฐ์ ์ํฉ์ ํ ๋ฒ์ฏค ๊ฒช๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์์ธ์ ๊ฒฝ๋ก(Path) ๋งค์นญ ์์๋ค.
FastAPI๋ ๊ฒฝ๋ก๋ฅผ ์์์ ์๋๋ก ์ฐจ๋ก๋๋ก ํ์ธํ๋ฉด์ โ๊ฐ์ฅ ๋จผ์ ๋งค์นญ๋๋โ ๋ผ์ฐํธ๋ฅผ ์ ํํ๋ค. ์ฆ, ์ ์ธ ์์๊ฐ ๊ณง ์ฐ์ ์์๋ค.
from fastapi import FastAPI
app = FastAPI()
# โ
๊ณ ์ ๊ฒฝ๋ก ๋จผ์
@app.get("/users/me")
async def read_user_me():
return {"user_id": "ํ์ฌ ๋ก๊ทธ์ธํ ์ฌ์ฉ์"}
# โ
๋์ ๊ฒฝ๋ก๋ ๋์ค์
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
์ด ์ํ์์ ์์ฒญ์ ๋ณด๋ด๋ฉด ์๋๋๋ก ๋์ํ๋ค.
/users/me โ read_user_me() ์คํ/users/123 โ read_user() ์คํ (user_id="123")from fastapi import FastAPI
app = FastAPI()
# โ ๋์ ๊ฒฝ๋ก๊ฐ ๋จผ์
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
# โ ๊ณ ์ ๊ฒฝ๋ก๊ฐ ๋์ค
@app.get("/users/me")
async def read_user_me():
return {"user_id": "ํ์ฌ ๋ก๊ทธ์ธํ ์ฌ์ฉ์"}
์ด ๊ฒฝ์ฐ /users/me ์์ฒญ์ด ๋ค์ด์ค๋ฉดโฆ
/users/{user_id} ๋ /users/me ์๋ ๋งค์นญ๋๋ค.user_id="me" ๋ก ํด์ํด๋ฒ๋ฆฐ๋ค.์ฆ, ๊ฒฐ๊ณผ๊ฐ ์ด๋ ๊ฒ ๋๋ค:
/users/me โ read_user() ์คํ (์๋์ ๋ค๋ฆ)์ด๊ฑด ๋จ์ํ โ๊ฒฐ๊ณผ๊ฐ ์ด์ํ๋คโ์์ ๋๋์ง ์๋๋ค.
๊ทธ๋์ ์ค๋ฌด์์๋ ์ด ์์ ๊ท์น์ ๊ฑฐ์ โ๊ท์นโ์ด ์๋๋ผ โ๋ฒโ์ฒ๋ผ ๋ค๋ฃฌ๋ค.
๋ผ์ฐํฐ๋ฅผ ์ค๊ณํ ๋ ์๋์ฒ๋ผ โ๊ณ ์ โ์ ๋จผ์ ๋ชจ์๋๋ฉด ์ค์๊ฐ ํ ์ค์ด๋ ๋ค.
# โ
users ๊ด๋ จ ๊ณ ์ ๋ผ์ฐํธ
@app.get("/users/me")
async def me(): ...
@app.get("/users/admin")
async def admin(): ...
# โ
๋ง์ง๋ง์ users ๋์ ๋ผ์ฐํธ
@app.get("/users/{user_id}")
async def user(user_id: str): ...
๊ฒฐ๋ก ๋ถํฐ ๋งํ๋ฉด ํ๋ฉด ์๋๋ค.
FastAPI์์ ๊ฐ์ ๋ฉ์๋ + ๊ฐ์ ๊ฒฝ๋ก๋ฅผ ๋ ๋ฒ ์ ์ํ๋ฉด, ์ฌ์ค์ โ๋ค์ ์๋ ๊ฑด ์๋ฏธ๊ฐ ์๊ธฐ ๋๋ฌธโ.
from fastapi import FastAPI
app = FastAPI()
@app.get("/users")
async def read_users():
return ["์ฒ ์", "์ํฌ"]
@app.get("/users")
async def read_users2():
return ["ํ์ด", "์งฑ๊ตฌ"]
์ด๋ฐ ์ฝ๋๋ ๋ณด๋ ์ฌ๋์ ํท๊ฐ๋ฆฌ๊ฒ ๋ง๋ค๊ณ ์ ์ง๋ณด์๋ ์ต์
์ด๋ค.
(ํ๊ฒฝ/๋ฒ์ ์ ๋ฐ๋ผ ๋ผ์ฐํธ ๋ฑ๋ก ์์ ์ฒ๋ฆฌ ๋ฐฉ์์ด ๋ค๋ฅผ ์ ์์ด ๋ ์ํํ๋ค)
โ ๊ฐ์ ๊ฒฝ๋ก๋ฅผ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ๊ณ ์ถ๋ค๋ฉด ๋ณดํต ์๋ ์ค ํ๋๋ก ํด๊ฒฐํ๋ค.
GET /users vs POST /users/users vs /users/v2/users?type=...Path Parameter๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๋ค ๋ฌธ์์ด์ด๋ ๋ฐ์ ์ ์๋ค.
๊ทธ๋ฐ๋ฐ ์ค๋ฌด์์๋ โ์ ํด์ง ๊ฐ๋ง ํ์ฉํ๊ณ ์ถ์โ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
์๋ฅผ ๋ค์ด ๋ชจ๋ธ ์ด๋ฆ์ด ์๋ 3๊ฐ ์ค ํ๋๋ง ๊ฐ๋ฅํ๋ค๊ณ ํ์.
alexnetresnetlenet์ด๋ด ๋ Python์ Enum์ ์ฐ๋ฉด:
/docs)์์ ๋๋กญ๋ค์ด์ฒ๋ผ ์ ํ ๊ฐ๋ฅํ ํํ๋ก ๋ณด์ธ๋คfrom enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
/docs์์ ์ ํ ๊ฐ๋ฅํ ๊ฐ ๋ชฉ๋ก์ด UI๋ก ํ์๋จif model_name is ModelName.alexnet ์ฒ๋ผ ์์ ํ๊ฒ ๋น๊ต ๊ฐ๋ฅpending / running / donenews / blog / noticeadmin / user / guestimage / video / textโ๋ฒ์๊ฐ ์ ํด์ง ๊ฐโ์ด๋ฉด Enum์ ์ฌ์ฉํ์
์ผ๋ฐ์ ์ผ๋ก Path Parameter๋ ์ฌ๋์(/)๋ฅผ ๊ฒฝ๊ณ๋ก ๋๊ธด๋ค.
์ฆ, ๊ธฐ๋ณธ ํํ์์๋ ์๋์ฒ๋ผ โํ ๋ฉ์ด๋ฆฌโ๋ง ๋ฐ๋๋ค.
/files/a/b/c.txt ์์ {file_path} ๋ ๋ณดํต a๊น์ง๋ง ๋ฐ๋๋ค๊ทธ๋ฐ๋ฐ ํ์ผ ๊ฒฝ๋ก์ฒ๋ผ ์ฌ๋์ ํฌํจ ์ ์ฒด ๊ฒฝ๋ก๋ฅผ ํต์งธ๋ก ๋ฐ๊ณ ์ถ์ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์ด๋ FastAPI๋ :path ์ปจ๋ฒํฐ๋ฅผ ์ ๊ณตํ๋ค.
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
์ด์ ์๋ ์์ฒญ์ด ๊ฐ๋ฅํด์ง๋ค.
/files/home/jay/myfile.txt{"file_path": "home/jay/myfile.txt"}๋ง์ฝ ์ค์ ๋ก /home/jay/myfile.txt ์ฒ๋ผ โ์ฌ๋์๋ก ์์ํ๋ ๊ฒฝ๋กโ๋ฅผ ๊ทธ๋๋ก ๋๊ธฐ๊ณ ์ถ๋ค๋ฉด URL์ ์ด๋ ๊ฒ ๋๋ค:
/files//home/jay/myfile.txt์ค๊ฐ์ ์ฌ๋์๊ฐ ํ๋ ๋ ๋ค์ด๊ฐ๋ ์ด์ ๋:
/files/ ๋ค์ Path Parameter ๊ฐ์ด ๋ค์ด๊ฐ๋๋ฐ/ ๋ก ์์ํ๋๊น// ์ฒ๋ผ ๋ณด์ด๊ฒ ๋๋ ๊ฒPath Parameter๋ ๋จ์ํ โURL์์ ๊ฐ ๋ฐ๊ธฐโ๊ฐ ์๋๋ค.
FastAPI์์๋
๊น์ง ํ ๋ฒ์ ์ด์ด์ง๋ค.
์ฆ, Path Parameter๋ฅผ ์ ์ฐ๋ฉด
API ์ค๊ณ๊ฐ ๋ ์์ ํด์ง๊ณ ๋ฌธ์๊น์ง ๊น๋ํด์ง๋ค.