Under the Hood: FastAPI는 단지 Starlette + Pydantic일 뿐입니다.
Grace Collins
Solutions Engineer · Leapcell

Starlette 및 Pydantic: FastAPI 없이 강력한 API 구축하기
Python 웹 개발 분야에서 FastAPI는 간결하고 사용자 친화적인 기능으로 많은 관심을 받고 있습니다. 그러나 실제로는 Starlette와 Pydantic의 고수준 캡슐화일 뿐입니다. 공식 Starlette 웹사이트는 풍부한 기능을 보여주고 있으며, Pydantic은 강력한 데이터 유효성 검사 기능으로 유명합니다. 이 두 라이브러리를 직접 사용함으로써 개발자는 FastAPI의 캡슐화에 의존하지 않고도 유연하게 고성능 API를 구축할 수 있습니다. 다음으로, 두 라이브러리의 핵심 기능과 특징을 결합하여 자세히 설명하겠습니다.
1. Starlette의 핵심 기능 및 예제
1.1 비동기 요청 처리
Starlette는 ASGI 표준을 기반으로 하며 비동기 작업을 효율적으로 처리할 수 있습니다. FastAPI에서 작성하는 방식과 비교하면 기본 로직을 더 잘 반영할 수 있습니다.
FastAPI 예제
from fastapi import FastAPI import asyncio # FastAPI 애플리케이션 인스턴스 생성 app = FastAPI() # 데코레이터를 사용하여 GET 요청 경로를 정의합니다. 함수는 비동기 함수이며 다른 요청을 차단하지 않고 시간이 오래 걸리는 작업을 처리할 수 있습니다. @app.get("/async_items/") async def async_read_items(): await asyncio.sleep(1) # I/O 작업을 시뮬레이션하고 1초 동안 일시 중지합니다. return {"message": "FastAPI 비동기 처리 예제"}
Starlette 예제
from starlette.applications import Starlette from starlette.responses import JSONResponse import asyncio # Starlette 애플리케이션 인스턴스 생성 app = Starlette() # 애플리케이션 인스턴스에서 경로를 직접 정의하고 경로와 요청 방법을 지정합니다. 처리 함수는 비동기 함수입니다. @app.route("/async_items/", methods=["GET"]) async def async_read_items(request): await asyncio.sleep(1) # I/O 작업을 시뮬레이션하고 1초 동안 일시 중지합니다. return JSONResponse({"message": "Starlette 비동기 처리 예제"})
보시다시피 FastAPI는 데코레이터를 통해 경로 정의를 단순화하는 반면 Starlette는 기본 ASGI 작업에 더 가깝습니다. 애플리케이션 인스턴스에서 경로를 직접 정의하여 더 많은 유연성을 제공합니다.
1.2 미들웨어 사용
Starlette는 다양한 미들웨어를 지원합니다. 예를 들어 간단한 로깅 미들웨어를 추가하는 경우 FastAPI에서 특정 종속성 주입을 통해 구현해야 합니다.
Starlette 미들웨어 예제
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.middleware.base import BaseHTTPMiddleware import logging # 로거 구성 logger = logging.getLogger(__name__) # 사용자 지정 로깅 미들웨어, BaseHTTPMiddleware에서 상속 class LoggingMiddleware(BaseHTTPMiddleware): async def dispatch(self, request, call_next): # 요청 방법 및 URL을 포함한 요청 정보 기록 logger.info(f"Request: {request.method} {request.url}") # 요청 처리를 계속하고 응답을 가져옵니다. response = await call_next(request) # 응답 상태 코드 기록 logger.info(f"Response: {response.status_code}") return response # Starlette 애플리케이션 인스턴스를 생성하고 미들웨어 인스턴스를 전달합니다. app = Starlette(middleware=[LoggingMiddleware(app)]) # 경로 처리 함수 정의 @app.route("/middleware_example/", methods=["GET"]) async def middleware_example(request): return JSONResponse({"message": "미들웨어가 적용되었습니다."})
FastAPI에서 유사한 기능을 구현하려면 사용자 지정 종속성 함수 및 전역 종속성 구성에 의존해야 합니다. 이에 비해 Starlette에서 미들웨어를 사용하는 방식이 더 직관적이고 기본 ASGI 사양에 더 가깝습니다.
1.3 WebSocket 지원
Starlette는 기본적으로 WebSocket을 지원합니다. 다음은 간단한 WebSocket 채팅 예제입니다.
from starlette.applications import Starlette from starlette.websockets import WebSocket, WebSocketDisconnect import json # Starlette 애플리케이션 인스턴스 생성 app = Starlette() # 연결된 클라이언트의 WebSocket 객체 저장 connected_clients = [] # WebSocket 경로 처리 함수 정의 @app.websocket_route("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() # WebSocket 연결 수락 connected_clients.append(websocket) # 연결된 클라이언트를 목록에 추가 try: while True: # 클라이언트가 보낸 텍스트 데이터 수신 data = await websocket.receive_text() message = json.loads(data) # 수신된 JSON 문자열을 Python 객체로 구문 분석 for client in connected_clients: if client != websocket: # 보낸 사람을 제외한 다른 클라이언트에 메시지 전달 await client.send_text(json.dumps(message)) except WebSocketDisconnect: connected_clients.remove(websocket) # 연결이 끊어지면 목록에서 클라이언트 제거
FastAPI도 WebSocket을 지원하지만 구현 세부 정보는 Starlette와 유사합니다. Starlette는 WebSocket 처리 인터페이스를 직접 노출하므로 개발자가 심층적인 사용자 지정을 수행하는 데 더 편리합니다.
2. Starlette에서 Pydantic 적용
2.1 데이터 유효성 검사 및 직렬화
Starlette에서 Pydantic을 사용하여 데이터 유효성 검사를 수행합니다. FastAPI와 비교:
FastAPI 예제
from fastapi import FastAPI from pydantic import BaseModel # FastAPI 애플리케이션 인스턴스 생성 app = FastAPI() # Pydantic을 사용하여 데이터 유효성 검사 및 직렬화를 위한 데이터 모델 정의 class Item(BaseModel): name: str price: float # 경로 처리 함수 정의. FastAPI는 들어오는 데이터를 자동으로 검증하고 응답을 직렬화합니다. @app.post("/fastapi_items/") async def create_fastapi_item(item: Item): return item
Starlette 예제
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.requests import Request from pydantic import BaseModel # Starlette 애플리케이션 인스턴스 생성 app = Starlette() # Pydantic을 사용하여 데이터 유효성 검사 및 직렬화를 위한 데이터 모델 정의 class Item(BaseModel): name: str price: float # 경로 처리 함수 정의하고 요청 데이터 및 유효성 검사 로직을 수동으로 처리합니다. @app.route("/starlette_items/", methods=["POST"]) async def create_starlette_item(request: Request): data = await request.json() # 요청에서 JSON 데이터 가져오기 try: item = Item(**data) # Pydantic을 사용하여 데이터 유효성 검사. 유효하지 않으면 예외가 발생합니다. except ValueError as e: return JSONResponse({"error": str(e)}, status_code=400) # 유효성 검사에 실패하면 오류 응답 반환 return JSONResponse(item.dict()) # 유효성 검사에 통과하면 직렬화된 응답 반환
FastAPI는 데이터 유효성 검사 및 오류 반환을 자동으로 처리하지만 Starlette에서는 개발자가 예외를 수동으로 catch하고 처리해야 합니다. 그러나 이 접근 방식은 개발자에게 더 많은 제어 권한을 부여합니다.
2.2 복잡한 데이터 모델 및 중첩된 유효성 검사
복잡한 데이터 모델을 처리할 때 Pydantic의 장점이 더욱 분명해집니다.
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.requests import Request from pydantic import BaseModel # Starlette 애플리케이션 인스턴스 생성 app = Starlette() # 주소 데이터 모델 정의 class Address(BaseModel): street: str city: str zip_code: str # 중첩된 주소 모델을 포함하는 사용자 데이터 모델 정의 class User(BaseModel): username: str email: str address: Address # 사용자 데이터의 유효성 검사 및 저장을 처리하기 위한 경로 처리 함수 정의 @app.route("/users/", methods=["POST"]) async def create_user(request: Request): data = await request.json() # 요청에서 JSON 데이터 가져오기 try: user = User(**data) # Pydantic을 사용하여 중첩된 데이터 유효성 검사. 유효하지 않으면 예외가 발생합니다. except ValueError as e: return JSONResponse({"error": str(e)}, status_code=400) # 유효성 검사에 실패하면 오류 응답 반환 return JSONResponse(user.dict()) # 유효성 검사에 통과하면 직렬화된 응답 반환
Starlette 또는 FastAPI이든 Pydantic은 중첩된 데이터 구조의 유효성 검사를 효율적으로 처리하여 데이터의 무결성 및 정확성을 보장할 수 있습니다.
3. Starlette와 Pydantic의 심층적인 통합
Starlette의 라우팅 및 미들웨어와 Pydantic의 데이터 유효성 검사를 결합하여 완전한 기능을 갖춘 API를 구축할 수 있습니다.
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.requests import Request from starlette.exceptions import HTTPException from starlette.middleware.cors import CORSMiddleware from pydantic import BaseModel # Starlette 애플리케이션 인스턴스 생성 app = Starlette() # 모든 출처의 요청을 허용하기 위해 CORS 미들웨어 추가(프로덕션 환경에서는 특정 도메인 이름을 제한해야 함) app.add_middleware(CORSMiddleware, allow_origins=["*"]) # Pydantic을 사용하여 제품 데이터 모델 정의 class Product(BaseModel): name: str price: float quantity: int # 제품 데이터를 저장할 목록 products = [] # 제품 생성을 위한 경로 처리 함수 정의 @app.route("/products/", methods=["POST"]) async def create_product(request: Request): data = await request.json() # 요청에서 JSON 데이터 가져오기 try: product = Product(**data) # Pydantic을 사용하여 데이터 유효성 검사. 유효하지 않으면 예외가 발생합니다. except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) # 유효성 검사에 실패하면 HTTP 예외 반환 products.append(product.dict()) # 유효성 검사에 통과하면 제품 데이터를 목록에 추가 return JSONResponse(product.dict()) # 생성된 제품 데이터 반환 # 모든 제품을 가져오기 위한 경로 처리 함수 정의 @app.route("/products/", methods=["GET"]) async def get_products(request): return JSONResponse(products) # 모든 제품 데이터 반환
이 예제에서는 Starlette가 라우팅, 교차 출처 문제(미들웨어 사용)를 처리하고 Pydantic이 데이터 유효성 검사 및 직렬화를 수행하는 전체 프로세스를 보여줍니다. FastAPI에 비해 문서 자동 생성과 같은 기능은 없지만 개발자는 실제 요구 사항에 따라 타사 라이브러리를 유연하게 선택하여 확장할 수 있습니다(예: drf-spectacular
또는 apispec
을 사용하여 API 문서 생성).
결론
Starlette와 Pydantic을 결합하면 FastAPI의 캡슐화에 의존하지 않고도 고성능 및 기능이 풍부한 API를 구축할 수 있습니다. Starlette는 비동기 처리, 미들웨어 및 WebSocket과 같은 핵심 기능을 지원하는 유연한 ASGI 애플리케이션 기반을 제공합니다. Pydantic은 데이터 유효성 검사 및 직렬화에 중점을 둡니다. FastAPI는 개발 프로세스를 단순화하지만 Starlette와 Pydantic을 직접 사용하면 개발자는 기본 원칙에 대한 더 깊은 이해를 갖고 프로젝트 요구 사항에 따라 고도로 사용자 정의된 조정을 수행하며 복잡한 시나리오에서 더 강력한 적응력을 보여줄 수 있습니다.
Leapcell: 최고의 서버리스 웹 호스팅
마지막으로, Python 서비스를 배포하는 데 가장 적합한 플랫폼인 **Leapcell**을 추천합니다.
🚀 좋아하는 언어로 빌드
JavaScript, Python, Go 또는 Rust로 손쉽게 개발하세요.
🌍 무제한 프로젝트를 무료로 배포
사용한 만큼만 지불하세요. 요청도 없고, 요금도 없습니다.
⚡ 사용한 만큼 지불, 숨겨진 비용 없음
유휴 수수료 없이 원활한 확장성만 제공합니다.
🔹 Twitter에서 팔로우하세요: @LeapcellHQ