TrendShift 딥다이브 · 2026-07-01

FastAPI 딥다이브
— 타입 힌트만으로 API를 완성하는 파이썬 웹 프레임워크

FastAPI는 파이썬 타입 힌트 기반의 현대적 고성능 웹 프레임워크다. 함수 시그니처에 타입을 적어두면 요청 검증 · 직렬화 · 자동 문서화(OpenAPI/Swagger)가 전부 공짜로 따라온다. 내부적으로는 Starlette(ASGI 웹 계층) + Pydantic(데이터 검증) + Uvicorn(ASGI 서버)이라는 세 거인의 어깨 위에 올라앉아 있고, 그 위에 FastAPI만의 핵심 발명품인 Depends() 의존성 주입 시스템을 얹었다. Node.js·Go급 성능(벤치마크 기준)을 내면서도 Flask만큼 배우기 쉽다는 평가를 받아, 현재 파이썬 생태계에서 가장 널리 쓰이는 API 프레임워크 중 하나로 자리잡았다. (저장소: fastapi/fastapi · Python · v0.138.2 · MIT License · 제작자 Sebastián Ramírez)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 저장소가 대체 무엇인가.

핵심 메시지

"함수 시그니처에 타입을 적으면, 그 타입이 검증기·직렬화기·문서 작성자 역할을 동시에 한다."

일반적인 웹 프레임워크에서는 요청 데이터 검증 로직을 직접 짜고, 응답 형식을 직접 맞추고, API 문서는 별도로 관리한다. FastAPI는 이 세 가지를 파이썬 타입 힌트 하나로 통합했다. def create_item(item: Item)라고만 써두면, FastAPI가 런타임에 함수 시그니처를 들여다보고(인트로스펙션) Item이 Pydantic 모델이라는 걸 파악한 뒤 — 요청 본문을 그 모델로 자동 검증하고, 실패하면 422 에러를 자동으로 반환하고, 성공하면 파싱된 객체를 함수에 주입하고, 응답을 다시 JSON으로 직렬화하고, 이 모든 스키마를 OpenAPI 문서로 자동 생성한다.

여기에 Depends()라는 의존성 주입(DI) 시스템을 더해, "이 라우트를 실행하기 전에 DB 세션을 열고, 토큰을 검증하고, 사용자 객체를 조회해줘" 같은 반복 로직을 함수 시그니처 안에서 선언적으로 조립할 수 있게 했다. Starlette 위에서 ASGI(비동기 서버 게이트웨이 인터페이스)를 그대로 활용하므로 async defdef 핸들러를 자유롭게 섞어 쓸 수 있다.

용어
타입 힌트 (Type Hint)
파이썬 함수의 매개변수나 반환값에 : int, : str, : Item처럼 타입을 명시하는 문법(PEP 484). 원래는 IDE 자동완성과 정적 분석 도구(mypy)를 돕기 위한 "힌트"일 뿐 런타임에 강제되지 않았다. FastAPI는 이 힌트를 런타임에 실제로 읽어서(inspect.signature) 검증·직렬화·문서화에 활용하는 것이 핵심 아이디어다.

2왜 주목받는가

Flask · Django REST Framework 대비 장점 · 트렌딩 이유.

2018년 등장 이후 FastAPI는 파이썬 API 프레임워크 생태계의 지각변동을 일으켰다. 기존 강자였던 Flask는 최소주의(microframework) 철학이라 검증·직렬화·문서화를 전부 Flask-RESTful, marshmallow, flasgger 같은 별도 라이브러리로 조립해야 했다. Django REST Framework(DRF)는 기능은 강력하지만 Django 전체(ORM, admin, settings)를 끌고 들어와야 하고 시리얼라이저를 직접 클래스로 작성해야 하는 보일러플레이트가 많다. 두 프레임워크 모두 WSGI 기반이라 네이티브 async를 지원하지 않는다(Django는 3.1+부터 부분 지원).

경쟁 프레임워크 상세 비교

기능FlaskDjango REST FrameworkFastAPI
비동기(async) 네이티브 지원제한적(확장 필요)부분적✓ (ASGI 기반)
요청 검증별도 라이브러리 필요Serializer 직접 작성✓ 타입 힌트만으로 자동
자동 API 문서(OpenAPI)확장 필요(flasgger)확장 필요(drf-spectacular)✓ 기본 내장
에디터 자동완성/타입체크약함약함✓ 강력(Pydantic 모델 기반)
의존성 주입 시스템없음없음(Mixin 방식)✓ Depends()
학습 곡선매우 쉬움가파름쉬움~보통
ORM 종속성없음(자유 선택)Django ORM 사실상 강제없음(자유 선택)
FastAPI의 핵심 차별점 세 가지
① 타입 힌트 = 검증+직렬화+문서 ② Depends() DI ③ ASGI 네이티브 async

