FastAPI로 레거시 Flask API 점진적으로 교체하기
배경
2년간 운영해온 Flask 기반 API 서버의 성능 이슈가 반복됐다. 동시 요청 처리에서 병목이 발생했고, 타입 힌팅이 없어 런타임 에러도 잦았다. FastAPI로의 전환을 결정했다.
마이그레이션 전략
전체를 한 번에 교체하는 건 위험했다. 같은 서버에서 Flask와 FastAPI를 함께 운영하기로 했다.
# main.py
from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from legacy_app import flask_app
app = FastAPI()
# 새로운 엔드포인트
@app.get("/api/v2/users/{user_id}")
async def get_user(user_id: int):
return {"id": user_id, "name": "test"}
# 레거시 Flask 앱을 마운트
app.mount("/api/v1", WSGIMiddleware(flask_app))
/api/v2로 시작하는 엔드포인트는 FastAPI로, 기존 /api/v1은 Flask가 처리하도록 구성했다.
실제 전환 과정
- 가장 부하가 큰 엔드포인트부터 전환했다. 상품 검색 API가 첫 대상이었다.
- Pydantic 모델 정의로 요청/응답 검증을 자동화했다.
- async/await 도입으로 DB 쿼리와 외부 API 호출을 병렬 처리했다.
from pydantic import BaseModel
from typing import List
class Product(BaseModel):
id: int
name: str
price: int
@app.get("/api/v2/products", response_model=List[Product])
async def search_products(q: str):
# 비동기 DB 쿼리
products = await db.fetch_all(
"SELECT id, name, price FROM products WHERE name LIKE :query",
{"query": f"%{q}%"}
)
return products
결과
- 평균 응답 시간 200ms → 80ms
- 타입 에러로 인한 장애 제로
- API 문서 자동 생성으로 프론트엔드 팀 커뮤니케이션 개선
3개월간 점진적으로 전환해 큰 장애 없이 마이그레이션을 완료했다.