Pydantic과 FastAPI를 통한 API 문서 간소화
Min-jun Kim
Dev Intern · Leapcell

소개
웹 개발의 활기찬 세계에서 API는 현대 애플리케이션의 중추 역할을 하며, 서로 다른 시스템 간에 원활한 통신을 가능하게 합니다. 그러나 강력하고 잘 문서화된 API를 구축하는 것은 종종 어려운 일이 될 수 있습니다. 개발자들은 API 문서를 수동으로 작성하고 유지 관리하는 번거로운 작업에 자주 직면하게 되는데, 이는 시간 소모적일 뿐만 아니라 불일치와 오래된 정보가 발생하기 쉽습니다. 이러한 오버헤드는 개발 속도를 크게 저하시키고 팀 간의 협업을 복잡하게 만들 수 있습니다.
좋은 소식은 Python 웹 프레임워크의 발전으로 이 널리 퍼진 문제에 대한 우아한 해결책이 제시되었다는 것입니다. 이 글에서는 Pydantic의 강력한 기능을 활용하는 FastAPI가 대화형 OpenAPI(이전 Swagger) 및 ReDoc 사양을 자동으로 생성하여 API 문서를 혁신하는 방법을 자세히 살펴봅니다. 이 동적 듀오는 한때 지루했던 작업을 API 개발의 통합되고 효율적이며 즐거운 측면으로 변화시켜 API 문서가 항상 정확하고 최신 상태이며 쉽게 접근할 수 있도록 보장합니다.
핵심 구성 요소 이해
이러한 원활한 문서 생성을 가능하게 하는 메커니즘을 자세히 살펴보기 전에 관련 핵심 기술을 간략하게 정의해 보겠습니다.
- FastAPI: FastAPI는 Python 3.7+ 기반의 현대적이고 빠른(고성능) API 구축용 웹 프레임워크로, 표준 Python 타입 힌트에 기반합니다. 주요 기능에는 속도, 직관적인 디자인, 자동 문서가 포함됩니다. 웹 부분은 Starlette에, 데이터 검증 및 직렬화는 Pydantic에 기반합니다.
- Pydantic: Pydantic은 Python 타입 힌트를 사용하는 데이터 검증 및 설정 관리 라이브러리입니다. 개발자는 표준 Python 클래스 구문과 타입 주석을 사용하여 데이터 스키마를 정의할 수 있습니다. Pydantic은 데이터를 자동으로 검증, 직렬화 및 역직렬화하며, 검증 실패 시 명확한 오류를 발생시킵니다. 이 강력한 타입 검사 메커니즘은 FastAPI가 API 스키마를 추론하는 데 활용하는 것입니다.
- OpenAPI (이전 Swagger) 사양: OpenAPI는 REST API를 위한 언어 불가지론적이고 사람이 읽을 수 있는 설명 형식입니다. 소스 코드나 추가 문서에 액세스하지 않고도 인간과 기계가 서비스의 기능을 이해할 수 있도록 합니다. 그런 다음 도구를 사용하여 이 사양을 사용하여 코드를 생성하고, 문서를 만들고, 테스트 사례를 작성할 수 있습니다.
- Swagger UI / ReDoc: 이들은 OpenAPI 사양을 대화형 사용자 친화적인 API 문서로 렌더링하는 인기 있는 도구입니다. Swagger UI는 엔드포인트를 탐색하고, 브라우저에서 직접 요청을 시도하고, 응답을 볼 수 있는 포괄적인 인터페이스를 제공합니다. 반면에 ReDoc은 미학적으로 더 보기 좋고 가독성이 높은 문서를 만드는 데 중점을 두며, 종종 정적 API 문서에 선호됩니다.
자동 문서화의 마법
FastAPI의 자동 문서화 뒤에 있는 핵심 원리는 Pydantic 및 Python의 타입 힌팅 시스템과의 깊은 통합에 있습니다. Pydantic 모델과 타입 힌트를 사용하여 API 엔드포인트와 해당 요청/응답 모델을 정의하면 FastAPI는 이 정보를 검증 또는 직렬화에만 사용하는 것이 아닙니다. 또한 이러한 정의를 검사하여 OpenAPI 스키마를 구성합니다.
작동 방식을 자세히 살펴보겠습니다.
-
스키마로서의 Pydantic 모델: Pydantic 모델을 사용하여 요청 본문, 응답 모델 및 쿼리 매개변수의 구조를 정의합니다. 타입 힌트(예:
str
,int
,Optional[float]
, 사용자 정의 Pydantic 모델)가 있는 이러한 모델은 자동으로 OpenAPI 스키마 구성 요소로 변환됩니다. Pydantic은 필드 검증(예:Field(..., min_length=3)
)도 지원하며, 이는 검증 규칙으로 OpenAPI 스키마를 더욱 풍부하게 만듭니다. -
경로 및 쿼리 매개변수의 타입 힌트: 경로 매개변수(예:
/items/{item_id}
) 및 쿼리 매개변수(예:/items?skip=0&limit=10
)의 경우 FastAPI는 함수 서명에서 직접 타입 정보를 추출합니다. 이를 통해 타입을 자동으로 추론하고, 필수 상태 및 설명을 제공할 수 있습니다. -
FastAPI의 OpenAPI 생성기: 애플리케이션이 시작되면 FastAPI는 정의된 모든 라우트를 스캔합니다. 각 라우트에 대해 Pydantic 모델, 타입 힌트 및 추가 메타데이터(예:
APIRouter
또는Depends
함수의description
또는summary
)를 분석하여 JSON 형식의 포괄적인 OpenAPI 사양을 빌드합니다(일반적으로/openapi.json
에서 액세스 가능). -
대화형 문서 렌더링: 그런 다음 FastAPI는 두 가지 대화형 문서 UI를 자동으로 제공합니다.
- Swagger UI: 기본적으로
/docs
에서 액세스할 수 있습니다./openapi.json
을 읽고 사용자가 엔드포인트를 탐색하고, 예제 요청/응답을 보고, 브라우저에서 직접 API를 테스트할 수 있는 동적 인터페이스로 표시합니다. - ReDoc: 기본적으로
/redoc
에서 액세스할 수 있습니다./openapi.json
을 읽고 우아한 디자인과 쉬운 탐색으로 인해 종종 프레젠테이션에 선호되는 깔끔한 단일 페이지 문서 사이트로 렌더링합니다.
- Swagger UI: 기본적으로
설명적인 예
이를 실제로 확인하기 위해 실용적인 예제를 살펴보겠습니다.
먼저 FastAPI 및 Uvicorn을 설치했는지 확인하십시오.
pip install "fastapi[all]" uvicorn
이제 main.py
와 같은 Python 파일을 만듭니다.
from typing import Optional, List from fastapi import FastAPI, Path, Query from pydantic import BaseModel, Field # 1. 데이터 검증 및 직렬화를 위한 Pydantic 모델 정의 # 이 모델은 Item의 구조를 설명합니다. class Item(BaseModel): name: str = Field(..., example="Pizza") description: Optional[str] = Field(None, example="A delicious Italian dish") price: float = Field(..., gt=0, example=12.99) tax: Optional[float] = Field(None, ge=0, example=1.04) # 더 나은 문서를 위한 예제 구성 class Config: schema_extra = { "example": { "name": "Burger", "description": "A classic American sandwich", "price": 8.50, "tax": 0.68, } } # 이 모델은 User의 구조를 설명합니다. class User(BaseModel): username: str = Field(..., min_length=3, max_length=20) email: str = Field(..., example="john.doe@example.com") is_active: bool = True app = FastAPI( title="My Awesome API", description="A comprehensive API for managing items and users.", version="1.0.0", docs_url="/documentation", # Swagger UI URL 사용자 지정 redoc_url="/alternative-documentation", # ReDoc URL 사용자 지정 ) # 2. Pydantic 모델 및 타입 힌트를 사용하여 API 엔드포인트 정의 @app.post("/items/", response_model=Item, summary="Create a new item") async def create_item(item: Item): """ Create an item with all the information: name, description, price, and tax. - **name**: Name of the item - **description**: A long description - **price**: Price of the item (must be greater than zero) - **tax**: Optional tax percentage """ return item @app.get("/items/{item_id}", response_model=Item, summary="Read an item by ID") async def read_item( item_id: int = Path(..., title="The ID of the item to get", ge=1), q: Optional[str] = Query(None, alias="item-query", description="Search query for the item", min_length=3, max_length=50, regex="^fixedquery$"), short: bool = False ): """ Retrieve a single item by its unique ID. You can optionally provide a search query `q` to refine the results. `short` parameter can be used for brevity. """ item_data = {"name": "Example Item", "description": "This is an example item.", "price": 19.99} if q and "fixedquery" in q: item_data["description"] += f" - Query match: {q}" if short: return {"name": item_data["name"], "price": item_data["price"]} return Item(id=item_id, **item_data) # Note: Adding id for demonstration, Pydantic handles it. @app.put("/items/{item_id}", response_model=Item, summary="Update an existing item") async def update_item( item_id: int, item: Item = Field(..., description="The item object to update with.") ): """ Update an existing item's details. """ # In a real application, you'd fetch, update, and save the item. return item @app.post("/users/", response_model=User, summary="Register a new user") async def create_user(user: User): """ Register a new user with a username, email, and active status. """ return user @app.get("/users/", response_model=List[User], summary="Get all users") async def get_users(skip: int = 0, limit: int = 10): """ Retrieve a list of users with pagination options. """ # Simulate fetching users from a database users_db = [ User(username="alice", email="alice@example.com"), User(username="bob", email="bob@example.com", is_active=False), User(username="charlie", email="charlie@example.com"), ] return users_db[skip : skip + limit]
이 애플리케이션을 실행하려면 터미널에서 다음을 실행합니다.
uvicorn main:app --reload
이제 웹 브라우저를 열고 다음으로 이동하십시오.
http://127.0.0.1:8000/documentation
(Swagger UI용)http://127.0.0.1:8000/alternative-documentation
(ReDoc용)
그러면 Pydantic 모델, 타입 힌트 및 독스트링에서 자동으로 생성된 엔드포인트 설명, 요청/응답 모델, 예제 값을 포함한 완전한 대화형 API 문서가 즉시 표시됩니다.
애플리케이션 시나리오
Pydantic 및 FastAPI의 자동 OpenAPI 및 ReDoc 생성 기능은 여러 시나리오에서 매우 유용합니다.
- 신속한 API 프로토타이핑: 구축 중인 API의 시각적 표현을 빠르게 얻어 설계 반복을 촉진합니다.
- 향상된 개발자 경험: API를 사용하는 개발자는 상호 작용 방법을 쉽게 이해할 수 있어 마찰과 통합 시간을 줄일 수 있습니다.
- 개선된 협업: 프론트엔드, 백엔드 및 QA 엔지니어는 API 사양에 대한 단일 진실 공급원을 신뢰하여 오해를 최소화할 수 있습니다.
- 클라이언트 SDK 생성: 생성된 OpenAPI 사양은 다양한 도구에서 사용하여 여러 프로그래밍 언어로 클라이언트 라이브러리를 자동으로 생성하여 클라이언트 측 개발을 더욱 가속화할 수 있습니다.
- 자동화된 테스트: 테스트 프레임워크는 OpenAPI 사양을 활용하여 API 검증을 위한 강력한 테스트 스위트를 생성할 수 있습니다.
- 일관된 문서: 문서가 코드에서 직접 파생되므로 API의 실제 동작과 본질적으로 일관되어 수동 유지 관리 문제를 제거합니다.
결론
데이터 모델링 및 검증을 위한 Pydantic과 고성능 API 구축을 위한 FastAPI의 조합은 효율적이고 즐거운 개발자 경험을 제공합니다. 대화형 OpenAPI 및 ReDoc 문서를 자동으로 생성함으로써 이 강력한 듀오는 수동 문서 작성의 지루함을 제거하여 API 사양이 항상 정확하고 접근하기 쉽도록 보장합니다. Pydantic 및 FastAPI를 채택하면 API 개발이 가속화될 뿐만 아니라 전체 소프트웨어 개발 수명 주기에 걸쳐 협업 및 유지 관리가 크게 향상되어 진정한 문서 작성이 API의 필수적이고 쉬운 부분이 됩니다.