Flask는 빠르고 배우기 쉽지만 API용 부가기능이 없다. DRF는 기능이 다 있지만 보일러플레이트가 많고 Django에 묶인다. FastAPI는 "타입 힌트 하나로 세 가지를 자동화"하는 아이디어로 이 둘 사이의 공백을 정확히 채웠다. 특히 에디터에서 item.을 입력했을 때 Pydantic 모델의 필드가 자동완성되는 개발자 경험(DX)이 채택을 가속화한 핵심 요인으로 꼽힌다.

이런 상황을 상상해봐

주문서 양식을 설계한다고 하자. Flask라면: 양식을 받고(request.json), 필드가 있는지 하나하나 확인하고(if 'name' not in data), 타입이 맞는지 확인하고, 에러 메시지를 직접 만들고, 마지막으로 API 문서 페이지에 이 양식을 손으로 다시 옮겨 적어야 한다. FastAPI라면: class Order(BaseModel): name: str; qty: int 하나만 정의하면 검증도, 에러 메시지도, 문서 페이지(Swagger UI)도 전부 그 정의에서 자동으로 파생된다. "양식을 한 번만 그리면 검증기와 안내판이 저절로 생기는" 셈이다.

3기술 스택 전체 지도

Starlette(ASGI) · Pydantic(검증) · Uvicorn(서버) · 타입 힌트 각각 상세.

핵심 의존성 (pyproject.toml 기준)

패키지버전 조건역할
starlette>=0.46.0ASGI 웹 프레임워크 — 라우팅·미들웨어·요청/응답 객체·WebSocket의 기반. FastAPI는 이를 상속·확장한다.
pydantic>=2.9.0데이터 검증/직렬화 라이브러리 — 요청 바디, 쿼리 파라미터, 응답 모델을 정의하는 BaseModel 제공. Rust로 작성된 pydantic-core가 실제 검증을 수행해 매우 빠르다.
typing-extensions>=4.8.0표준 typing 모듈에 아직 없는 최신 타입 기능(예: Annotated) 백포트.
typing-inspection>=0.4.2타입 힌트를 런타임에 안전하게 분석·순회하는 유틸리티 — Pydantic v2와 FastAPI가 공통으로 의존.
annotated-doc>=0.0.2Annotated[X, Doc("설명")] 형태로 파라미터 문서 문자열을 부여하는 표준화 라이브러리 — FastAPI 소스 전체(예: applications.py)의 매개변수 docstring에 사용된다.

optional dependencies — pip install "fastapi[standard]"

패키지역할
fastapi-cli[standard]fastapi dev / fastapi run CLI 명령 제공 — 개발 서버 실행, 프로덕션 실행을 감싼 래퍼
uvicorn[standard]ASGI 서버 — uvloop(고성능 이벤트 루프) + httptools 포함 버전
httpxTestClient가 내부적으로 사용하는 HTTP 클라이언트 — 테스트 코드에서 앱을 직접 호출
jinja2서버사이드 HTML 템플릿 렌더링(Jinja2Templates)
python-multipartmultipart/form-data 파싱 — 폼 데이터·파일 업로드 처리에 필수
email-validatorPydantic의 EmailStr 타입 검증에 사용
pydantic-settings환경변수 기반 설정 관리(BaseSettings)
pydantic-extra-types색상·좌표 등 추가 Pydantic 타입
itsdangerous (all만)Starlette SessionMiddleware용 서명 쿠키
pyyaml (all만)OpenAPI 스키마 YAML 출력 등

3계층 스택 구조

┌─────────────────────────────────────────────────┐ │ FastAPI (fastapi/) │ │ - Depends() 의존성 주입 │ │ - 타입 힌트 → 검증/직렬화/OpenAPI 자동 변환 │ │ - APIRouter, path operation 데코레이터 │ └───────────────────┬───────────────────────────────┘ │ 상속(FastAPI(Starlette)) + 함수 호출 ┌────────────────────▼───────────────────────────────┐ │ Starlette │ │ - ASGI 애플리케이션 프레임워크 │ │ - Route, Router, Middleware, Request/Response │ │ - WebSocket, BackgroundTasks, TestClient 기반 │ └────────────────────┬───────────────────────────────┘ │ ASGI 프로토콜 (async callable) ┌────────────────────▼───────────────────────────────┐ │ Uvicorn (ASGI 서버) │ │ - HTTP/1.1, WebSocket을 파싱해 ASGI scope로 변환 │ │ - uvloop(이벤트 루프) + httptools(HTTP 파서) │ └────────────────────┬───────────────────────────────┘ │ TCP 소켓 [ 클라이언트 브라우저 / curl / httpx ] ※ 별도 축: Pydantic — 위 모든 계층과 독립적으로 "타입 → 검증 스키마 → JSON Schema" 변환을 전담

