# Pydantic Pydantic은 Python에서 데이터 모델링과 데이터 검증을 간편하게 수행하기 위한 라이브러리다. 타입 힌트를 기반으로 입력 데이터를 파싱하고 검증하며, 잘못된 데이터에 대해 명확한 에러를 제공한다. 또한 모델 인스턴스의 직렬화/역직렬화 기능을 제공하여 API 입력/output 처리에 널리 사용된다. Pydantic은 특히 FastAPI와의 강력한 연동으로 잘 알려져 있으며, 데이터 유효성 검사와 설정 관리 측면에서 일관된 개발 경험을 제공한다. --- ## 역사와 발전 - 초기 버전은 2010년대 중반에 개발되어 Python 데이터 검증에 대한 요구를 충족했다. - Pydantic v1은 간단한 모델 정의와 벨리데이션 데코레이터를 중심으로 널리 사용되었다. - Pydantic v2는 설계 개선과 성능 향상을 목표로 도입되었고, field_validator/model_validator와 같은 새로운 벨리데이션 시스템, 모델 구성 설정의 변화 등으로 발전했다. - 현재 버전은 안정적인 API와 성능 최적화를 바탕으로 다양한 파이프라인(웹 API, 데이터 파이프라인, 설정 관리)에 적용되고 있다. --- ## 핵심 개념 - 데이터 모델링: BaseModel을 상속한 모델 클래스로 입력 데이터의 구조를 정의한다. - 타입 기반 유효성 검사: Python의 타입 힌트를 활용해 입력 데이터를 파싱하고 검증한다. - 직렬화/역직렬화: 모델 인스턴스를 dict/json으로 변환하고, 외부 데이터로부터 모델을 생성한다. - 커스텀 벨리데이터: 내장 벨리데이터 외에도 사용자가 직접 검증 로직을 정의할 수 있다. - 설정 관리: 모델의 동작 방식(예: 필드 alias, 허용하는 추가 값 등)을 제어하는 설정 옵션을 제공한다. --- ## 모델 정의의 기본 구성 - BaseModel: 데이터 모델의 기본 클래스이다. - Field: 필드의 기본값, 제약조건, 메타데이터를 정의한다. - 타입: int, float, str, bool, List, Optional, Union, Literal 등 Python의 typing 타입을 활용한다. - 예시: ```python from typing import List, Optional from datetime import datetime from pydantic import BaseModel, Field, EmailStr class User(BaseModel): id: int name: str = Field(..., min_length=2, max_length=50) email: EmailStr signup_ts: Optional[datetime] = None friends: List[int] = [] ``` - v1 스타일의 직렬화/역직렬화 - dict() 메서드를 사용한다. - 예: user.dict() - v2 스타일의 직렬화/역직렬화 - model_dump()와 model_dump_json()을 사용한다. - 예: user.model_dump(), user.model_dump_json() --- ## 데이터 검증 흐름 - 입력 데이터로 모델 인스턴스 생성 시, 각 필드의 타입 검사와 제약조건이 적용된다. - 필요 시 validators를 추가하여 커스텀 검증을 수행한다. - 검증 실패 시 ValidationError 예외가 발생하며, 에러 메시지가 계층적으로 구성된다. 벨리데이션 예시(전통적 방법, v1 스타일): ```python from pydantic import BaseModel, validator class User(BaseModel): username: str password: str @validator('password') def password_min_length(cls, v): if len(v) < 8: raise ValueError('Password must be at least 8 characters') return v ``` 필드 기반 벨리데이션(필드 레벨, v2 포함 가능): ```python # v2에서 field_validator를 사용하는 예시(개념적 예) from pydantic import BaseModel, field_validator class User(BaseModel): username: str password: str @field_validator('password') def validate_password(cls, v): if len(v) < 8: raise ValueError('Password must be at least 8 characters') return v ``` - ValidationError의 에러 포맷은 e.json()를 통해 JSON 형태로 확인 가능하다. --- ## [[직렬화 및 역직렬화]] - 입력 데이터로부터 모델 생성: parse_obj, parse_raw 등 다양한 입력 포맷을 지원한다. - v1 스타일: dict(), json() - v2 스타일: model_dump(), model_dump_json(), model_dump(include={}, exclude={}) 예시: ```python # 역직렬화(입력으로부터 모델 생성) data = {"id": 1, "name": "Alice", "email": "[email protected]"} user = User(**data) # v1 스타일으로도 가능 # 직렬화 payload = user.dict() # v1 payload_v2 = user.model_dump() # v2 ``` 또한 JSON 직렬화는 model_dump_json()으로 간단히 수행할 수 있다. --- ## 설정과 고급 사용 - 설정/config: 모델의 동작을 제어하는 옵션들을 제공한다. - 필드 별 alias, 기본값, 기본 값 팩토리, 추가 속성 허용 여부 등 - v2 경우 설정은 model_config를 통해 표기하는 방식이 널리 사용된다(버전에 따라 다를 수 있음). 예시(개념): ```python class User(BaseModel): id: int name: str class Config: allow_population_by_field_name = True anystr_strip_whitespace = True ``` 또는 v2 스타일의 설정 구현도 가능하다(문서의 버전에 따라 차이가 있다). --- ## 성능 및 아키텍처 - Pydantic은 내부적으로 pydantic-core라는 Rust 기반 파서를 사용해 성능을 끌어올린다(버전에 따라 구성 요소가 다를 수 있다). - 타입 힌트를 적극 활용하여 런타임 검사와 변환을 효율적으로 수행한다. - 대규모 API 입력 검증이나 데이터 파이프라인에서 높은 안정성과 예측 가능한 에러 형식을 제공한다. --- ## 사용 사례 - 웹 API 입력 검증: FastAPI가 Pydantic을 기본 데이터 모델로 채택하여 요청/응답의 스키마를 명확히 정의한다. - 데이터 파이프라인: 외부 데이터 소스에서 들어오는 JSON/딕셔너리 데이터를 모델로 검증하고 변환한다. - 설정 관리: 어플리케이션 설정 값을 모델로 관리하고, 환경 변수에서 로드해 기본값과 유효성 검사를 수행한다. --- ## 비교 및 대안 - Pydantic vs Dataclasses: Pydantic은 런타임 유효성 검사와 자동 파싱을 제공하는 반면, 표준 dataclasses는 유효성 검사를 기본으로 제공하지 않는다. 필요 시 추가 라이브러리로 보완할 수 있다. - Pydantic vs Marshmallow: Marshmallow는 데이터 직렬화/검증 기능을 오래전부터 제공해 왔으나, Pydantic은 타입 힌트 기반의 설계와 간결한 모델 정의로 인해 최근에 더 널리 채택되는 경향이 있다. - Pydantic v1 vs v2: v2는 벨리데이션 시스템의 개선, 더 명확한 API, 성능 최적화 등을 목표로 하며, 기존 v1의 코드베이스를 점진적으로 마이그레이션하는 방식으로 사용되는 경우가 많다. --- ## 일반적인 모범 사례 - 명확한 타입 힌트를 사용하고, 불필요한 타입 변환을 피한다. - 필드 수준의 제약조건은 Field(...) 혹은 typing 기반 제약으로 명확히 정의한다. - 입력 데이터에 대한 예외를 포괄적으로 처리하고, ValidationError의 에러 포맷을 로깅/전달에 활용한다. - FastAPI 등 프레임워크와의 결합에서 Pydantic의 스키마를 API의 계약으로 활용한다. --- ## 추가 예시: API 응답 모델 ```python from pydantic import BaseModel from typing import List class Item(BaseModel): id: int name: str class Response(BaseModel): ok: bool data: List[Item] total: int ``` 위와 같은 구성은 API 응답의 일관된 스키마를 정의하는 데 유용하다. --- ## 참고 및 학습 자료 - Pydantic 공식 문서 - FastAPI 공식 문서의 데이터 모델러로의 Pydantic 사용 가이드 - Pydantic-v1 vs v2 마이그레이션 가이드 - JSON Schema와 Pydantic의 상호작용에 대한 문서 --- 관련 문서: [[Pydantic-고급사용법]], [[FastAPI와_Pydantic_통합]], [[Pydantic-Core_이해하기]], [[JSON_Schema와_Pydantic의_상호작용]], [[Pydantic-v1_vs_v2_비교]]