FastAPI 서버개발, 스키마 – 응답, 응답 타입 정의에 대한 설명

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, 빠른 개발과 성능을 목표로 하고 있습니다. 이 블로그 포스트에서는 FastAPI에서 스키마를 정의하고 이를 통해 응답을 설정하는 방법에 대해 자세히 설명하도록 하겠습니다. 우리는 여기에 여러 예제와 함께 설명할 것이며, 명확한 이해를 돕기 위해 단계적으로 진행하겠습니다.

FastAPI란?

FastAPI는 다음과 같은 주요 특징을 가지고 있습니다:

  • 자동 생성된 OpenAPI 문서
  • 유효성 검사를 통한 데이터 검증
  • 비동기 지원으로 높은 성능
  • 모든 매개변수의 자동 문서화

FastAPI 설치

FastAPI를 시작하기 위해서는 먼저 FastAPI와 Uvicorn을 설치해야 합니다. Uvicorn은 ASGI 서버로 FastAPI 애플리케이션을 실행하는 데 사용됩니다. 아래와 같이 설치할 수 있습니다:

pip install fastapi uvicorn

응답 스키마 정의

FastAPI는 Pydantic을 통해 데이터 유효성 검사와 직렬화를 처리합니다. Pydantic 모델을 사용하면 API의 데이터 모델을 정의할 수 있습니다. 이를 통해 클라이언트가 요청한 데이터를 검증하고, 서버가 보낼 응답 형태를 정의할 수 있습니다.

Pydantic 모델 생성

Pydantic 모델을 생성하는 방법에 대해 살펴보겠습니다. 아래는 간단한 Pydantic 모델을 정의하는 예제입니다:

from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None

위의 Item 클래스는 name, description, price, 그리고 tax 필드를 포함하고 있습니다. descriptiontax는 기본값으로 None을 설정하였으므로 선택적 필드입니다. 이제 이 모델을 사용하여 FastAPI 라우트를 정의해 보겠습니다.

FastAPI에서 응답 정의

FastAPI에서 정의한 Pydantic 모델을 응답 스키마로 활용하는 방법을 설명하겠습니다. 아래는 FastAPI와 Pydantic을 사용한 간단한 API 예제입니다:

from fastapi import FastAPI

app = FastAPI()

@app.post("/items/", response_model=Item)
async def create_item(item: Item):
    return item

위의 예제에서는 /items/ 엔드포인트를 통해 아이템을 생성하는 API를 정의하였습니다. 사용자가 요청한 아이템 데이터는 Pydantic 모델인 Item을 기준으로 검증됩니다. 요청이 성공적으로 처리되면, 동일한 아이템 데이터가 응답으로 반환됩니다.

응답 타입 정의

FastAPI에서는 응답의 타입을 정의하여 클라이언트에게 어떤 형식의 데이터를 보낼 것인지 명확히 알릴 수 있습니다. 이는 API의 가독성을 높이고, 클라이언트가 올바르게 요청을 할 수 있도록 돕습니다.

응답 모델 사용하기

응답 모델은 위에서 정의한 Pydantic 모델을 쉽게 활용할 수 있습니다. 여기서는 약간 더 복잡한 예제를 통해 응답 타입을 정의하는 방법을 알아보겠습니다:

from typing import List

class ItemResponse(BaseModel):
    items: List[Item]
    total: int

@app.get("/items/", response_model=ItemResponse)
async def read_items(skip: int = 0, limit: int = 10):
    # 여기서 실제 데이터베이스 쿼리를 수행하겠지만, 예제로 일부 더미 데이터를 반환합니다.
    fake_items = [Item(name="Item 1", price=100.0), Item(name="Item 2", price=200.0)]
    return ItemResponse(items=fake_items, total=len(fake_items))

위의 예제는 /items/ 엔드포인트를 통해 아이템 리스트와 총 개수를 반환합니다. ItemResponse 모델은 items 필드와 total 필드를 포함하고 있으며, 데이터를 리스트와 정수 형태로 묶어서 보냅니다.

응답 JSON 예제

위의 예제를 통해 API를 호출하면 다음과 같은 JSON 응답을 얻을 수 있습니다:

{
    "items": [
        {"name": "Item 1", "description": null, "price": 100.0, "tax": null},
        {"name": "Item 2", "description": null, "price": 200.0, "tax": null}
    ],
    "total": 2
}

여기서 클라이언트는 요청한 API에서 어떤 형태의 데이터가 반환될지를 예측할 수 있으며, 이는 개발자와 사용자가 더 나은 대화를 할 수 있도록 돕습니다.

오류 응답 처리

FastAPI에서는 정의된 스키마에 맞지 않는 요청에 대해 자동으로 오류를 처리합니다. 사용자가 잘못된 데이터를 보낼 경우, FastAPI는 422 Unprocessable Entity 오류를 반환하며, 어떤 필드가 잘못되었는지에 대한 정보를 제공합니다.

POST /items/
{
    "name": "Item 1",
    "price": "Not a number"  # 이 필드는 숫자가 필요합니다.
}

이와 같은 경우 FastAPI는 다음과 같은 오류 응답을 생성합니다:

{
    "detail": [
        {
            "loc": ["body", "price"],
            "msg": "value is not a valid float",
            "type": "value_error.float"
        }
    ]
}

결론

이 블로그 포스트에서는 FastAPI에서 스키마를 정의하고, 이를 통해 API의 응답 타입을 설정하는 방법에 대해 자세히 살펴보았습니다. Pydantic 모델을 사용하여 데이터 구조를 정의하고, 이를 FastAPI에 통합하여 강력한 API를 만들 수 있음을 확인하였습니다. 이러한 접근은 데이터의 무결성과 API의 명료성을 보장하는 데 큰 도움이 됩니다.

FastAPI를 통해 더 나은 웹 서비스를 개발할 수 있기를 바랍니다. 추가적인 질문이 있다면 언제든지 댓글 달아 주시기 바랍니다!