각 계층 상세 역할

계층 1

Starlette — ASGI 웹 프레임워크

FastAPI 클래스 자체가 class FastAPI(Starlette):로 Starlette를 상속한다. 라우팅 트리, 미들웨어 체인, Request/Response 객체, WebSocket 지원, 예외 처리 미들웨어(ExceptionMiddleware, ServerErrorMiddleware)까지 전부 Starlette가 제공하는 것을 FastAPI가 그대로 쓰거나 살짝 확장한다. FastAPI 문서가 "우리는 Starlette 위의 얇은 레이어"라고 자주 표현하는 이유다.

계층 2

Pydantic — 데이터 검증/직렬화

BaseModel을 상속한 클래스가 요청 바디, 응답 모델, 설정값의 스키마 역할을 한다. Pydantic v2부터 핵심 검증 로직이 Rust로 작성된 pydantic-core로 이전되어 순수 파이썬 대비 수배~수십 배 빠르다. FastAPI는 이 모델에서 JSON Schema를 뽑아 OpenAPI 문서를 만들고, 요청이 들어올 때 이 모델로 model_validate()를 호출해 검증한다.

계층 3

Uvicorn — ASGI 서버

실제로 TCP 소켓을 열고 HTTP 요청을 받아 ASGI scope/receive/send 3종 세트로 변환해 FastAPI 앱(callable)에 넘기는 것이 Uvicorn의 역할이다. uvicorn[standard]는 libuv 기반 uvloop(이벤트 루프 가속)와 httptools(C로 작성된 HTTP 파서)를 포함해 순수 asyncio 대비 빠르다. fastapi dev main.py를 실행하면 내부적으로 Uvicorn을 자동 리로드 모드로 띄운다.

용어
ASGI (Asynchronous Server Gateway Interface)
파이썬 웹 서버와 애플리케이션 사이의 표준 인터페이스. 기존 WSGI는 동기(sync) 요청 하나에 스레드 하나를 쓰는 모델이라 WebSocket이나 장시간 스트리밍에 취약했다. ASGI는 async def app(scope, receive, send) 형태의 콜러블로 통일해, HTTP뿐 아니라 WebSocket·수명주기(lifespan) 이벤트까지 하나의 프로토콜로 다룬다. Starlette와 FastAPI 모두 ASGI 애플리케이션이다.

4아키텍처 심화 분석

요청 처리 흐름도 + OpenAPI 자동생성 파이프라인 + 핵심 설계 패턴.

요청 처리 전체 흐름 (ASCII 다이어그램)

클라이언트 요청 (HTTP) │ ▼ ┌───────────────────────────────────────────────────────┐ │ Uvicorn (ASGI 서버) │ │ HTTP 파싱 → scope/receive/send 생성 │ └───────────────────────┬─────────────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────┐ │ Starlette 미들웨어 체인 │ │ ServerErrorMiddleware → 사용자 미들웨어들 → │ │ ExceptionMiddleware → AsyncExitStackMiddleware │ └───────────────────────┬─────────────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────┐ │ ① 라우팅 (APIRouter) │ │ URL 패턴 매칭 → 해당 APIRoute 선택 │ │ 경로 파라미터 추출 (예: /items/{item_id} → item_id="5") │ └───────────────────────┬─────────────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────┐ │ ② 의존성 해결 (solve_dependencies) │ │ get_request_handler가 만든 Dependant 그래프를 순회 │ │ - 하위 의존성부터 재귀적으로 먼저 resolve │ │ - Depends(oauth2_scheme) → Depends(get_current_user) │ │ → 실제 라우트 함수 순서로 값이 쌓임 │ │ - 동일 요청 내 캐시(use_cache=True 기본값) │ └───────────────────────┬─────────────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────┐ │ ③ 파라미터 검증 (Pydantic) │ │ Query/Path/Header/Cookie/Body 각각을 타입에 맞게 파싱 │ │ 실패 시 → RequestValidationError → 422 응답 (여기서 중단) │ └───────────────────────┬─────────────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────┐ │ ④ 핸들러 실행 (run_endpoint_function) │ │ async def면 그대로 await │ │ 일반 def면 스레드풀(run_in_threadpool)에서 실행 │ │ → 동기 코드가 이벤트 루프를 막지 않도록 │ └───────────────────────┬─────────────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────┐ │ ⑤ 응답 직렬화 (serialize_response) │ │ response_model이 있으면 그 모델로 재검증 + jsonable_encoder │ │ 없으면 반환값을 그대로 인코딩 │ └───────────────────────┬─────────────────────────────────┘ ▼ ┌───────────────────────────────────────────────────────┐ │ ⑥ 응답 반환 (JSONResponse 등) │ │ BackgroundTasks가 있으면 응답 전송 후 백그라운드 실행 │ └───────────────────────┬─────────────────────────────────┘ ▼ 클라이언트에게 응답 (HTTP)

