파이썬
데이터 클래스 비교: dataclass vs Pydantic BaseModel
코샵
2024. 12. 8. 10:35
반응형
소개
Python에서 데이터를 구조화할 때 주로 사용되는 두 가지 방식인 dataclass
와 Pydantic의 BaseModel
에 대해 알아보겠습니다. 각각의 특징과 사용법, 그리고 언제 어떤 것을 사용해야 하는지 살펴보겠습니다.
Dataclass
기본 사용법
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class User:
name: str
age: int
email: Optional[str] = None
friends: List[str] = None
# 사용 예시
user = User(name="John", age=30)
print(user.name) # "John"
고급 기능 활용
from dataclasses import dataclass, field
@dataclass(frozen=True) # 불변 객체 생성
class Configuration:
host: str
port: int = 8000
tags: List[str] = field(default_factory=list) # 가변 기본값
def get_address(self) -> str:
return f"{self.host}:{self.port}"
장점 | 단점 |
---|---|
표준 라이브러리 포함 | 데이터 검증 기능 없음 |
가벼움과 빠른 성능 | 복잡한 타입 변환 어려움 |
간단한 구현 | JSON 직렬화 제한적 |
메모리 효율적 | 동적 필드 처리 어려움 |
Pydantic : BaseModel
기본 사용법
from pydantic import BaseModel, EmailStr
from typing import List, Optional
class User(BaseModel):
name: str
age: int
email: Optional[EmailStr] = None
friends: List[str] = []
# 사용 예시
user = User(name="John", age=30, email="john@example.com")
print(user.model_dump()) # JSON 형태로 변환
고급 기능 활용
from pydantic import BaseModel, Field, validator
from datetime import datetime
class Article(BaseModel):
title: str = Field(..., min_length=3)
content: str
created_at: datetime = Field(default_factory=datetime.now)
tags: List[str] = []
@validator('title')
def title_must_be_title_case(cls, v):
if not v[0].isupper():
raise ValueError('Title must start with capital letter')
return v
장점 | 단점 |
---|---|
강력한 데이터 검증 | 추가 의존성 필요 |
JSON 자동 직렬화/역직렬화 | 상대적으로 느린 성능 |
자동 문서화 지원 | 더 많은 메모리 사용 |
복잡한 타입 변환 지원 | 학습 곡선 존재 |
활용 예시
dataclass
from dataclasses import dataclass
from typing import Dict
@dataclass
class CacheConfig:
max_size: int
ttl_seconds: int
strategy: str = "LRU"
def validate(self) -> bool:
return (
self.max_size > 0 and
self.ttl_seconds > 0 and
self.strategy in ["LRU", "FIFO"]
)
# 설정 관리에 적합
config = CacheConfig(max_size=1000, ttl_seconds=3600)
baseModel
from pydantic import BaseModel, HttpUrl, constr
from datetime import datetime
class BlogPost(BaseModel):
id: int
title: constr(min_length=5, max_length=100)
content: str
author_email: EmailStr
published: bool = False
tags: List[str] = []
image_url: Optional[HttpUrl] = None
created_at: datetime
class Config:
json_encoders = {
datetime: lambda v: v.isoformat()
}
# API 요청/응답 처리에 적합
post = BlogPost(
id=1,
title="My First Post",
content="Hello World",
author_email="author@example.com",
created_at=datetime.now()
)
선택 가이드
dataclass 사용이 좋은 경우
- 단순한 데이터 구조화가 필요할 때
- 성능이 중요한 경우
- 추가 의존성을 피하고 싶을 때
- 내부 데이터 구조에서 사용할 때
@dataclass
class Point:
x: float
y: float
def distance_from_origin(self) -> float:
return (self.x ** 2 + self.y ** 2) ** 0.5
BaseModel 사용이 좋은 경우
- API 요청/응답 처리
- 데이터 검증이 필요한 경우
- JSON 처리가 많은 경우
- FastAPI와 함께 사용할 때
class UserRegistration(BaseModel):
username: str = Field(..., min_length=3, max_length=20)
password: str = Field(..., min_length=8)
email: EmailStr
age: int = Field(..., ge=0, lt=150)
@validator('password')
def password_must_contain_special_char(cls, v):
if not any(c in '!@#$%^&*()' for c in v):
raise ValueError('Password must contain special character')
return v
두 기능의 조합 사용
from dataclasses import dataclass
from pydantic import BaseModel, validator
# 내부 로직용 데이터 클래스
@dataclass
class UserInternal:
id: int
name: str
score: float = 0.0
def calculate_ranking(self) -> int:
# 내부 비즈니스 로직
pass
# API 응답용 Pydantic 모델
class UserResponse(BaseModel):
id: int
name: str
score: float
ranking: int
@classmethod
def from_internal(cls, user: UserInternal):
return cls(
id=user.id,
name=user.name,
score=user.score,
ranking=user.calculate_ranking()
)
결론
- dataclass는 단순하고 가벼운 데이터 구조화에 적합
- Pydantic BaseModel은 데이터 검증과 API 통신에 적합
- 프로젝트의 요구사항에 따라 적절히 선택하거나 조합하여 사용