이 디렉터리는 핸드북 문서를 "읽고 끝내는 것"이 아니라 바로 실행해보며 감을 잡도록 만든 예제 모음이다. 예제는 크게 두 축으로 나뉜다.
- 버전별 변화 예제: Python 3.10~3.14에서 새로 들어온 기능을 빠르게 체감
- 주제별 심화 예제: Pydantic, asyncio, FastAPI, SQLAlchemy, dataclass, testing 같은 실전 주제를 코드로 확인
모든 예제는 이 저장소의 .venv 기준으로 점검한다.
개별 실행:
./.venv/bin/python examples/py310_pattern_matching.py
./.venv/bin/python examples/pydantic_validation_pipeline.py
./.venv/bin/python examples/fastapi_service_template_example.py전체 순회:
for file in examples/*.py; do
echo "=== $file ==="
./.venv/bin/python "$file"
done정적 검사:
uv run ty check
uv run ruff check .| 파트 | 먼저 볼 예제 | 왜 먼저 보나 |
|---|---|---|
| Intro | import_packaging_environment_lab.py |
python -m, import cache, pyproject.toml, virtualenv 같은 fundamentals를 코드로 바로 체감하기 좋음 |
| Pythonic | py310_pattern_matching.py, metaprogramming_hooks_lab.py |
Python 문법의 표현력과 메타프로그래밍 훅 선택 감각을 함께 익히기 좋음 |
| Typing | py310_typing_and_zip_strict.py, py312_type_params.py |
modern typing 문법과 boundary 설계 감각을 같이 잡기 좋음 |
| Runtime | py312_sys_monitoring.py, py313_runtime_modes.py, py314_interpreter_pool.py, cpython_runtime_labs.py |
CPython 런타임 방향성과 내부 실험(dis/ast/gc/tracemalloc)을 함께 보여줌 |
| Dataclass | dataclass_patterns.py |
값 객체, default_factory, kw_only, 패턴 매칭 조합을 빨리 익히기 좋음 |
| Asyncio | py311_exception_groups_and_taskgroup.py, asyncio_backpressure_and_cancellation.py |
구조적 동시성, cancellation, backpressure를 함께 익히기 좋음 |
| Pydantic | pydantic_validation_pipeline.py |
core schema, strict/lax, validator/serializer 흐름을 한 번에 보여줌 |
| FastAPI / SQLAlchemy | asgi_lifecycle_lab.py, fastapi_security_auth_lab.py, fastapi_background_tasks_patterns.py, fastapi_realtime_and_middleware_lab.py, websocket_auth_and_rooms_lab.py, websocket_redis_pubsub_lab.py, websocket_client_protocol_reconnect_lab.py, uvicorn_proxy_and_health_lab.py, fastapi_service_template_example.py, sqlalchemy_loading_strategies.py, sqlalchemy_class_based_uow.py, usecase_with_uow_abc.py, sqlalchemy_deployment_profiles.py, alembic_zero_downtime_lab.py |
ASGI 메시지 흐름, authn/authz 경계, BackgroundTasks 경계, realtime transport, websocket 실전 패턴, Redis pub/sub, reconnect protocol, middleware, proxy/health, 서비스 경계, ORM 로딩 전략, class-based UoW, ABC 기반 use case, 배포별 엔진 설정, zero-downtime migration rollout 감각을 같이 확인할 수 있음 |
| Settings | pydantic_settings_patterns.py |
settings.py, env source priority, .env, secrets, pydantic-settings 감각을 빠르게 익히기 좋음 |
| Playbooks / Testing | idempotency_outbox_lab.py, progressive_delivery_backfill_lab.py, tests/test_fastapi_fixtures_and_teardown.py, tests/test_idempotency_and_contracts.py |
retry-safe create path, outbox, chunked resumable backfill, fixture setup/teardown, ASGI contract test, property-based idempotency invariant를 함께 익히기 좋음 |
| 버전 | 파일 | 핵심 기능 | 볼 포인트 |
|---|---|---|---|
| 3.10 | py310_pattern_matching.py |
match/case |
데이터 모양 기반 분기가 얼마나 간결해지는지 |
| 3.10 | py310_typing_and_zip_strict.py |
ParamSpec, TypeGuard, zip(strict=True) |
타입 정밀도와 조용한 데이터 손실 방지 |
| 3.11 | py311_exception_groups_and_taskgroup.py |
TaskGroup, ExceptionGroup, except* |
구조적 동시성과 구조적 실패 처리 |
| 3.11 | py311_tomllib.py |
tomllib |
표준 라이브러리 TOML 파싱 |
| 3.12 | py312_type_params.py |
type parameter syntax, type alias |
typing 문법의 언어화 |
| 3.12 | py312_sys_monitoring.py |
sys.monitoring |
저비용 런타임 이벤트 훅 |
| 3.13 | py313_runtime_modes.py |
free-threaded/JIT 상태 조회 | CPython 런타임 방향성 |
| 3.13 | py313_type_defaults_and_deprecated.py |
type defaults, warnings.deprecated |
제네릭 사용성과 deprecation 신호 |
| 3.14 | py314_annotationlib.py |
annotationlib |
어노테이션 introspection 변화 |
| 3.14 | py314_template_strings.py |
t"...", string.templatelib |
문자열 결과가 아니라 템플릿 구조 다루기 |
| 3.14 | py314_interpreter_pool.py |
InterpreterPoolExecutor |
subinterpreter 기반 병렬성 |
무엇을 보여주나:
TypeAdapter와BaseModel의 공통 엔진- strict vs lax parsing
- validator와 serializer 역할 분리
TypedDict같은 임의 타입 구조 검증
언제 보면 좋나:
- Pydantic handbook 파트를 읽은 직후
- FastAPI request/response DTO를 더 정교하게 설계하고 싶을 때
무엇을 보여주나:
TaskGroup- bounded queue
SemaphoreQueue.shutdown()- cancellation path cleanup
언제 보면 좋나:
- asyncio chapter에서 cancellation/backpressure를 읽은 직후
- worker, fan-out pipeline, webhook consumer 구조를 고민할 때
무엇을 보여주나:
frozen=True,slots=True,kw_only=Truedefault_factory__post_init__()정규화- dataclass와 pattern matching 조합
언제 보면 좋나:
- Pythonic 파트에서 dataclass 챕터를 읽은 직후
- 내부 command/value object를 어떻게 만들지 고민할 때
실행:
./.venv/bin/python examples/dataclass_patterns.py무엇을 보여주나:
__set_name__descriptor binding__init_subclass__등록 패턴- class decorator 후처리
- metaclass 정책 강제
왜 중요한가:
- 메타프로그래밍에서 "가장 작은 도구부터 고르는 기준"을 실행 코드로 체감할 수 있다.
- 선언형 API를 만들 때 어느 훅을 써야 팀 비용이 낮은지 감이 생긴다.
실행:
./.venv/bin/python examples/metaprogramming_hooks_lab.py체크 포인트:
- descriptor가 attribute access를 제어한다.
- subclass 등록이 metaclass 없이도 가능하다.
- class decorator와 metaclass의 책임 차이가 보인다.
무엇을 보여주나:
python file.py와python -m package차이sys.modulesimport cachepyproject.tomlmetadata- virtualenv 감지 신호
왜 중요한가:
- import, packaging, environment 문제는 Python fundamentals에서 가장 자주 팀을 괴롭힌다.
- 상대 import, editable install, interpreter mismatch 문제를 더 구조적으로 보게 해준다.
실행:
./.venv/bin/python examples/import_packaging_environment_lab.py체크 포인트:
- 파일 경로 실행과 모듈 실행이 다르게 동작한다.
- 같은 모듈 import는 cache를 재사용한다.
pyproject.toml가 entry point와 metadata를 선언한다.sys.prefix/sys.base_prefix로 virtualenv 감각을 잡을 수 있다.
무엇을 보여주나:
scope,receive,sendlifespan.startup/lifespan.shutdownhttp.response.start/http.response.body- ASGI app이 response object 대신 message를 보내는 구조
왜 중요한가:
- FastAPI가 "어떤 request object를 직접 받는 프레임워크"가 아니라 ASGI contract 위에 올라간다는 점이 선명해진다.
CGI -> WSGI -> ASGI역사에서 왜 ASGI가 connection/event 모델로 바뀌었는지 코드로 체감할 수 있다.
실행:
./.venv/bin/python examples/asgi_lifecycle_lab.py체크 포인트:
- lifespan과 http가 다른 scope type으로 보인다.
- 앱은 event를
receive()로 읽고send()로 response message를 쓴다. - Uvicorn 같은 ASGI server가 실제로 하는 역할을 추상적으로 이해할 수 있다.
무엇을 보여주나:
BackgroundTasks+ sync taskBackgroundTasks+ async task- inline await가 필요한 작업
- queue/worker로 빼야 하는 작업 분류
왜 중요한가:
- "동기 함수를 background에 넣어도 되는가", "async로 감싸면 해결되는가" 같은 실무 질문에 기준선을 준다.
BackgroundTasks가 durable queue가 아니라는 점을 코드와 출력으로 같이 확인할 수 있다.
실행:
./.venv/bin/python examples/fastapi_background_tasks_patterns.py체크 포인트:
- audit log는
background-sync로 분류된다. - async webhook은
background-async로 분류된다. - invoice PDF 같은 일은
queue-worker로 분류된다. - 결제 승인처럼 응답에 영향을 주는 일은
inline-await로 남는다.
무엇을 보여주나:
- bearer token auth
- cookie session auth
- CSRF 방어 필요성
- admin-only authorization dependency
왜 중요한가:
- FastAPI security는 dependency 몇 줄보다 authn/authz 경계 설계가 더 중요하다.
- cookie와 bearer token이 같은 문제가 아니라는 점을 실행 예제로 바로 볼 수 있다.
실행:
./.venv/bin/python examples/fastapi_security_auth_lab.py체크 포인트:
- member token은 admin route에서
403이 난다. - cookie session은 profile 조회에 쓸 수 있다.
- cookie 기반 write는 CSRF token이 없으면 막힌다.
무엇을 보여주나:
StreamingResponse- SSE (
text/event-stream) - WebSocket echo
- pure ASGI middleware가 HTTP와 WebSocket scope를 보는 방식
왜 중요한가:
- realtime transport를 "그냥 route 종류 하나 더"가 아니라 연결 수명 모델로 이해하게 해준다.
- middleware가 request object보다 더 아래 ASGI 레벨에서 어떻게 응답 header를 다루는지 보인다.
실행:
./.venv/bin/python examples/fastapi_realtime_and_middleware_lab.py체크 포인트:
- plain stream과 SSE의
content-type이 다르다. - WebSocket은 별도 메시지 loop를 가진다.
- pure ASGI middleware는 HTTP와 WebSocket scope를 모두 관찰한다.
무엇을 보여주나:
root_pathTrustedHostMiddlewareHTTPSRedirectMiddleware- readiness 전환
- 배포 프로필별 Uvicorn 플래그 감각
왜 중요한가:
- 로컬에서는 멀쩡한데 proxy 뒤 배포에서 어긋나는 문제를 어디서 봐야 하는지 감을 준다.
- readiness를 내려서 drain하는 종료 흐름과 host/scheme 보호 장치를 같이 볼 수 있다.
실행:
./.venv/bin/python examples/uvicorn_proxy_and_health_lab.py체크 포인트:
- HTTP 요청은 HTTPS redirect를 받는다.
root_path가 scope에 들어간다.- drain 뒤 readiness가
503으로 내려간다. - 허용되지 않은 host는 거부된다.
무엇을 보여주나:
- connect 시 token 인증
RoomManager의 join/leave/broadcast- room 내부 fan-out
- disconnect cleanup
- invalid token close code
왜 중요한가:
- echo server 수준을 넘어 실제 서비스에서 가장 먼저 필요한 websocket 기본형을 보여준다.
- route loop에 auth/room 상태/cleanup을 다 몰아넣지 않고 역할을 분리하는 감각을 준다.
실행:
./.venv/bin/python examples/websocket_auth_and_rooms_lab.py체크 포인트:
- 첫 연결은
system:...:joined메시지를 받는다. - 두 번째 연결이 들어오면 room fan-out이 양쪽에 전달된다.
- disconnect 뒤 room state가 정리된다.
- 잘못된 token은 policy violation close code로 끊긴다.
무엇을 보여주나:
- local-only room broadcast의 한계
- broker-backed multi-worker fan-out
PubSubEnvelopeRedisPubSubBrokeradapter shape
왜 중요한가:
- single-worker에서는 보이지 않던 websocket room fan-out 문제가 multi-worker에서 왜 터지는지 직관적으로 보여준다.
- Redis를 "socket 저장소"가 아니라 "worker 간 fan-out 버스"로 이해하게 해준다.
실행:
./.venv/bin/python examples/websocket_redis_pubsub_lab.py체크 포인트:
- local-only에서는 다른 worker inbox가 비어 있다.
- broker-backed에서는 두 worker inbox 모두 메시지를 본다.
- 코드 안에 실제
redis.asyncioadapter shape가 들어 있다.
무엇을 보여주나:
server.helloclient.joinroom.joinedchat.message+event_idresume_from기반 replay
왜 중요한가:
- reconnect 문제를 단순 소켓 재연결이 아니라 protocol 계약 문제로 보게 해준다.
- event id와 replay가 없으면 왜 중복/누락 처리에 약해지는지 감이 생긴다.
실행:
./.venv/bin/python examples/websocket_client_protocol_reconnect_lab.py체크 포인트:
- 첫 연결은
server.hello를 받는다. - 재연결 후
resume_from기준으로 놓친 이벤트를 replay받는다. - backoff 샘플 값이 같이 출력된다.
무엇을 보여주나:
- route는 HTTP 계약만 소유
- service가 transaction 경계를 소유
- repository가 query와 persistence 세부 구현 담당
- response DTO로 API 계약 마무리
왜 중요한가:
- "작동은 하는데 금방 지저분해지는" FastAPI 구조를 피하는 기본 패턴을 실행 가능한 형태로 볼 수 있다.
commit과flush가 어디 있어야 하는지 감이 생긴다.
실행:
./.venv/bin/python examples/fastapi_service_template_example.py체크 포인트:
- 첫 요청은
201로 생성된다. - 같은 이메일로 다시 요청하면
409가 반환된다. - 조회는
GET /users/1로 별도 route를 통해 이뤄진다.
무엇을 보여주나:
- class-based
SqlAlchemyUnitOfWork - repository 묶음과 session 소유권
- service가 commit 시점만 결정하는 패턴
왜 중요한가:
- repository가 많아질수록 "한 작업 단위"를 명시적 객체로 두는 편이 읽기 좋아질 때가 있다.
- session을 직접 흘리는 방식과 UoW 객체를 주입하는 방식의 차이를 체감할 수 있다.
실행:
./.venv/bin/python examples/sqlalchemy_class_based_uow.py체크 포인트:
- 중복 이메일은
DuplicateEmail로 막힌다. flush()는 commit 전에 PK를 확보한다.- UoW가 session close를 소유한다.
무엇을 보여주나:
abc.ABC기반 port- use case가 concrete SQLAlchemy 대신 UoW port에 의존하는 구조
- commit 뒤 외부 부수효과를 실행하는 패턴
왜 중요한가:
- SOLID의 DIP를 Python 서비스 코드에 어떻게 "과하지 않게" 적용할지 보여준다.
- 모든 계층을 interface로 만드는 나쁜 패턴과, 진짜 경계만 추상화하는 좋은 패턴 차이를 이해하기 좋다.
- 팀이
Protocol보다 명시적 abstract base class를 선호할 때 어떤 모양이 읽기 좋은지 바로 볼 수 있다.
실행:
./.venv/bin/python examples/usecase_with_uow_abc.py체크 포인트:
- 첫 등록 뒤 welcome notifier가 실행된다.
- 중복 이메일은
DuplicateEmail로 막힌다. - use case는 notifier와 UoW ABC만 알고, SQLAlchemy 세부 구현은 바깥에 남는다.
무엇을 보여주나:
- Lambda direct DB
- Lambda + RDS Proxy
- Kubernetes sync API
- Kubernetes async API
- batch/worker
왜 중요한가:
- SQLAlchemy 설정은 배포 환경의 process model에 따라 달라져야 한다.
pool_size,max_overflow가 DB connection budget에 어떤 영향을 주는지 감을 잡기 좋다.
실행:
./.venv/bin/python examples/sqlalchemy_deployment_profiles.py체크 포인트:
- 환경별로
QueuePool과NullPool선택이 어떻게 달라지는지 본다. - session 기본값으로
autoflush=False,expire_on_commit=False를 왜 자주 쓰는지 확인한다. - Kubernetes 예시에서 총 연결 수 계산을 직접 본다.
무엇을 보여주나:
- additive schema expand
- dual write
- backfill
- contract를 마지막으로 미루는 이유
왜 중요한가:
- migration은 모델 diff보다 rollout compatibility가 더 중요하다.
- old app / new schema / new app / old schema 조합을 어떻게 안전하게 통과할지 감을 준다.
실행:
./.venv/bin/python examples/alembic_zero_downtime_lab.py체크 포인트:
- 새 column은 먼저 nullable로 추가된다.
- 새 앱은 dual write를 한다.
- backfill 뒤 new app은
display_name기준으로 읽을 수 있다. - old column drop은 마지막에 해야 한다.
무엇을 보여주나:
- checkpoint table
- chunked backfill
- worker interruption 뒤 resume
- operational backfill을 Alembic DDL과 분리하는 감각
왜 중요한가:
- 실서비스의 큰 backfill은 migration revision보다 별도 job으로 굴리는 경우가 많다.
- rolling/blue-green/canary 모두 shared DB를 쓰면 resumable backfill discipline이 중요해진다.
실행:
./.venv/bin/python examples/progressive_delivery_backfill_lab.py체크 포인트:
- 첫 batch 뒤 checkpoint가 저장된다.
- worker가 중단돼도 다음 실행이 이어서 진행된다.
- batch별 commit으로 긴 transaction을 피한다.
- schema expand와 data backfill이 다른 단계라는 점이 드러난다.
무엇을 보여주나:
- class-based UoW
- idempotency key + payload fingerprint
- outbox message 저장
- conflicting retry 거부
왜 중요한가:
- retry-safe create API와 reliable publish는 실서비스에서 거의 항상 같이 등장한다.
BackgroundTasks와 transactional outbox의 차이를 구조적으로 이해하게 해준다.
실행:
./.venv/bin/python examples/idempotency_outbox_lab.py체크 포인트:
- 같은 key + 같은 payload는 기존 응답을 재사용한다.
- 같은 key + 다른 payload는 에러로 거부된다.
- order 저장과 outbox 저장이 같은 UoW에 들어간다.
무엇을 보여주나:
pydantic-settingsenv_prefixenv_nested_delimiter.env와 실제 환경 변수 우선순위- secret dir와
@lru_cache
왜 중요한가:
- 서비스 설정은 코드 곳곳의
os.getenv()가 아니라 typed boundary로 다뤄야 한다. - local, test, Kubernetes, Lambda에서 source priority를 어떻게 이해해야 하는지 감을 잡기 좋다.
실행:
./.venv/bin/python examples/pydantic_settings_patterns.py체크 포인트:
- 같은 인자로
get_settings()를 두 번 부르면 cache hit가 난다. - 실제 환경 변수가
.env보다 우선한다. - secret 값은 secret dir fallback으로도 공급될 수 있다.
무엇을 보여주나:
- 기본 lazy loading
selectinload()joinedload()- 각 전략별 query count 차이
왜 중요한가:
- SQLAlchemy 성능 문제는 ORM 문법보다 loading strategy에서 더 자주 발생한다.
- 목록 API와 상세 API가 왜 다른 로딩 전략을 가져야 하는지 직관적으로 보인다.
실행:
./.venv/bin/python examples/sqlalchemy_loading_strategies.py체크 포인트:
- lazy loading은 부모 조회 후 관계 접근 때 추가 쿼리가 발생한다.
selectinload()는 대체로 2번 쿼리로 안정적인 목록 로딩을 보여준다.joinedload()는 한 번의 쿼리지만 collection에서는unique()처리가 필요하다.
무엇을 보여주나:
ast.parse()와 AST dumpdis.dis()바이트코드 관찰- cycle 객체 +
gc.collect() tracemalloc상위 할당 라인 추적sys.monitoring이벤트 샘플
왜 중요한가:
- CPython 내부 동작을 개념이 아니라 관찰 가능한 실험으로 이해할 수 있다.
- runtime 파트 학습 후 "어디서 비용이 생기는지"를 직접 확인하기 좋다.
실행:
./.venv/bin/python examples/cpython_runtime_labs.py체크 포인트:
- 함수 실행이 bytecode 형태로 보인다.
- cycle GC가 refcount와 다른 역할을 한다.
- 할당 hotspot을 파일/라인 기준으로 볼 수 있다.
무엇을 보여주나:
- engine fixture setup/teardown
- seed fixture
- FastAPI
dependency_overridescleanup TestClientcontext manager lifecycle
실행:
uv run pytest tests/test_fastapi_fixtures_and_teardown.py체크 포인트:
- seed 데이터가 fixture에서 준비된다.
/meta는 override된 dependency 값"test"를 본다.- teardown은 fixture 쪽에서 소유하고 test body는 소비만 한다.
무엇을 보여주나:
abc.ABC기반 경계FakeUnitOfWorkRecordingNotifier- pytest fixture graph
실행:
uv run pytest tests/test_abc_fake_uow_pytest.py체크 포인트:
- 성공 경로는 commit과 notifier 호출을 남긴다.
- 실패 경로는 rollback 상태만 남기고 notifier 호출을 생략한다.
- DB 없이도 use case branching을 빠르게 검증할 수 있다.
무엇을 보여주나:
monkeypatch.setenv()tmp_path_env_file_secrets_dir
실행:
uv run pytest tests/test_pydantic_settings_patterns.py체크 포인트:
- 실제 환경 변수가
.env보다 우선한다. - secret dir가 env 부재 시 fallback source가 된다.
무엇을 보여주나:
- property-based idempotency invariant
- same-key conflict 검증
httpx.ASGITransportcontract test
실행:
uv run pytest tests/test_idempotency_and_contracts.py체크 포인트:
- 같은 key + 같은 payload는 operation을 한 번만 실행한다.
- 같은 key + 다른 payload는 conflict가 난다.
- ASGI transport가
/healthcontract를 직접 검증한다.
- FastAPI 예제와 같이 읽기:
/fastapi/project-structure,/fastapi/dependency-injection,/playbooks/api-service-template - ASGI/Uvicorn 예제와 같이 읽기:
/intro/web-gateway-evolution,/fastapi/asgi-and-uvicorn,/fastapi/background-tasks-and-offloading - Realtime/운영 예제와 같이 읽기:
/fastapi/websockets-streaming-and-middleware,/fastapi/proxy-health-and-shutdown - Security 예제와 같이 읽기:
/fastapi/security-and-auth - WebSocket 실전 패턴과 같이 읽기:
/fastapi/websocket-practical-patterns - Multi-worker/reconnect 예제와 같이 읽기:
/fastapi/websocket-redis-pubsub,/fastapi/websocket-client-protocol-and-reconnect - SQLAlchemy 예제와 같이 읽기:
/sqlalchemy/session-and-unit-of-work,/sqlalchemy/relationships-and-loading - Alembic 예제와 같이 읽기:
/sqlalchemy/alembic-and-zero-downtime - Progressive delivery 예제와 같이 읽기:
/playbooks/progressive-delivery-and-alembic - Pydantic 예제와 같이 읽기:
/pydantic/core-schema,/pydantic/validation-pipeline - Asyncio 예제와 같이 읽기:
/asyncio/cancellation-and-taskgroup,/asyncio/queues-and-backpressure - Dataclass 예제와 같이 읽기:
/pythonic/dataclasses - 메타프로그래밍 예제와 같이 읽기:
/pythonic/metaprogramming-advanced - Import/packaging 예제와 같이 읽기:
/intro/import-packaging-and-environments - CPython 실험 예제와 같이 읽기:
/runtime/cpython-internals-advanced - Testing 예제와 같이 읽기:
/fastapi/lifespan-and-testing,/playbooks/testing-with-pytest-fixtures,/playbooks/testing-beyond-fixtures,/playbooks/idempotency-and-outbox