WEB
[Python Backend] RestAPI 기반의 Flask vs FastAPI (feat. gRPC)
땽뚕
2025. 5. 25. 09:07
728x90
[Python Backend] RestAPI 기반의 Flask vs FastAPI (feat. gRPC)
보통 Python Backend로는 Flask vs FastAPI vs Django를 많이 비교선상에 두곤 한다.
나도 4년전 Flask 깔짝 ... 한 적 있지만 이게 지금 이렇게 쓰일 줄 몰랐다.
그때도 Flask랑 Django 중에 뭐 공부할까 하다가 비교적 간단한 Flask를 공부했던 기억이 있다.
LLM 서비스 특성상 빠르게 통신되어야 하고, Flask보다는 FastAPI가 두 배는 더 빠르기 때문에 (Because of 비동기 지원!!!) FastAPI 공부 겸 ... 개념 닦기
* 이전 포스트에서 이어집니다 (https://asidefine.tistory.com/329)
* 이후 포스트로 이어집니다 (https://asidefine.tistory.com/332)
항목 | Flask | FastAPI | Django + DRF |
프레임워크 타입 | 마이크로 프레임워크 | 비동기 지원 마이크로 프레임워크 | 풀스택 프레임워크 + REST 확장 |
비동기 지원 | ❌ 기본 미지원 (추가 패키지 필요) | ✅ async/await 완전 지원 | 🔄 제한적 (DRF + ASGI 설정 시 가능) |
성능 (속도) | 느림 | 매우 빠름 | 보통 |
설정 복잡도 | 매우 간단 | 간단 | 복잡함 |
개발 난이도 | 쉬움 | 쉬움 + 타입힌트 필요 | 상대적으로 어려움 |
자동 문서화 | ❌ 수동 설정 필요 (Swagger 따로 붙여야 함) | ✅ 자동 생성 (Swagger, ReDoc) | ✅ 자동 생성 (DRF + CoreAPI/OpenAPI) |
ORM 연동 | 없음 (SQLAlchemy 등 수동 설정) | 없음 (Tortoise 등 외부 사용) | ✅ Django ORM 완벽 통합 |
대규모 프로젝트 적합성 | 낮음 | 중간 | ✅ 매우 높음 |
대표 사용처 | 간단한 API, 프로토타입 | 빠르고 효율적인 서비스 API | 복잡한 웹/앱 백엔드, MSA, 기업 시스템 |
API 통신 방식 정리
✅ API는 목적에 따라 다양한 방식으로 구현됨
- RESTful 방식
- 최근 가장 많이 사용되는 방식
- HTTP/1.1 기반 통신을 사용함
- JSON, XML 등 형식으로 데이터를 주고받음
- RPC 방식
- 원격 프로시저 호출(Remote Procedure Call) 방식
- 클라이언트가 서버의 함수를 직접 호출하듯 통신함
- gRPC의 등장 이후 많이 쓰이는 추세임
- Python에서는 RESTful(FastAPI, Flask)과 RPC(gRPC) 방식 모두 구현 가능함
📌 RESTful 방식
🔹 Flask
- 가볍고 간단한 REST API 라이브러리임
- 소규모 또는 중규모 프로젝트에 적합함
- 표준화가 잘 되어 있지 않음
- HTTP/1.1은 커넥션당 하나의 처리만 가능하므로, 동시 요청 처리 시 병목이 발생함
- 프로토타입이나 기능 테스트용으로 적합함
📦 예시 코드 (Flask)
from flask import Flask, request, jsonify
from flask_swagger_ui import get_swaggerui_blueprint
app = Flask(__name__)
SWAGGER_URL = '/swagger'
API_URL = '/static/swagger.json'
swaggerui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={'app_name': "My Flask App"}
)
app.register_blueprint(swaggerui_blueprint, url_prefix=SWAGGER_URL)
@app.route('/')
def hello():
return 'Hello, World!'
@app.route('/user/<username>')
def show_user_profile(username):
return f'User {username}'
@app.route('/post', methods=['POST'])
def create_post():
data = request.get_json()
return jsonify(data), 201
if __name__ == '__main__':
app.run(debug=True)
🔹 FastAPI
- Flask보다 더 빠르고 효율적인 Framework임
- asyncio와 type hint를 기반으로 버그를 줄이고 개발 생산성을 높임
- Swagger UI와 자동 문서화가 기본 제공됨
- HTTP/1.1의 구조적 한계를 공유함
📦 예시 코드 (FastAPI)
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(title="My FastAPI App", docs_url="/docs", redoc_url="/redoc")
class Item(BaseModel):
name: str
price: float
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
@app.post("/items/")
def create_item(item: Item):
return item.dict()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
📌 RPC 방식 (gRPC)
- HTTP/2.0 기반으로 동작하며, 양방향 스트리밍 지원함
- **지연(latency)**과 리소스 효율성 측면에서 HTTP/1.1보다 뛰어남
- 하나의 커넥션에서 여러 요청/응답을 처리할 수 있음
- 데이터는 Protocol Buffers (protobuf) 를 통해 바이너리로 직렬화되어 매우 빠름
- MSA(Microservice Architecture) 환경에서 적극적으로 사용됨
1️⃣ .proto 파일 정의
syntax = "proto3";
package greet;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse) {}
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
2️⃣ gRPC 서버 구현
import grpc
from concurrent import futures
import time
from protos.greeter_pb2 import HelloReply
from protos.greeter_pb2_grpc import GreeterServicer, add_GreeterServicer_to_server
class MyGreeterServicer(GreeterServicer):
def SayHello(self, request, context):
return HelloReply(message=f'Hello, {request.name}!')
def run_server(host, port):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
add_GreeterServicer_to_server(MyGreeterServicer(), server)
server.add_insecure_port(f'{host}:{port}')
server.start()
print(f"Server started at {host}:{port}...")
try:
while True:
time.sleep(60 * 60 * 24)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
run_server('0.0.0.0', 50051)
3️⃣ gRPC 클라이언트 구현
import grpc
from protos.greeter_pb2 import HelloRequest
from protos.greeter_pb2_grpc import GreeterStub
def run_client(host, port):
channel = grpc.insecure_channel(f'{host}:{port}')
stub = GreeterStub(channel)
response = stub.SayHello(HelloRequest(name='John Doe'))
print(response.message)
if __name__ == '__main__':
run_client('localhost', 50051)
4️⃣ gRPC + Swagger 연동 예시
def run_server(host, port):
server = SwaggerDecoratedServer(
grpc.server(futures.ThreadPoolExecutor(max_workers=10)),
swagger_host=host,
swagger_port=port+1,
)
add_GreeterServicer_to_server(MyGreeterServicer(), server)
server.add_insecure_port(f'{host}:{port}')
server.start()
print(f"gRPC Server started at {host}:{port}...")
print(f"Swagger docs: http://{host}:{port+1}/docs")
try:
while True:
time.sleep(60 * 60 * 24)
except KeyboardInterrupt:
server.stop(0)
🔍 비교 정리
항목FlaskFastAPIgRPC
통신방식 | RESTful | RESTful | RPC |
네트워크 | HTTP/1.1 | HTTP/1.1 | HTTP/2.0 |
데이터 형식 | JSON, XML | JSON, XML | Protocol Buffers (바이너리) |
속도 | 느림 | 빠름 | 매우 빠름 |
주요 사용처 | 프로토타입, 테스트 | 웹/앱 서비스 | MSA 아키텍처, 서비스 간 통신 |
gRPC 기반으로 해서 빨랐던 게 있었는데 ? -> Trition Inference Server
이전에 Trtion Inference Server 역시 RestAPI 그리고 gRPC 모두 지원한다는 부분이 떠올랐다 (https://asidefine.tistory.com/319)
이렇게 또 한 번 복습
Reference.
728x90