OpenAPI 자동생성 파이프라인

앱 시작 시 (FastAPI.setup() 호출) │ ▼ GET /openapi.json 라우트 등록 │ (첫 호출 시에만 실제 생성, 이후 캐시) ▼ get_openapi(routes=app.routes, ...) ── fastapi/openapi/utils.py │ ├─ 모든 APIRoute 순회 │ ├─ 각 라우트의 Dependant에서 파라미터 필드 추출 │ │ (Query/Path/Header/Cookie/Body 전부 Pydantic FieldInfo) │ ├─ 파라미터 → OpenAPI Parameter Object 변환 │ ├─ request_body(BaseModel) → JSON Schema 변환 │ └─ response_model → responses.{status}.content 스키마 변환 │ └─ 전체를 모아 OpenAPI 3.1 스펙 dict 조립 │ ▼ /docs (Swagger UI) ── openapi.json을 fetch해 대화형 문서 렌더링 /redoc (ReDoc) ── 동일 스펙을 다른 UI로 렌더링

핵심 설계 패턴 두 가지

패턴 1

타입 힌트 인트로스펙션 (Dependant 그래프 빌드)

라우트 함수를 등록하는 시점에 FastAPI는 inspect.signature()로 함수의 모든 매개변수를 읽고, 각 매개변수의 타입 힌트와 기본값(Depends(), Query(), Body() 등)을 분석해 Dependant라는 데이터 구조를 만든다(fastapi/dependencies/models.py). 이 Dependant는 "이 함수를 실행하려면 어떤 하위 의존성들을 먼저 해결해야 하는지"를 트리 형태로 표현한다. 이 분석은 요청이 오기 전, 앱 시작 시 한 번만 수행되고, 이후 요청마다는 이미 만들어진 그래프를 순회하기만 하므로 빠르다.

패턴 2

의존성 주입(Dependency Injection) — Depends()

Depends(callable)는 "이 콜러블을 먼저 실행해서 나온 값을 이 매개변수에 넣어줘"라는 선언이다. 콜러블은 함수든 클래스든 상관없고, 그 콜러블 자체도 다시 Depends()를 매개변수로 가질 수 있어 의존성이 의존성을 부르는 트리 구조가 만들어진다. 요청마다 solve_dependencies()(fastapi/dependencies/utils.py)가 이 트리를 리프 노드부터 재귀적으로 해결하며, 기본적으로 같은 요청 안에서 동일한 의존성은 한 번만 호출하고 캐시한다(use_cache=True). yield를 쓰는 의존성은 컨텍스트 매니저처럼 동작해 응답 후 정리 코드(DB 세션 종료 등)를 실행한다.

# 의존성이 의존성을 부르는 전형적인 체인
def get_db():
    db = SessionLocal()
    try:
        yield db          # 여기까지가 "생성"
    finally:
        db.close()        # 응답 후 자동 실행되는 "정리"

def get_current_user(
    token: Annotated[str, Depends(oauth2_scheme)],
    db: Annotated[Session, Depends(get_db)],
):
    ...  # token과 db는 이미 해결된 상태로 주입됨
    return user

@app.get("/users/me")
def read_current_user(
    user: Annotated[User, Depends(get_current_user)]
):
    return user  # oauth2_scheme → get_db, get_current_user 순으로 자동 해결

5디렉토리 구조 해부

fastapi/ 패키지 내부 주요 모듈 역할.

