Python 학습 가이드
문법, 프레임워크, 패키지 — 코드 레벨로 동작 원리 정리
문법 & 기초
Generator와 yield — 메모리를 안 먹는 이터레이션의 원리
yield가 함수 실행을 "일시 정지"시키는 메커니즘
Generator는 값을 한꺼번에 만들지 않고 yield로 하나씩 내보낸다. 10GB 파일을 한 줄씩 처리할 수 있는 이유가 이것이다. 내부적으로 함수의 스택 프레임을 보존하면서 실행을 중단/재개한다.
Decorator 내부 구조 — @가 실제로 하는 일
함수를 받아서 함수를 반환하는 함수 — 그게 전부다
@decorator는 문법적 설탕(syntactic sugar)이다. func = decorator(func)와 동일하다. 클로저와 *args/**kwargs 조합으로 원본 함수를 감싸는 패턴.
Context Manager — with문이 실제로 하는 일
__enter__과 __exit__로 리소스 정리를 보장하는 프로토콜
with open("f") as f: 의 with는 __enter__()를 호출해서 리소스를 얻고, 블록이 끝나면(에러가 나든 안 나든) __exit__()로 정리한다. contextlib.contextmanager로 generator 기반 구현도 가능.
Type Hints — 런타임에서는 아무것도 안 한다
Python의 타입 힌트가 "힌트"인 이유와, Pydantic이 이걸 극복하는 방법
Python의 type hint(: int, -> str)는 런타임에 검사되지 않는다. mypy 같은 정적 분석 도구가 읽을 뿐이다. Pydantic은 이 한계를 __init_subclass__와 모델 검증으로 넘어서서 런타임 타입 검사를 구현한다.
Keyword-only 인자 — `*,` 가 뭔지, 왜 쓰는지
`def f(a, b, *, c)` 의 그 별 하나
Python의 `*,`는 "여기부터는 키워드로만 받는다"는 구분선이다. 위치 인자로 넘기면 TypeError. 호출 의도를 명확하게 하고 시그니처 변경에 강하게 만든다. Ruby에는 `:` 키워드 인자 자체가 처음부터 keyword-only라 별도 문법이 필요 없다.
FastAPI
FastAPI 아키텍처 — Starlette + Pydantic + Uvicorn의 조합
FastAPI가 "빠르다"고 말하는 이유의 실체
FastAPI 자체는 "프레임워크 위의 프레임워크"다. HTTP는 Starlette가, 데이터 검증은 Pydantic이, ASGI 서버는 Uvicorn이 담당한다. FastAPI는 이것들을 타입 힌트 기반 인터페이스로 묶은 것.
FastAPI Depends() — 함수 시그니처로 DI하는 방법
DB 세션, 인증, 페이지네이션을 함수 인자로 주입하는 패턴
FastAPI의 Depends()는 함수를 인자의 기본값으로 넣으면 자동으로 호출/주입해주는 DI 시스템이다. 중첩 가능하고, generator를 쓰면 cleanup도 보장된다.
FastAPI의 async/await — def와 async def의 차이
async def를 쓰면 빨라지나? 그건 경우에 따라 다르다
FastAPI에서 def는 스레드풀에서, async def는 이벤트 루프에서 실행된다. I/O 대기가 많으면 async가 유리하고, CPU 바운드면 def가 낫다. 둘 다 지원하는 게 FastAPI의 강점.
Django
Django ORM 내부 — QuerySet이 lazy한 이유
filter().exclude().order_by()를 체이닝해도 SQL이 안 나가는 원리
Django의 QuerySet은 평가(evaluate)되기 전까지 SQL을 실행하지 않는다. filter/exclude/order_by는 내부적으로 SQL 조건을 쌓기만 하고, list()/for/[0] 등으로 접근할 때 비로소 DB에 쿼리한다.
Django Middleware — 요청/응답을 감싸는 양파 구조
MIDDLEWARE 설정 순서가 왜 중요한지, 내부에서 어떻게 체이닝되는지
Django의 미들웨어는 양파 껍질처럼 겹겹이 감싸는 구조다. 요청은 바깥에서 안으로, 응답은 안에서 밖으로 통과한다. MIDDLEWARE 리스트의 순서가 실행 순서를 결정한다.
Django Signals — 이벤트 기반 느슨한 결합
post_save, pre_delete가 내부적으로 어떻게 동작하는가
Django Signal은 Observer 패턴의 구현이다. 모델이 저장/삭제될 때 등록된 receiver 함수를 자동으로 호출한다. 편리하지만 남용하면 디버깅이 어려워진다.
자주 쓰는 패키지
requests 내부 구조 — requests.get()이 실제로 하는 일
Session, PreparedRequest, HTTPAdapter, urllib3까지의 호출 체인
requests.get(url)은 내부적으로 Session 생성 → PreparedRequest 조립 → HTTPAdapter 선택 → urllib3.PoolManager로 실제 TCP 연결을 거친다. 이 계층 구조를 알면 커넥션 풀, 타임아웃, 재시도를 제대로 설정할 수 있다.
Pydantic 내부 — 타입 힌트가 런타임 검증이 되는 과정
__annotations__ → Rust 코어(pydantic-core) → 검증 실행
Pydantic v2는 모델 클래스를 정의할 때 __annotations__를 읽어서 Rust로 작성된 pydantic-core의 검증 스키마를 생성한다. __init__에서 값을 넣을 때 이 스키마로 검증이 실행된다.
Click — Python CLI 도구를 만드는 가장 깔끔한 방법
decorator 기반 CLI 프레임워크의 내부 동작
Click은 decorator로 CLI 인자/옵션을 정의하는 프레임워크다. argparse보다 직관적이고, Flask 개발자(Armin Ronacher)가 만들었다. @click.command + @click.option으로 CLI가 완성된다.