Pydantic 내부 — 타입 힌트가 런타임 검증이 되는 과정
__annotations__ → Rust 코어(pydantic-core) → 검증 실행
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
email: str | None = None
이 클래스 정의 시점에 이미 검증 로직이 만들어진다.
v2의 핵심 — pydantic-core
Pydantic v2의 검증 로직은 Python이 아니라 Rust(pydantic-core)로 작성되어 있다. v1 대비 5~50배 빠르다.
흐름:
1. class User(BaseModel): → ModelMetaclass.__new__() 호출
2. 클래스의 __annotations__를 읽어 각 필드의 타입을 파악
3. 타입별로 core_schema를 생성 (str → str_schema(), int → int_schema() 등)
4. SchemaValidator(Rust 객체)를 생성해서 클래스에 저장
5. User(name='Kim', age=25) → __init__ → SchemaValidator.validate_python(data) 호출
6. Rust에서 타입 검사/변환 실행 → 실패하면 ValidationError
자동 변환(coercion)
User(name='Kim', age='25') # age가 str이지만 int로 자동 변환된다
User(name='Kim', age='abc') # ValidationError — int로 변환 불가
Pydantic은 기본적으로 "맞출 수 있으면 맞춰준다" (strict mode를 켜면 끔).
FastAPI에서의 역할
FastAPI는 엔드포인트 함수의 인자 타입이 Pydantic 모델이면, 요청 body를 자동으로 이 모델로 파싱/검증한다. 타입 힌트 한 줄이 입력 검증 + 문서화 + 직렬화를 전부 해결하는 구조.
핵심 포인트
class User(BaseModel): 정의 시 ModelMetaclass가 __annotations__를 읽는다
각 필드 타입에 맞는 core_schema를 생성 (Rust 레벨)
User(...) 호출 시 SchemaValidator.validate_python()으로 Rust에서 검증
검증 실패 시 ValidationError — 어떤 필드가 왜 틀렸는지 상세 정보