FastAPI 서버개발, 요청 및 응답 데이터 검증 및 변환

FastAPI는 간단하고 효율적인 웹 API를 구축할 수 있는 현대적인 프레임워크입니다. Python의 타입 힌트를 적극적으로 활용하여 코드의 가독성을 높이고, 자동으로 OpenAPI 및 JSON Schema를 생성하는 등의 특성을 갖추고 있습니다. 이번 강좌에서는 FastAPI에서 요청 및 응답 데이터의 검증 및 변환 방법에 대해 자세히 알아보겠습니다.

1. 데이터 검증의 필요성

웹 서버는 클라이언트로부터 다양한 형태의 데이터 요청을 받습니다. 이러한 데이터는 종종 예상하지 못한 형식이나 값을 가질 수 있으며, 이로 인해 서버에서 오류가 발생하거나 잘못된 동작을 유발할 수 있습니다. 따라서 데이터의 유효성을 검사하고, 필요시 변환하는 과정이 중요합니다.

2. FastAPI에서의 데이터 검증

FastAPI는 Pydantic이라는 데이터 검증 라이브러리를 사용하여 요청 및 응답 데이터의 검증을 수행합니다. Pydantic의 모델을 선언하고 유효성 검사를 수행하는 방법을 살펴보겠습니다.

2.1 Pydantic 모델 정의하기

Pydantic 모델은 요청 데이터의 구조를 정의하며, 각 필드에 대한 데이터 타입과 제약 조건을 설정할 수 있습니다. 다음은 사용자 정보를 정의하는 Pydantic 모델의 예시입니다.

from pydantic import BaseModel, EmailStr, conint

class User(BaseModel):
    name: str
    email: EmailStr
    age: conint(ge=0)  # 0 이상의 정수

위의 모델은 사용자의 이름, 이메일, 나이를 저장하는 구조체를 정의합니다. 여기서 EmailStr는 유효한 이메일 형식인지 검사하며, conint는 정수 값을 기준으로 제약 조건을 설정합니다.

2.2 FastAPI 엔드포인트에서 데이터 검증하기

이제 이 Pydantic 모델을 FastAPI의 엔드포인트에 사용하여 클라이언트로부터 오는 요청을 검증할 수 있습니다.

from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.post("/users/")
async def create_user(user: User):
    return user

위의 엔드포인트는 POST 요청을 처리하고, 요청 본문에서 사용자 정보를 가져와 검증합니다. 만약 요청 데이터가 유효하지 않다면 FastAPI는 자동으로 422 Unprocessable Entity 오류를 반환합니다.

3. 응답 데이터 검증 및 변환

FastAPI는 응답 데이터도 Pydantic 모델을 사용하여 추천합니다. 이는 응답 형식을 일관되게 유지하고 클라이언트가 받을 데이터를 정확히 알고 있게 합니다.

3.1 응답 모델 정의하기

응답 데이터의 형태도 Pydantic 모델로 정의할 수 있습니다. 예를 들어, 사용자가 생성된 후 반환할 데이터의 형태를 정의합니다.

class UserResponse(BaseModel):
    id: int
    name: str
    email: EmailStr

3.2 엔드포인트에서 응답 데이터 사용하기

@app.post("/users/", response_model=UserResponse)
async def create_user(user: User):
    user_id = 1  # 예를 들어, 사용자 ID를 1로 설정
    return UserResponse(id=user_id, name=user.name, email=user.email)

이제 응답 데이터는 UserResponse 모델에 따라 검증되고 변환됩니다. 클라이언트는 명확하게 어떤 형태의 데이터를 받을 수 있는지 알 수 있습니다.

4. 데이터 변환

FastAPI는 요청 데이터 및 응답 데이터의 구조를 변환할 수 있는 방법을 제공합니다. 예를 들어, 클라이언트가 UUID 형식의 ID를 보낸다고 가정할 때, 이를 정수형 ID로 변환하는 방법을 설명합니다.

4.1 UUID 검증 및 변환

from uuid import UUID

class User(BaseModel):
    name: str
    email: EmailStr
    id: UUID  # UUID로 ID를 정의

이 경우 FastAPI는 클라이언트가 보낸 데이터를 자동으로 UUID 형태로 변환합니다.

4.2 변환 예제 코드

@app.post("/users/", response_model=UserResponse)
async def create_user(user: User):
    user_id = str(user.id)  # UUID에서 문자열로 변환
    # DB에 사용자 정보를 저장하는 로직 추가
    return UserResponse(id=user_id, name=user.name, email=user.email)

5. 전체 예제

전체적인 코드를 종합하여 FastAPI 애플리케이션을 구현하겠습니다. 아래 예시는 사용자 정보를 생성하는 API로, 데이터 검증 및 응답 변환을 포함합니다.

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr, conint
from uuid import UUID
import uvicorn

class User(BaseModel):
    name: str
    email: EmailStr
    id: UUID

class UserResponse(BaseModel):
    id: str
    name: str
    email: EmailStr

app = FastAPI()

@app.post("/users/", response_model=UserResponse)
async def create_user(user: User):
    user_id = str(user.id)  # UUID에서 문자열로 변환
    # DB에 사용자 정보를 저장하는 로직 추가
    return UserResponse(id=user_id, name=user.name, email=user.email)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

6. 결론

FastAPI를 사용하여 요청 및 응답 데이터의 검증 및 변환 과정을 간편하게 처리할 수 있는 방법에 대해 알아보았습니다. 이는 서버의 안정성을 증가시키고, 클라이언트와의 통신을 명확하게 하여 개발 효율성을 높이는 데 기여합니다. FastAPI의 데이터 검증 및 변환 기능을 활용하면, 복잡한 비즈니스 로직을 간단하게 구현할 수 있습니다.

이 글을 통해 FastAPI의 장점과 데이터 검증 및 변환 프로세스를 이해하고, 실제 애플리케이션 개발에 적용할 수 있게 되기를 바랍니다.

7. 참고 문서