fastapi/ ├── __init__.py # 공개 API 재노출 + __version__ = "0.138.2" ├── applications.py # FastAPI 클래스 본체 (4768줄) — 라우트 데코레이터, │ # openapi()/setup() 메서드, 미들웨어 조립 ├── routing.py # APIRouter/APIRoute (6243줄) — 요청 핸들러 팩토리 │ # get_request_handler, solve_dependencies 호출부, │ # serialize_response, run_endpoint_function ├── params.py # Query/Path/Body/Header/Cookie/Security/Depends │ # 클래스 정의 — 전부 Pydantic FieldInfo 계열 ├── param_functions.py # Query()/Path()/Body() 등 사용자가 실제로 호출하는 │ # 팩토리 함수 (params.py 클래스를 생성해 반환) ├── dependencies/ │ ├── models.py # Dependant 데이터클래스 — 의존성 그래프 노드 정의 │ └── utils.py # get_dependant(), solve_dependencies() — DI 핵심 로직 ├── encoders.py # jsonable_encoder() — 임의 파이썬 객체를 │ # JSON 직렬화 가능한 형태로 재귀 변환 ├── openapi/ │ ├── utils.py # get_openapi() — 라우트 전체를 훑어 OpenAPI 스펙 생성 │ ├── docs.py # Swagger UI / ReDoc HTML 생성 │ └── models.py # OpenAPI 스펙 자체의 Pydantic 모델(스펙 검증용) ├── security/ # OAuth2PasswordBearer, HTTPBasic, APIKeyHeader 등 │ └── oauth2.py # OAuth2 플로우 구현 (693줄) ├── middleware/ # CORS, GZip, TrustedHost, WSGI 브리지 ├── _compat/ # Pydantic 버전 호환 레이어 (v1/v2 차이 흡수) ├── exceptions.py # HTTPException, RequestValidationError 등 ├── background.py # BackgroundTasks — 응답 후 실행되는 작업 큐 ├── concurrency.py # run_in_threadpool 등 동기/비동기 브리지 ├── testclient.py # Starlette TestClient 재노출 (httpx 기반) ├── cli.py # `fastapi` CLI 진입점 (fastapi-cli 위임) └── datastructures.py # UploadFile, Default 등 보조 타입
용어
jsonable_encoder
fastapi/encoders.py에 있는 함수로, Pydantic 모델뿐 아니라 datetime, Enum, dataclass, set, 커스텀 객체 등 "JSON으로 바로 못 바꾸는" 파이썬 객체를 재귀적으로 순회하며 dict/list/str/숫자 같은 JSON 호환 타입으로 변환한다. 응답을 직렬화하는 마지막 단계에서 항상 거치는 관문이다.

6학습 포인트 (기술별)

이 저장소에서 무엇을 배울 수 있는가.

1. 타입 힌트 기반 런타임 검증 — Pydantic + typing 인트로스펙션

FastAPI의 가장 근본적인 아이디어는 "타입 힌트를 정적 분석 도구용 장식이 아니라 런타임 동작을 결정하는 데이터로 쓴다"는 것이다. fastapi/dependencies/utils.pyget_dependant()inspect.signature()typing.get_type_hints()를 조합해 함수의 각 매개변수 타입을 분석하고, 그것이 Pydantic 모델인지, Annotated[X, Query()]인지, Depends()인지 분류한다.

배울 것: inspect 모듈로 함수 시그니처 읽기, typing.Annotated로 타입에 메타데이터 부착하기, Pydantic BaseModelmodel_validate()/model_dump() 활용, pydantic-core(Rust 백엔드)가 왜 빠른지.

2. 의존성 주입(DI) 시스템 설계 — Depends()

Java의 Spring이나 .NET의 DI 컨테이너 같은 무거운 프레임워크 없이, 파이썬 함수 매개변수 문법만으로 DI를 구현한 사례다. fastapi/dependencies/models.pyDependant 클래스와 fastapi/dependencies/utils.pysolve_dependencies()를 함께 읽으면, "선언적 DI"를 데코레이터·클래스 없이 순수 함수 합성으로 구현하는 방법을 배울 수 있다.

배울 것: 의존성 그래프의 재귀적 해결, yield 기반 컨텍스트 매니저 패턴(생성-사용-정리), 요청 스코프 캐싱(use_cache), 서브 의존성 오버라이드(app.dependency_overrides)로 테스트 시 실제 DB 대신 목(mock) 주입하기.

3. ASGI와 Starlette — 비동기 웹 계층의 표준

FastAPI는 Starlette를 상속만 한 게 아니라, WSGI/ASGI의 차이, 미들웨어 체인이 요청을 어떻게 감싸는지, lifespan 이벤트(시작/종료 훅)가 어떻게 동작하는지를 배우는 좋은 교재다. fastapi/applications.pyFastAPI.__init__ServerErrorMiddleware, ExceptionMiddleware, AsyncExitStackMiddleware를 쌓는 순서를 보면 미들웨어 체인 설계를 이해할 수 있다.

배울 것: ASGI 3-tuple(scope/receive/send) 프로토콜, 미들웨어 onion(양파) 구조, async defdef 핸들러가 스레드풀로 자동 분기되는 이유, WebSocket과 HTTP를 하나의 인터페이스로 통합하는 설계.

4. 자동 API 문서화 — OpenAPI/JSON Schema 생성기 만들기

fastapi/openapi/utils.pyget_openapi()는 "코드에서 문서를 역생성"하는 대표 사례다. 라우트마다 이미 존재하는 Dependant(파라미터 정보)와 Pydantic 모델의 JSON Schema를 조합해 OpenAPI 3.1 스펙 전체를 조립한다. 문서를 별도로 유지보수할 필요 없이 코드 자체가 단일 진실원(source of truth)이 되는 설계를 배울 수 있다.

배울 것: OpenAPI 스펙 구조(paths/components/schemas), Pydantic 모델 → JSON Schema 변환, Swagger UI/ReDoc이 스펙을 어떻게 소비하는지, response_model로 응답 스키마와 실제 반환 객체를 분리하는 이유(민감 필드 제외 등).

