본문으로 건너뛰기
Advertisement

FastAPI 개요

FastAPI는 Python 3.8+의 타입 힌트를 기반으로 REST API를 빠르게 구축하는 현대적 웹 프레임워크입니다. 높은 성능, 자동 문서화, Pydantic 통합이 핵심 강점입니다.


FastAPI의 위치

클라이언트 (브라우저 / 앱)
│ HTTP 요청

Uvicorn (ASGI 서버) ← HTTP를 Python 이벤트로 변환


Starlette (ASGI 프레임워크) ← 라우팅, 미들웨어, WebSocket


FastAPI ← Starlette 위에 타입 힌트 + Pydantic + OpenAPI 추가
# 설치
pip install fastapi uvicorn[standard]

# 선택 사항
pip install python-multipart # 파일 업로드
pip install python-jose[cryptography] # JWT
pip install passlib[bcrypt] # 비밀번호 해싱
pip install sqlalchemy # ORM

첫 번째 API

# main.py
from fastapi import FastAPI

app = FastAPI(
title="학습 API",
description="FastAPI 학습용 예제",
version="1.0.0",
)


@app.get("/")
def read_root():
return {"message": "Hello FastAPI"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
# 개발 서버 실행
uvicorn main:app --reload

# 접속
# API: http://localhost:8000
# 문서: http://localhost:8000/docs (Swagger UI)
# 문서: http://localhost:8000/redoc (ReDoc)

경로·쿼리·바디 매개변수

from fastapi import FastAPI
from pydantic import BaseModel
from typing import Annotated
from fastapi import Query, Path, Body

app = FastAPI()


# 경로 매개변수 (Path parameter)
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"user_id": user_id}


# 쿼리 매개변수 (Query parameter)
@app.get("/search")
def search(
q: str,
skip: int = 0,
limit: Annotated[int, Query(ge=1, le=100)] = 10,
):
return {"q": q, "skip": skip, "limit": limit}


# 요청 바디 (Request Body — Pydantic 모델)
class Item(BaseModel):
name: str
price: float
is_offer: bool = False


@app.post("/items/")
def create_item(item: Item):
return {"item_name": item.name, "price": item.price}


# 경로 + 바디 혼합
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_id": item_id, "item": item}

응답 모델과 상태 코드

from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel
from typing import Optional

app = FastAPI()


class UserIn(BaseModel):
name: str
email: str
password: str


class UserOut(BaseModel):
id: int
name: str
email: str
# password 필드 없음 → 응답에서 자동 제외


fake_db: dict[int, dict] = {}
next_id = 1


@app.post(
"/users/",
response_model=UserOut, # 응답 스키마 지정
status_code=status.HTTP_201_CREATED, # 성공 시 201
)
def create_user(user: UserIn):
global next_id
user_data = {"id": next_id, "name": user.name, "email": user.email}
fake_db[next_id] = user_data
next_id += 1
return user_data


@app.get("/users/{user_id}", response_model=UserOut)
def get_user(user_id: int):
if user_id not in fake_db:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"User {user_id} not found",
)
return fake_db[user_id]


# 여러 응답 타입 문서화
from typing import Union


@app.get(
"/items/{item_id}",
responses={
200: {"description": "성공"},
404: {"description": "아이템 없음"},
},
)
def get_item(item_id: int):
if item_id > 100:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}

비동기 엔드포인트

import asyncio
import httpx
from fastapi import FastAPI

app = FastAPI()


# async def: 비동기 I/O에 권장
@app.get("/async-example")
async def async_example():
await asyncio.sleep(0.1) # 논블로킹 대기
return {"result": "async response"}


# 외부 API 호출 (httpx 비동기 클라이언트)
@app.get("/external")
async def call_external():
async with httpx.AsyncClient() as client:
response = await client.get("https://httpbin.org/uuid")
return response.json()


# def vs async def
# - def: 스레드풀에서 실행 (블로킹 OK)
# - async def: 이벤트 루프에서 실행 (await 필수)

@app.get("/sync")
def sync_endpoint():
# CPU-bound 또는 레거시 동기 코드
return {"type": "sync"}


@app.get("/async")
async def async_endpoint():
# I/O-bound: DB 쿼리, HTTP 요청, 파일 읽기
await asyncio.sleep(0)
return {"type": "async"}

앱 이벤트와 Lifespan

from contextlib import asynccontextmanager
from fastapi import FastAPI


# Python 3.9+: lifespan으로 startup/shutdown 처리
@asynccontextmanager
async def lifespan(app: FastAPI):
# 앱 시작 시 실행
print("앱 시작: DB 연결 풀 초기화")
app.state.db_pool = {"connected": True}

yield # 앱 실행 중

# 앱 종료 시 실행
print("앱 종료: DB 연결 풀 정리")
app.state.db_pool = None


app = FastAPI(lifespan=lifespan)


@app.get("/health")
def health_check():
return {"status": "ok", "db": app.state.db_pool["connected"]}

정리

개념설명
FastAPIStarlette + Pydantic + OpenAPI 통합
UvicornASGI 서버 (빠른 비동기 HTTP 처리)
/docsSwagger UI 자동 생성
response_model응답 스키마 지정 + 자동 필터링
HTTPExceptionHTTP 에러 응답
async def비동기 엔드포인트
lifespan앱 시작/종료 이벤트 처리

FastAPI는 타입 힌트를 코드 문서화·검증·직렬화에 모두 활용하는 것이 핵심입니다.

Advertisement