API 서버를 FastAPI로 구성하여 사용자의 요청을 받고 처리하는 기능을 구현하려고 한다.
서버가 살아있나 확인하는 API
from fastapi import FastAPI
app = FastAPI()
@app.get("/health")
def health_check():
return {"status": "ok"}
Python
복사
from fastapi import FastAPI
Python
복사
FastAPI 프레임워크에서 앱 객체(웹 서버가 이해할 규칙 모음)를 만들기 위해 가져온다.
app = FastAPI()
Python
복사
FastAPI 앱을 하나 생성하고 이 app 안에 어떤 URL로 오면 어떤 함수를 실행할지에 대한 규칙을 등록할 것이다.
@app.get("/health")
Python
복사
데코레이터라고 부르는 것으로 GET /health 요청이 오면 아래 함수를 실행하라는 뜻이다.
GET은 조회할 때 쓰이는 HTTP 메서드 이다.
def health_check():
return {"status": "ok"}
Python
복사
요청이 오면 실행되는 함수로 dict를 반환한다. 이 dict는 FastAPI가 자동으로 JSON으로 바꿔서 응답해준다.
URL로 숫자 받기
@app.get("/items/{item_id}")
def get_item(item_id: int):
"""Endpoint to get an item by its ID."""
return {"item_id": item_id}
Python
복사
/itmes/3 처럼 URL에 포함된 값을 받을 때 {item_id}를 사용하여 값을 받는다.
item_id는 int 타입으로, 숫자가 아닌 다른 타입의 값을 보내면 에러를 반환한다.
@app.get("/hello/{name}")
def say_hello(name: str):
return {"message": f"hello {name}"}
Python
복사
마찬가지로 URL에 문자를 받아서 처리할 때에는 파라미터 타입을 str로 지정하면 된다.
@app.get("/add/{a}/{b}")
def add(a: int, b: int):
return {"result": a + b}
Python
복사
URL에 여러 파라미터를 받을 때에도 위와 같이 받을 파라미터를 URL에 지정하고 함수에도 해당 파라미터와 타입을 지정하면 된다.
Query Parameter
지금까지 예시는 URL에 파라미터를 괄호 안에 지정 해놓는 Path parameter에 대한 것이었다.
만약, /add/3/5와 같은 Path parameter가 아닌 /multiply?a=3&b=5와 같은 Query parameter를 사용하려고하면 어떻게 해야할까?
FastAPI는 파라미터 위치를 자동으로 판단하는데, URL에 { }가 있으면 Path parameter로, 단순 함수 파라미터만 있으면 Query parameter로 판단한다.
@app.get("/multiply")
def multiply(a: int, b: int):
return {"result": a * b}
Python
복사
위의 예시는 URL에 파라미터가 없고 단순 함수 파라미터만 존재한다. FastAPI는 쿼리 스트링에서 파라미터를 찾고 지정된 함수의 기능을 실행한다.
POST
POST + JSON Body를 받는 형태의 API도 많이 쓰인다.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
a: int
b: int
@app.post("/sum")
def sum_numbers(item: Item):
"""Endpoint to sum two numbers."""
return {"result": item.a + item.b}
Python
복사
기본적인 GET을 할 때에는 Class도 사용하지 않았고, Class에도 Pydantic의 BaseModel을 상속받아 사용하지 않았다. 왜 BaseModel을 상속받아 파라미터를 구성해야 할까?
class Item(BaseModel):
Python
복사
BaseModel을 상속받은 Item 클래스는 아래의 기능을 수행할 수 있다.
•
JSON body를 자동으로 파싱
•
타입 검증
URL에 { }를 포함했다면 FastAPI는 Path parameter로, 단순 함수 파라미터면 Query parameter로, BaseModel 타입을 사용하면 JSON Body로 인식한다.
response_model
FastAPI의 response_model은 이 API가 어떤 형태로 응답할지를 명세로 고정하는 장치이다. 이 response_model을 지정하면 문서(/docs)에 응답 스펙이 정확히 찍히고, 실수로 이상한 필드를 섞어 반환해도 자동으로 정리된다. 예를 들어 실수로 내부 정보를 같이 return 해버리면 큰일인데, response_model이 있으면 모델에 없는 필드는 기본적으로 응답에서 제거된다. 추가로, 타입과 형식이 맞는지 검증해준다.
class SumRequest(BaseModel):
"""Pydantic model for summing two numbers."""
a: int
b: int
class SumResponse(BaseModel):
"""Pydantic model for the response of summing two numbers."""
result: int
@app.post("/sum2", response_model=SumResponse)
def sum_numbers2(body: SumRequest) -> SumResponse:
"""Endpoint to sum two numbers with a response model."""
return {"result": body.a + body.b, debug: f"Summing {body.a} and {body.b}"}
Python
복사
위와 같이 SumRequest라는 클라이언트가 보내는 JSON 형태와, 서버가 돌려주는 JSON 형태인 SumResponse를 생성한다. SumResponse 형태의 응답을 돌려주는 것으로 고정하기 위해 response_model를 SumResponse로 지정한다.
return에는 result와 debug가 존재하는데, response_model에는 result만 존재하기 때문에 debug를 보내더라도 응답에는 debug가 실리지 않는다.