5. 보안 스킴 추상화 — OAuth2/JWT를 Depends()로 표현하기

fastapi/security/oauth2.pyOAuth2PasswordBearer는 "보안 스킴도 결국 하나의 의존성"이라는 것을 보여준다. 이 클래스의 인스턴스 자체가 callable이라 Depends(oauth2_scheme)로 쓰이며, 동시에 OpenAPI 문서에 자물쇠 아이콘과 인증 방식을 자동으로 표시하는 메타데이터 역할도 겸한다.

배울 것: OAuth2 Password/Authorization Code 플로우의 파이썬 구현, __call__을 구현한 클래스를 Depends()에 넣는 패턴, JWT 토큰 검증을 의존성 체인으로 표현하기, Swagger UI의 "Authorize" 버튼이 동작하는 원리.

7하드웨어 / 시스템 요구사항

실행 환경 · 설치 조건.

항목요구사항
Python 버전3.10 이상 (pyproject.toml requires-python = ">=3.10", 3.10~3.14 공식 지원)
필수 의존성starlette>=0.46.0, pydantic>=2.9.0, typing-extensions, typing-inspection, annotated-doc
ASGI 서버 (프로덕션 실행 시 필요)Uvicorn(권장), Hypercorn, Daphne 등 — fastapi[standard] 설치 시 Uvicorn 자동 포함
메모리 사용순수 파이썬 프레임워크 수준(수십 MB) — 실제 사용량은 애플리케이션 코드·워커 수에 좌우
동시성 모델단일 프로세스 내 asyncio 이벤트 루프 — 수평 확장은 Uvicorn --workers 또는 Gunicorn+Uvicorn 워커, 컨테이너 복제
OSLinux/macOS/Windows 모두 지원 (Python이 동작하는 모든 곳)
선택적 시스템 의존성python-multipart(파일 업로드 시), email-validator(EmailStr 검증 시)
운영 특성
동기(def)와 비동기(async def)를 같은 앱에서 자유롭게 혼용 가능

FastAPI는 라우트 핸들러가 async def인지 일반 def인지 자동으로 감지한다. async def는 이벤트 루프에서 직접 await되고, 일반 defrun_in_threadpool로 별도 스레드풀에서 실행되어 블로킹 코드(동기 DB 드라이버 등)가 이벤트 루프 전체를 멈추지 않도록 한다. 이 덕분에 레거시 동기 라이브러리를 async 코드베이스에 안전하게 섞어 쓸 수 있다.

현실적 주의사항
async def 안에서 블로킹 코드를 직접 호출하면 전체 서버가 멈춘다

async def 핸들러 안에서 time.sleep()이나 동기 requests 라이브러리 같은 블로킹 호출을 그대로 쓰면, 이벤트 루프 자체가 멈춰 그 순간 다른 모든 요청도 함께 지연된다. 블로킹 작업이 필요하면 일반 def로 선언하거나 run_in_threadpool로 명시적으로 감싸야 한다.

8직접 해볼 수 있는 실습 과제

난이도별 5개.

난이도: 입문Lv.1

실습 1 — Hello World API + 자동 문서 확인

FastAPI를 설치하고 최소 앱을 실행한 뒤 자동 생성된 Swagger UI를 직접 눈으로 확인한다.

pip install "fastapi[standard]"

# main.py
from fastapi import FastAPI

app = FastAPI()

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

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}
fastapi dev main.py
# http://127.0.0.1:8000/docs 에서 Swagger UI 확인
# http://127.0.0.1:8000/items/5?q=test 호출해보기
# http://127.0.0.1:8000/items/abc 호출 → 422 검증 에러 확인 (int가 아니라서)

확인 포인트: item_id: int인데 문자열을 넣으면 자동으로 422 에러가 나는 것을 관찰. /docs에서 각 파라미터 타입이 어떻게 표시되는지 확인.

난이도: 초급Lv.2

실습 2 — Pydantic 모델로 POST 바디 검증하기

Pydantic BaseModel을 정의하고 POST 요청 바디로 받아, 검증 실패 시 에러 응답 형태를 관찰한다.

from pydantic import BaseModel
from fastapi import FastAPI

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool | None = None

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

확인 포인트: /docs에서 "Try it out"으로 price에 문자열("abc")을 넣어 422 에러의 상세 구조(loc, msg, type)를 확인. response_model=Item을 추가해 응답 스키마도 검증되는지 비교.

난이도: 중급Lv.3

실습 3 — Depends()로 공통 쿼리 파라미터 + DB 세션 의존성 만들기

여러 라우트에서 재사용되는 공통 로직(페이지네이션 파라미터, 가짜 DB 세션)을 Depends()로 뽑아내 본다.

