Path Operation
Path는 URL에서 도메인 뒤에 붙는 경로를 말한다. 예를 들어, 아래와 같은 URL이 있다고 하자.
https://example.com/items/foo
여기서 Path에 해당하는 것은
/items/foo
Operation은 HTTP 메소드를 말한다. GET, POST, PUT, DELETE 이외에도 OPTIONS, HEAD, PATCH 등이 있다.
이렇게 Path와 Operation의 조합을 Path Operation이라고 한다. FastAPI에서는 특정한 Path Operation으로 요청이 왔을 때 실행할 함수를 decorator로 FastAPI 인스턴스에 등록할 수 있다.
@app.get("/")
def hello_world():
return {"Hello": "World!"}
이 때, 같은 Path Operation이라도 사용자의 입력에 따라 다양한 동작을 수행할 수 있다. 이번 글에서는 FastAPI에서 사용자의 입력을 받는 방법을 알아보자.
Path Parameter
먼저, Path Parameter는 Path의 특정 부분을 매개변수로 받는 방법이다. 예를 들어, 쇼핑몰에서 판매중인 상품을 Item이라고 하자. 각 상품의 상세 정보를 얻고싶다면 해당 상품을 특정할 수 있는 id가 필요하다. 이런 경우, 각 상품의 id별로 함수를 만들어야 한다면 새로운 상품을 등록할 때마다 새로운 함수를 작성해야 할 것이고, 매번 서버를 재시작해야 할 것이다.
사용법
대부분의 웹 프레임워크는 Path의 일부를 Path Parameter로 사용할 수 있는 방법을 제공한다. FastAPI도 마찬가지로, 아래와 같이 사용할 수 있다.
@app.get("/items/{item_id}")
def read_item(item_id):
return {"item_id": item_id}
Path에서 Path Parameter로 사용할 부분을 중괄호 안에 넣고, 함수의 parameter를 같은 이름으로 만들어주면 된다. 이제 직접 테스트를 해보자. /items/abcd로 GET 요청을 보내면 아래와 같은 응답이 온다.
{"item_id": "abcd"}
이번에는 /items/123으로 GET 요청을 보내면 마찬가지로 응답이 온다.
{"item_id": "123"}
응답을 보면 123이 문자로 인식되는 것을 알 수 있다. 요청을 숫자로 요청을 보냈지만 서버는 그것을 숫자로 처리해야할지, 문자열로 처리해야할지 알지 못한다. 따라서 타입에 대한 힌트를 제공해야 item_id를 숫자로 사용할 수 있다.
타입이 있는 path parameter
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
이제, 같은 요청을 보냈을 때 숫자로 응답이 온다.
{"item_id": 123}
이렇게 타입을 명시하는 경우, 타입이 맞지 않으면 에러가 난다. /items/abcd으로 GET 요청을 해보면 에러가 나는 것을 확인할 수 있다.
Enum
Enum을 사용해 미리 정의된 값으로만 parameter를 받을 수도 있다. 예를 들어, Item의 타입이 음식과 음료로 나누어진다고 하자. 아래와 같이 Enum 클래스를 정의할 수 있다.
from enum import Enum
class ItemType(str, Enum):
food = "food"
beverage = "beverage"
이제, path parameter를 통해 ItemType을 받아보자.
@app.get("/items/{item_type}")
def item_type(item_type: ItemType):
return {"item_type": item_type}
이제 /items/food로 GET 요청을 보내면 아래와 같은 응답이 온다.
{"item_type":"food"}
만약 food와 beverage가 아닌 값을 보내면 에러가 발생한다.
Query Parameter
Query Parameter는 URL 끝에 ? 뒤에 붙은 것들을 말한다. 예를 들면 아래와 같은 형식이다.
http://127.0.0.1:8000/items/?skip=0&limit=10
위 요청에서 skip이라는 query parameter로 0, limit이라는 query parameter로 10이 들어왔다. Query Parameter는 이처럼 key-value로 이루어진 값이다.
사용법
FastAPI에서는 함수의 parameter로 선언된 값들 중 path parameter가 아닌 것들을 query parameter로 취급한다. 아래와 같은 함수를 보자.
@app.get("/items/")
def read_item(skip: int, limit: int):
return items[skip : skip + limit]
위 요청에 의하면 items 리스트의 0부터 9까지 10개의 값을 리턴한다.
기본값
Query parameter는 기본값을 정의하는 경우가 많다. 기본값을 정의하면 query parameter를 주지 않고도 요청을 보낼 수 있다. 위 함수에 기본값을 정의하면 아래와 같다.
@app.get("/items/")
def read_item(skip: int = 0, limit: int = 20):
return items[skip : skip + limit]
이제 요청시에 query parameter가 없어도 잘 동작한다.
http://127.0.0.1:8000/items/
위 요청은 아래와 완전히 동일하다.
http://127.0.0.1:8000/items/?skip=0&limit=20
둘 중 하나만 요청해도 된다. 예를 들어, 위 요청에서 skip이 0이므로 기본값과 같다. 따라서 아래와 같이 보내도 동일한 결과가 나온다.
http://127.0.0.1:8000/items/?limit=20
Request Body
마지막으로, Request Body는 HTTP 요청의 body에 실어보내는 데이터를 의미한다. 일반적으로 API를 통해 데이터를 주고받을 때 JSON 형식의 데이터를 통해 데이터를 주고받는다.
사용법
JSON 형식의 데이터를 입력으로 받기 위해서 구조화된 클래스를 정의해야한다. 이 클래스는 pydantic 패키지의 BaseModel을 상속받는다.
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
이제 이렇게 정의된 클래스를 함수의 메소드 파라미터로 정의하면 된다.
@app.post("/items/")
def create_item(item: Item):
return item
이제 item의 구조와 똑같은 구조를 가진 JSON 데이터를 HTTP body로 갖는 POST 요청을 보낼 수 있다.
{
"name": "item1",
"description": "1번 아이템",
"price": 300.0,
"tax": 10.0
}
여기서 description과 tax는 None이 될 수도 있는 optional한 속성이기 때문에 아래와 같은 JSON도 유효하다.
{
"name": "item1",
"price": 300.0
}
3줄 요약
- URL의 Path와 HTTP 메소드의 operation을 합쳐서 path operation을 정의할 수 있다
- API에서 데이터를 입력받는 방법은 Path Parameter, Query Parameter, Request Body가 있다
- FastAPI는 함수 파라미터를 정의하는 것만으로 간단하게 입력을 받을 수 있는 방법을 제공한다
'Python > FastAPI' 카테고리의 다른 글
[FastAPI] FastAPI 튜토리얼 (6) - 로그인 (0) | 2023.08.02 |
---|---|
[FastAPI] FastAPI 튜토리얼 (5) - SQLAlchemy ORM (0) | 2023.07.30 |
[FastAPI] FastAPI 튜토리얼 (4) - SQLAlchemy Core (0) | 2023.07.22 |
[FastAPI] FastAPI 튜토리얼 (3) - Dependency (0) | 2023.07.20 |
[FastAPI] FastAPI 튜토리얼 (1) - FastAPI 소개 (0) | 2023.07.12 |