FastAPI는 Python으로 API를 개발할 때 경로 매개변수(path parameter)를 간단하고 직관적으로 처리할 수 있는 기능을 제공한다.
경로 매개변수란?
경로 매개변수는 URL 경로의 일부로 사용되는 변수를 의미한다. 예를 들어, https://example.com/items/42
라는 URL에서 42
는 경로 매개변수로 사용될 수 있다. 경로 매개변수를 사용하면 클라이언트가 특정 자원에 접근하거나, 동적으로 값을 전달할 수 있게 된다.
FastAPI에서는 경로 매개변수를 정의하고 사용하는 것이 매우 간단하다.
경로 매개변수 사용법
기본 사용법
FastAPI에서 경로 매개변수를 정의하려면, 경로 문자열에 중괄호 {}
를 사용하면 된다. 예를 들어, 아이템의 ID를 경로 매개변수로 받아서 해당 아이템을 반환하는 API를 만들어 보자.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
위 코드에서는 item_id
라는 경로 매개변수를 정의하고, 이 값을 함수의 인자로 전달받고 있다. FastAPI는 item_id
를 자동으로 추출하여 int
타입으로 변환한 후, 함수에 전달한다.
여러 개의 경로 매개변수 사용하기
여러 개의 경로 매개변수를 사용해야 하는 경우, 이를 경로에 추가하면 됩니다. 예를 들어, 특정 사용자의 특정 아이템을 조회하는 API를 만들어 보겠습니다.
@app.get("/users/{user_id}/items/{item_id}")
def read_user_item(user_id: int, item_id: int):
return {"user_id": user_id, "item_id": item_id}
위 코드에서는 user_id
와 item_id
두 개의 경로 매개변수를 사용하고 있으며, 두 매개변수를 모두 함수의 인자로 전달받아 처리하고 있다.
경로 매개변수와 타입 힌트
FastAPI는 Python의 타입 힌트를 활용하여 경로 매개변수의 타입을 자동으로 변환해 준다. 예를 들어, item_id
를 int
로 정의하면, FastAPI는 해당 값을 int
로 변환하려고 시도한다. 만약 클라이언트가 정수 이외의 값을 전달하면, FastAPI는 자동으로 422 Unprocessable Entity 에러를 반환한다.
예시)
GET http://localhost:8000/users/hong/items/2
응답결과)
HTTP/1.1 422 Unprocessable Entity
{
"detail": [
{
"type": "int_parsing",
"loc": [
"path",
"user_id"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "hong"
}
]
}
다양한 타입을 경로 매개변수로 사용할 수 있으며, 예를 들어 str
, float
, bool
등을 사용할 수 있다. 아래는 float
타입의 경로 매개변수를 사용하는 예제이다.
@app.get("/prices/{price}")
def read_price(price: float):
return {"price": price}
경로 매개변수에 기본값 사용하기
FastAPI의 경로 매개변수는 선택적으로 기본값을 가질 수 있다. 기본값을 사용하면 클라이언트가 특정 매개변수를 생략했을 때 사용할 값을 정의할 수 있다. 다음은 item_id
에 기본값을 설정하는 예제이다.
@app.get("/items/{item_id}")
def read_item(item_id: int = 0):
return {"item_id": item_id}
이 경우, 클라이언트가 item_id
를 제공하지 않으면 기본값 0
이 사용된다.
경로 매개변수와 쿼리 매개변수 함께 사용하기
경로 매개변수와 쿼리 매개변수를 함께 사용하는 것도 가능하다. 쿼리 매개변수는 URL 경로의 일부가 아니라 ?key=value
형식으로 전달되는 매개변수이다. 예를 들어, 특정 아이템의 상세 정보를 조회할 때 옵션을 추가로 전달받고 싶다면 다음과 같이 작성할 수 있다.
@app.get("/items/{item_id}")
def read_item(item_id: int, detail: bool = False):
return {"item_id": item_id, "detail": detail}
이 예제에서는 경로 매개변수 item_id
와 함께 쿼리 매개변수 detail
을 사용할 수 있다. 클라이언트가 ?detail=true
를 URL에 추가하면, detail
값은 True
로 설정된다.
Enum 클래스 생성
Enum을 임포트하고 서브 클래스를 만든다. 그리고 fruits api를 만든다.
class FruitName(str, Enum):
apple = "apple"
pear = "pear"
banana = "banana"
@app.get("/fruits/{fruit_name}")
def get_fruit(fruit_name: FruitName):
return {"fruit_name": fruit_name}
여기에 apple을 호출해보자.
GET http://localhost:8000/fruits/apple
실행결과
{
"fruit_name": "apple"
}
만일 없는 과일을 요청한다면 422 오류가 발생한다.
GET http://localhost:8000/fruits/orange
실행결과
HTTP/1.1 422 Unprocessable Entity
{
"detail": [
{
"type": "enum",
"loc": [
"path",
"fruit_name"
],
"msg": "Input should be 'apple', 'pear' or 'banana'",
"input": "orange",
"ctx": {
"expected": "'apple', 'pear' or 'banana'"
}
}
]
}