from typing import Annotated
from fastapi import Depends, FastAPI

app = FastAPI()

async def common_pagination(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}

def get_fake_db():
    db = {"users": ["alice", "bob", "carol"]}
    try:
        yield db
    finally:
        print("DB 연결 정리 완료")  # 응답 후 자동 실행

@app.get("/users/")
def list_users(
    pagination: Annotated[dict, Depends(common_pagination)],
    db: Annotated[dict, Depends(get_fake_db)],
):
    users = db["users"][pagination["skip"]: pagination["skip"] + pagination["limit"]]
    return {"users": users, **pagination}

확인 포인트: 같은 common_pagination 의존성을 다른 라우트(/items/)에도 재사용해보고, yield 이후 코드가 응답 전송 이후 실행되는 시점을 print로 확인.

난이도: 중급Lv.4

실습 4 — OAuth2PasswordBearer로 JWT 인증 라우트 만들기

FastAPI 보안 유틸리티로 로그인 → 토큰 발급 → 보호된 라우트 접근 흐름을 구현한다.

from typing import Annotated
from fastapi import Depends, FastAPI, HTTPException
from fastapi.security import OAuth2PasswordBearer

app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
    if token != "valid-token":
        raise HTTPException(status_code=401, detail="Invalid token")
    return {"username": "demo_user"}

@app.get("/users/me")
def read_users_me(
    current_user: Annotated[dict, Depends(get_current_user)]
):
    return current_user

확인 포인트: /docs에 자물쇠 아이콘이 자동으로 생기는 것을 확인. Authorization 헤더 없이 호출 시 401, 잘못된 토큰일 때의 에러 구조 비교. pyjwt를 추가해 실제 JWT 서명·검증으로 확장해본다.

난이도: 고급Lv.5

실습 5 — FastAPI 소스 클론 + solve_dependencies 실행 흐름 디버깅

저장소를 직접 클론하고, 디버거로 solve_dependencies()가 실제로 호출되는 시점을 추적한다.

git clone https://github.com/fastapi/fastapi
cd fastapi
pip install -e ".[all]"
# fastapi/dependencies/utils.py의 solve_dependencies에 breakpoint() 삽입
# 아무 예제 앱이나 실행 후 요청을 보내 콜스택 관찰
python -m pytest tests/test_dependency_cache.py -v   # 의존성 캐싱 테스트 확인

확인 포인트: get_dependant()가 앱 시작(라우트 등록) 시 한 번만 호출되고, solve_dependencies()는 매 요청마다 호출된다는 시점 차이를 콜스택으로 직접 확인. app.dependency_overrides로 테스트에서 실제 의존성을 목으로 교체하는 코드(tests/ 디렉토리 다수)를 찾아 분석.

9관련 기술 심화 학습 로드맵

FastAPI 이해·기여를 위한 주차별 학습 경로.

1주차 — 파이썬 타입 힌트 기초

목표: PEP 484 타입 힌트 문법, Optional/Union/Annotated 이해.

자료: 파이썬 공식 typing 문서(docs.python.org/3/library/typing.html), FastAPI 공식 튜토리얼의 "Python Types Intro" 챕터.

실습: mypy로 타입 체크가 되는 간단한 함수 여러 개 작성.

2주차 — Pydantic v2 깊이 파고들기

목표: BaseModel, validator, model_dump()/model_validate(), JSON Schema 생성 이해.

자료: Pydantic 공식 문서(docs.pydantic.dev), pydantic-core가 Rust로 작성된 이유에 대한 블로그 글.

실습: 중첩 모델, 커스텀 검증자(@field_validator)로 이메일/전화번호 검증 로직 작성.

3주차 — FastAPI 기본기: 라우팅 + 요청/응답 모델

목표: 경로 연산, 쿼리/경로/바디 파라미터, response_model, 상태 코드 관리.

자료: FastAPI 공식 튜토리얼(fastapi.tiangolo.com/tutorial/) 전체.

실습: CRUD API 하나를 처음부터 끝까지 구현 (인메모리 dict 저장소로 충분).

4주차 — 의존성 주입 시스템 마스터

목표: Depends(), 서브 의존성, yield 의존성, 클래스 기반 의존성, dependency_overrides.

자료: "Dependencies" 튜토리얼 섹션, fastapi/dependencies/utils.py 소스 직접 읽기.

실습: 실습 3~4를 확장해 DB 세션+인증+권한 검사를 의존성 체인으로 조합.

5주차 — ASGI와 Starlette 이해

목표: ASGI 스펙, 미들웨어, lifespan, WebSocket, BackgroundTasks.

자료: Starlette 공식 문서(starlette.dev), ASGI 스펙(asgi.readthedocs.io).

