Python으로 개발을 하다 보면 가장 많이 고민하게 되는 지점이 있습니다.
"이 데이터를 어떻게 정의해서 넘겨주지? 그냥 딕셔너리? 아니면 클래스?"
과거에는 그냥
dict나 일반 class를 썼지만, 이제는 선택지가 너무 많아졌습니다. Pydantic, Dataclasses, TypedDict... 다 비슷해 보이는데 용도는 완전히 다릅니다.오늘은 이들의 차이점을 명확히 정리하고, 특히 "외부 API 연동 시 무엇이 최선인지" 결론을 내려 드립니다.
1. 선수 입장: 주요 후보 3인방
① Pydantic (BaseModel)
- 한마디로: "깐깐한 관리자"
- 특징: 데이터가 들어올 때 타입을 **강제(Validation)**하고, 필요하면 **변환(Parsing)**해 줍니다.
- 주요 용도: FastAPI, 외부 API 응답 처리, 환경 설정 관리.
② Dataclasses (@dataclass)
- 한마디로: "효율적인 배달부"
- 특징: Python 3.7 표준 라이브러리.
__init__같은 반복 코드를 줄여주지만, 런타임에 타입을 검사하진 않습니다.
- 주요 용도: 애플리케이션 내부 로직 간의 데이터 이동(DTO).
③ TypedDict
- 한마디로: "가면 쓴 딕셔너리"
- 특징: 실행 시점에는 그냥
dict와 똑같습니다(메모리 효율 최강). IDE에서 자동완성을 지원받기 위해 사용합니다. Python 3.8부터 도입되었습니다.
- 주요 용도: 레거시 코드, JSON 변환 비용조차 아껴야 하는 고성능 환경.
2. 한눈에 보는 비교 (Feat. 성능 vs 안전)
특성 | Pydantic | Dataclasses | TypedDict |
핵심 가치 | 데이터 검증 & 파싱 | 보일러플레이트 제거 | 타입 힌트 (Zero Cost) |
런타임 검사 | ✅ 있음 (강력함) | ❌ 없음 | ❌ 없음 |
타입 자동변환 | ✅ "123" → 123 | ❌ "123" 유지 | ❌ 없음 |
속도 | 보통 (검증 로직 수행) | 🚀 빠름 | ⚡️ 매우 빠름 (dict와 동일) |
JSON 직렬화 | 내장 ( .model_dump_json) | 별도 처리 필요 | json.dumps 사용 |
Sheets로 내보내기
3. 실전 가이드: 외부 API 연동할 땐 무조건 Pydantic!
"외부 API에서 들어오는 데이터"는 우리가 제어할 수 없습니다. 언제든 타입이 바뀌거나
null이 들어올 수 있죠. 이때 TypedDict나 Dataclasses를 쓰면, 데이터가 들어올 땐 조용하다가 나중에 엉뚱한 곳에서 에러가 터집니다.Pydantic은 입구에서 데이터를 검문검색하여 "방어벽" 역할을 해줍니다.
Python
from pydantic import BaseModel, Field, HttpUrl
from typing import Optional
class UserResponse(BaseModel):
# 1. 자동 형 변환: API가 id를 "123"(str)으로 줘도 int로 받아줍니다.
id: int
# 2. 이름 매핑: API의 'userName'을 파이썬 스타일 'user_name'으로 자동 매핑
user_name: str = Field(alias="userName")
# 3. 데이터 검증: 이메일 형식이 아니거나 URL이 깨져있으면 에러 발생
email: str
website: Optional[HttpUrl] = None
# API 데이터 (JSON)
api_data = {
"id": "50",
"userName": "Pythonista",
"email": "[email protected]",
"website": "https://python.org"
}
# 검증 및 파싱
user = UserResponse(**api_data)
print(user.id) # 50 (정수로 변환됨)
print(user.user_name) # "Pythonista" (접근하기 편함)🍯 꿀팁: 코드를 직접 치지 마세요
API 응답 JSON이 너무 길다면
datamodel-code-generator를 사용하세요. JSON을 넣으면 Pydantic 클래스를 1초 만에 만들어줍니다.4. TypedDict 버전 이슈 (깨알 상식)
TypedDict는 Python 3.8에 처음 들어왔지만, 사실 Python 3.11에서 완성되었습니다. 3.10 버전까지는 특정 키만 Optional로 만드는 것이 매우 까다로웠지만, 3.11부터 Required와 NotRequired가 추가되면서 비로소 쓸만해졌습니다.Python
# Python 3.11+
from typing import TypedDict, NotRequired
class User(TypedDict):
name: str # 필수
age: NotRequired[int] # 선택 (이게 3.11에 생김!)5. 결론: 그래서 뭘 쓸까?
고민할 시간을 줄여드립니다. 딱 3가지 기준만 기억하세요.
- 외부 데이터(API, DB, 파일)를 다룬다? 👉 무조건 Pydantic
- 내부 로직에서 객체를 깔끔하게 쓰고 싶다? 👉 Dataclasses
- 기존 딕셔너리 코드를 안 고치고 타입만 입히고 싶다? 👉 TypedDict
상황에 맞는 도구를 선택해서 더 안전하고 깔끔한 Python 코드를 작성해 보세요!