Flask에서 FastAPI로 - 현대적인 요구사항에 맞춰 백엔드 성능 강화
Min-jun Kim
Dev Intern · Leapcell

소개
빠르게 발전하는 백엔드 개발 환경에서 우리가 선택하는 도구와 프레임워크는 애플리케이션의 확장성, 유지보수성 및 전반적인 성능에 지대한 영향을 미칩니다. 오랫동안 Flask는 Python으로 웹 서비스를 구축하는 데 있어 핵심적인 역할을 해왔으며, 가벼운 특성, 유연성, 그리고 구성 요소에 대한 명확한 제어로 많은 찬사를 받았습니다. 그러나 애플리케이션이 복잡해지고 사용자 기반이 확장되며 고처리량, 저지연 API에 대한 요구가 증가함에 따라 Flask의 일부 고유한 특성이 병목 현상이 될 수 있습니다.
이것이 바로 FastAPI와 같은 최신 비동기 프레임워크가 등장하는 이유입니다. 최첨단 Python 기능을 기반으로 구축된 FastAPI는 상당한 성능 향상을 도입하고 개발 워크플로우를 간소화하려는 개발자들에게 매력적인 대안을 제공합니다. 이 글에서는 기존 Flask 애플리케이션을 FastAPI로 마이그레이션하는 과정을 실질적으로 탐색합니다. 이 전환의 핵심 이유을 알아보고, 실질적인 이점을 강조하며, 백엔드를 현대화하고 성능을 강화하는 방법을 보여주는 구체적인 코드 예제를 제공할 것입니다.
마이그레이션 여정: FastAPI의 강력한 기능 활용
마이그레이션을 시작하기 전에 FastAPI를 최신 API 개발을 위한 강력한 경쟁자로 만드는 핵심 개념을 간략하게 정의해 보겠습니다.
핵심 개념: 비동기 프로그래밍, 타입 힌트 및 OpenAPI
FastAPI의 매력 핵심에는 세 가지 기본 기둥이 있습니다.
- 비동기 프로그래밍 (async/await): 이 패러다임은 애플리케이션이 메인 스레드를 차단하지 않고 여러 작업을 동시에 처리할 수 있도록 합니다. I/O 바운드 작업(예: 데이터베이스 쿼리 또는 외부 API 호출)이 완료될 때까지 기다리는 대신, 애플리케이션은 다른 작업으로 전환할 수 있어 처리량과 응답성이 크게 향상됩니다. 특히 부하가 많을 때 더욱 그렇습니다. FastAPI는 Python의
async
/await
구문을 기본적으로 완전히 활용합니다. - Python 타입 힌트: FastAPI는 Python의 타입 힌트(예:
str
,int
,List[str]
)를 광범위하게 사용합니다. 이러한 힌트는 정적 분석만을 위한 것이 아니라, FastAPI는 이를 사용하여 자동 데이터 유효성 검사, 직렬화 및 역직렬화를 수행합니다. 이를 통해 입력 유효성 검사를 위한 상용구 코드가 크게 줄어들고 디버깅이 단순화됩니다. - 자동 OpenAPI 및 JSON 스키마 문서화: FastAPI의 가장 널리 칭찬받는 기능 중 하나는 선언된 엔드포인트 및 타입 힌트를 기반으로 대화형 API 문서(Swagger UI 및 ReDoc)를 자동 생성하는 것입니다. 이 문서는 협업, API 소비 및 테스트에 매우 중요하며 수동 문서 업데이트의 필요성을 효과적으로 제거합니다.
왜 마이그레이션해야 하는가? 성능 및 개발 경험
Flask에서 FastAPI로 마이그레이션하는 주요 동기는 일반적으로 다음과 관련이 있습니다.
- 상당한 성능 향상: Uvicorn과 같은 ASGI 서버에서 실행되는 FastAPI는 Node.js 및 Go에 필적하는 성능을 달성할 수 있습니다. 비동기 특성은 본질적으로 동기적인 기존 WSGI 서버에서 실행되는 Flask에 비해 훨씬 더 많은 동시 요청을 처리할 수 있음을 의미합니다.
- 내장된 데이터 유효성 검사 및 직렬화: Flask는 강력한 데이터 유효성 검사를 위해 Marshmallow 또는 Pydantic(FastAPI가 내부적으로 사용하는)과 같은 외부 라이브러리를 필요로 합니다. FastAPI의 Pydantic 및 타입 힌트 통합은 이를 기본적으로 제공하여 상용구 코드를 줄이고 더 안정적인 API를 제공합니다.
- 자동 대화형 API 문서화: 자체 생성되는 OpenAPI 문서는 API 제공업체와 소비자 모두를 위한 개발 경험을 크게 향상시킵니다. 더 이상 오래되거나 수동으로 유지 관리되는 문서는 없습니다.
- 최신 Python 기능: FastAPI는 최신 Python 기능을 사용하도록 권장하여 코드베이스를 더 읽기 쉽고 유지 관리하기 쉬우며 암시적 타입 변환으로 인한 오류 가능성을 줄입니다.
- 의존성 주입 시스템: FastAPI는 강력하고 직관적인 의존성 주입 시스템을 갖추고 있어 종속성을 쉽게 관리하고, 테스트 가능한 코드를 작성하며, 대규모 애플리케이션을 구조화할 수 있습니다.
실질적인 마이그레이션: 단계별 예제
항목 목록을 관리하는 간단한 Flask 애플리케이션을 생각해 봅시다.
flask_app.py
from flask import Flask, jsonify, request app = Flask(__name__) items = [ {"id": 1, "name": "Apple"}, {"id": 2, "name": "Banana"} ] @app.route('/items', methods=['GET']) def get_items(): return jsonify(items) @app.route('/items', methods=['POST']) def add_item(): new_item = request.json if not new_item or 'name' not in new_item: return jsonify({"message": "Invalid item data"}), 400 new_item['id'] = len(items) + 1 items.append(new_item) return jsonify(new_item), 201 if __name__ == '__main__': app.run(debug=True)
이제 이것을 FastAPI로 마이그레이션해 보겠습니다.
fastapi_app.py
먼저 FastAPI와 Uvicorn을 설치합니다: pip install fastapi uvicorn pydantic
from fastapi import FastAPI, HTTPException, Body from pydantic import BaseModel from typing import List, Optional app = FastAPI() # 데이터 유효성 검사 및 직렬화를 위한 Pydantic 모델 정의 class Item(BaseModel): id: Optional[int] = None # id는 새 항목의 경우 None일 수 있으며, 서버에서 할당됩니다. name: str # 인메모리 데이터 저장소 items_db: List[Item] = [ Item(id=1, name="Apple"), Item(id=2, name="Banana") ] @app.get("/items", response_model=List[Item], summary="모든 항목 검색") async def get_all_items(): """ 현재 데이터베이스에 저장된 모든 항목 목록을 검색합니다. """ return items_db @app.post("/items", response_model=Item, status_code=201, summary="새 항목 생성") async def create_item(item: Item): """ 데이터베이스에 새 항목을 추가합니다. - **name**: 항목의 이름. """ next_id = max([item.id for item in items_db]) + 1 if items_db else 1 item.id = next_id items_db.append(item) return item # 이 Flask 앱을 실행하려면: python flask_app.py # 이 FastAPI 앱을 실행하려면: uvicorn fastapi_app:app --reload
변경 사항을 자세히 살펴보겠습니다.
FastAPI
및 PydanticBaseModel
가져오기: 필요한 구성 요소를 가져오면서 시작합니다.- Pydantic 모델 정의: 수동으로 딕셔너리를 조작하는 대신
BaseModel
을 상속하는Item
클래스를 정의합니다. 이는 들어오는 요청에 대한 자동 데이터 유효성 검사를 제공하고 일관된 응답 데이터 구조를 보장합니다.Item(id=1, name="Apple")
은 Pydantic 인스턴스를 생성합니다. - 라우트 정의:
@app.get("/items")
및@app.post("/items")
는 Flask의@app.route
데코레이터를 대체합니다. HTTP 메서드를 명시적으로 지정합니다.response_model=List[Item]
및response_model=Item
은 FastAPI에 나가는 응답 데이터가 어떤 모양이 될지 알려줍니다. 이는 직렬화 및 문서 생성에 사용됩니다.status_code=201
은 성공적인 생성에 대한 HTTP 상태 코드를 직접 설정합니다.summary
및 docstring ("""Docstring"""
)은 OpenAPI 문서를 자동으로 채우는 데 사용됩니다.
- 요청 본문 유효성 검사:
create_item
에서 함수 서명의item: Item
은 마법입니다. FastAPI는 자동으로Item
Pydantic 모델에 맞는 JSON 본문을 예상합니다. 들어오는 데이터가 일치하지 않으면 FastAPI는 세부 정보가 포함된422 Unprocessable Entity
오류를 자동으로 반환하여 수동 유효성 검사 검사를 제거합니다. - 비동기 함수: 각 엔드포인트 함수에 대한
async def
키워드는 이것이 비동기 코루틴임을 나타내며, FastAPI가 고성능 비동기 기능을 활용할 수 있도록 합니다. 함수에 명시적인await
호출이 포함되어 있지 않더라도async
로 정의하면 비동기 작업(예:asyncpg
또는SQLAlchemy
의 비동기 기능을 사용한 데이터베이스 호출)을 위해 애플리케이션을 준비합니다. - 애플리케이션 실행: FastAPI 애플리케이션은 일반적으로 Uvicorn과 같은 ASGI 서버에 의해 제공됩니다.
uvicorn fastapi_app:app --reload
는 애플리케이션을 실행합니다. 그러면http://127.0.0.1:8000/docs
로 이동하여 자동으로 생성된 대화형 API 문서를 볼 수 있습니다.
더 많은 고급 기능 탐색
-
경로 매개변수:
@app.get("/items/{item_id}") async def get_item(item_id: int): for item in items_db: if item.id == item_id: return item raise HTTPException(status_code=404, detail="Item not found")
FastAPI는
item_id
를 자동으로 정수로 유효성 검사합니다. -
쿼리 매개변수:
@app.get("/search") async def search_items(query: Optional[str] = None): if query: return [item for item in items_db if query.lower() in item.name.lower()] return items_db
Optional[str]
를 사용하면query
매개변수를 선택 사항으로 사용할 수 있습니다. -
의존성 주입: 여러 엔드포인트에서 데이터베이스 연결이나 사용자 인증 로직이 필요하다고 상상해 보십시오.
def get_current_user(token: str = Header(...)): # 토큰 유효성 검사 시뮬레이션 if token != "mysecrettoken": raise HTTPException(status_code=401, detail="Invalid token") return {"username": "admin"} @app.get("/protected-items") async def get_protected_items(current_user: dict = Depends(get_current_user)): return {"message": f"Welcome {current_user['username']}, here are your protected items."}
Depends(get_current_user)
는get_current_user
의 결과를 엔드포인트에 주입합니다. FastAPI는 실행 및 종속성 체인을 처리합니다.
결론
Flask에서 FastAPI로 마이그레이션하는 것은 고성능, 유지 관리 가능하고 최신 Python 웹 애플리케이션을 구축하는 데 있어 중요한 도약입니다. Flask가 작고 간단한 프로젝트에 여전히 강력한 선택이지만, FastAPI는 성능, 자동 문서화 및 엄격한 데이터 유효성 검사가 중요해질 때 특히 빛을 발합니다. 비동기식, Python 타입 힌트 활용 및 Pydantic의 강력한 기능 활용을 통해 FastAPI는 개발을 간소화하고, 상용구 코드를 줄이며, 내재된 확장성 이점을 제공합니다. 이 전환은 단순히 새로운 프레임워크를 채택하는 것이 아니라, 현대 디지털 환경의 요구사항을 충족하도록 백엔드 성능을 강화하는 패러다임 변화를 받아들이는 것입니다.