실습: 커스텀 미들웨어 작성(요청 처리 시간 로깅), WebSocket 채팅 엔드포인트 구현.

6주차 — 보안 + 프로덕션 배포

목표: OAuth2/JWT, CORS, Uvicorn 워커 설정, Docker 배포.

자료: "Security" 튜토리얼 섹션, FastAPI 공식 "Deployment" 가이드.

실습: JWT 로그인 API를 Docker 컨테이너로 패키징하고 Gunicorn+Uvicorn 워커로 실행.

7~8주차 — 오픈소스 기여

목표: FastAPI 저장소 구조 파악, 테스트 작성법 익히기, PR 프로세스 이해.

자료: CONTRIBUTING.md, tests/ 디렉토리의 기존 테스트 패턴.

실습: 문서 번역/개선 PR, 또는 이슈 트래커의 good-first-issue 라벨 항목에 도전.

10핵심 키워드 사전

이 저장소를 이해하는 데 필요한 핵심 용어.

ASGI
Asynchronous Server Gateway Interface
비동기 파이썬 웹 서버-앱 간 표준 인터페이스. WSGI의 async 버전으로, HTTP뿐 아니라 WebSocket과 lifespan 이벤트까지 하나의 콜러블 프로토콜로 다룬다. Starlette, FastAPI, Uvicorn이 모두 이 표준을 따른다.
Pydantic
Pydantic (BaseModel)
파이썬 타입 힌트로 데이터 스키마를 정의하고 런타임에 검증·직렬화하는 라이브러리. v2부터 핵심 로직이 Rust(pydantic-core)로 구현되어 매우 빠르다. FastAPI의 요청/응답 검증, 설정 관리, OpenAPI 스키마 생성이 전부 Pydantic 모델을 기반으로 한다.
의존성 주입
DI (Dependency Injection) — Depends()
함수/클래스가 필요한 것(DB 세션, 현재 사용자 등)을 직접 만들지 않고 외부에서 "주입"받는 설계 패턴. FastAPI에서는 Depends(callable)를 매개변수 기본값처럼 선언하면, 요청마다 그 callable이 먼저 실행되어 반환값이 자동으로 주입된다. 의존성끼리 중첩되면 트리 구조의 해결 순서가 자동으로 결정된다.
OpenAPI
OpenAPI Specification (구 Swagger)
REST API의 엔드포인트, 파라미터, 요청/응답 스키마를 언어 중립적인 JSON/YAML로 기술하는 표준 규격. FastAPI는 코드(라우트+Pydantic 모델)에서 이 스펙을 자동 생성하고, /docs(Swagger UI)와 /redoc(ReDoc) 페이지에서 대화형으로 렌더링한다.
타입 힌트
Type Hint (PEP 484)
name: str, age: int처럼 변수·매개변수·반환값에 타입을 명시하는 문법. 원래는 정적 분석 도구를 위한 것이었으나, FastAPI는 이를 런타임에 실제로 읽어 검증·직렬화·문서 생성의 근거로 삼는다는 점이 독창적이다.
async/await
비동기 프로그래밍 — async def / await
파이썬의 코루틴 문법. async def로 정의한 함수는 await로 다른 비동기 작업이 끝나길 "양보"하며 기다리는 동안 이벤트 루프가 다른 요청을 처리할 수 있다. FastAPI는 async def 핸들러를 이벤트 루프에서 직접 실행하고, 일반 def 핸들러는 스레드풀에서 실행해 블로킹을 방지한다.
Dependant
Dependant (의존성 그래프 노드)
fastapi/dependencies/models.py에 정의된 데이터 클래스. 라우트 함수 하나당 하나씩 만들어지며, 그 함수가 필요로 하는 경로/쿼리/헤더/바디 파라미터 목록과 하위 Depends() 의존성 목록을 트리 형태로 담는다. 앱 시작 시 get_dependant()가 생성하고, 요청마다 solve_dependencies()가 이를 순회해 실제 값을 채운다.
jsonable_encoder
jsonable_encoder()
Pydantic 모델, datetime, Enum, dataclass 등 다양한 파이썬 객체를 JSON으로 바로 직렬화 가능한 dict/list/기본형으로 재귀 변환하는 유틸리티 함수. 응답을 클라이언트에게 보내기 직전 항상 거치는 최종 변환 단계다.
Uvicorn
Uvicorn — ASGI 서버
실제로 TCP 소켓을 열고 HTTP/WebSocket 요청을 받아 ASGI 프로토콜로 변환해 FastAPI 앱에 전달하는 서버 구현체. uvloop(고성능 이벤트 루프)와 httptools(C 기반 HTTP 파서)를 옵션으로 포함해 성능을 낸다. fastapi dev/fastapi run CLI가 내부적으로 Uvicorn을 실행한다.

11참고 링크

더 깊이 파고들기 위한 공식 자료.