[Fluent Python] 일반 클래스, Named Tuple, dataclass, BaseModel(Pydentic) (260617)

WonTerry·2026년 6월 17일

Python

목록 보기
15/20

파이썬을 어느 정도 학습한 이후에는 "데이터를 어떻게 표현할 것인가?"가 매우 중요한 주제가 됩니다.

실무에서는 다음과 같이 사용하는 경우가 많습니다.

  • 일반 클래스(Class) → 비즈니스 로직이 많은 객체
  • NamedTuple → 변경되지 않는(Immutable) 간단한 데이터
  • dataclass → 대부분의 데이터 객체(DTO, Entity)
  • Pydantic BaseModel → API 입출력, JSON 검증

아래에서 하나씩 비교해보겠습니다.


한눈에 비교

항목일반 ClassNamedTupledataclassBaseModel(Pydantic)
목적객체지향 프로그래밍읽기 전용 데이터데이터 저장데이터 검증 + 직렬화
MutableOXO (기본)O (기본)
Immutable 가능직접 구현기본 제공frozen=Truefrozen=True
생성자 자동 생성XOOO
repr 자동XOOO
비교(eq) 자동XOOO
타입 힌트선택OOO
런타임 타입 검사XXXO
JSON 변환직접 작성직접 작성asdict()model_dump(), model_dump_json()
ValidationXXX매우 강력
속도빠름매우 빠름빠름상대적으로 느림
메모리보통매우 적음적음가장 큼
실무 사용 빈도★★★★☆★★☆☆☆★★★★★★★★★★

언제 무엇을 사용할까?

상황추천
비즈니스 로직이 많다일반 Class
좌표, RGB, Point처럼 변경되지 않는 데이터NamedTuple
대부분의 DTO, Entitydataclass
FastAPI Request/ResponseBaseModel
JSON 검증BaseModel
DB Entitydataclass
설정 파일(Config)BaseModel
계산 객체일반 Class

1. 일반 클래스(Class)

특징

  • 가장 자유롭다.
  • 메서드를 많이 넣을 수 있다.
  • 생성자를 직접 작성해야 한다.

예를 들어 쇼핑몰의 상품을 생각해보겠습니다.

class Product:
    """
    상품 클래스

    데이터뿐 아니라
    상품의 동작(비즈니스 로직)도 함께 가진다.
    """

    def __init__(self, name: str, price: int):
        # 상품명
        self.name = name

        # 가격
        self.price = price

    def discount(self, percent: int):
        """
        할인 적용

        예:
        percent = 20
        -> 가격을 20% 할인
        """

        self.price = int(self.price * (100 - percent) / 100)

    def print_info(self):
        """상품 정보 출력"""

        print(f"상품명 : {self.name}")
        print(f"가격 : {self.price:,}원")


product = Product("노트북", 1800000)

product.print_info()

product.discount(10)

product.print_info()

출력

상품명 : 노트북
가격 : 1,800,000원

상품명 : 노트북
가격 : 1,620,000원

장점

✔ 객체지향에 적합

✔ 기능(메서드)을 많이 넣을 수 있음

✔ 상속에 유리


단점

  • 생성자를 직접 작성해야 함
  • repr 없음
  • 비교 연산 없음

2. NamedTuple

특징

읽기 전용(Immutable) 데이터입니다.

좌표처럼 변경되면 안 되는 데이터를 표현할 때 좋습니다.

from typing import NamedTuple

class Point(NamedTuple):
    """
    2차원 좌표

    한번 생성되면 수정할 수 없다.
    """

    x: int
    y: int


point = Point(10, 20)

print(point.x)
print(point.y)

# point.x = 100
# AttributeError 발생

출력

10
20

장점

  • 메모리 사용량 적음
  • Immutable
  • Tuple처럼 사용 가능
x, y = point

print(x)
print(y)

단점

  • 수정 불가능
  • 기능 추가가 어려움

실무 예

class RGB(NamedTuple):
    red: int
    green: int
    blue: int

이미지 처리에서 자주 사용됩니다.


3. dataclass

가장 많이 사용하는 데이터 객체입니다.

from dataclasses import dataclass

@dataclass
class Customer:
    """
    고객 정보

    __init__
    __repr__
    __eq__
    를 자동 생성한다.
    """

    id: int
    name: str
    age: int


customer = Customer(
    id=1,
    name="홍길동",
    age=25
)

print(customer)

출력

Customer(id=1, name='홍길동', age=25)

수정 가능

customer.age = 30

print(customer)

자동 비교

a = Customer(1, "홍길동", 25)
b = Customer(1, "홍길동", 25)

print(a == b)

출력

True

dict 변환

from dataclasses import asdict

print(asdict(customer))

출력

{
    'id':1,
    'name':'홍길동',
    'age':30
}

실무 예

전자상거래 주문 Entity

from dataclasses import dataclass

@dataclass
class Order:
    """
    주문 Entity
    """

    order_id: int
    customer: str
    total_price: int

ORM 없이 간단한 프로젝트에서 많이 사용됩니다.


4. BaseModel (Pydantic)

실무에서 FastAPI를 사용한다면 가장 많이 만나는 클래스입니다.

from pydantic import BaseModel, Field

class User(BaseModel):
    """
    회원 가입 데이터

    입력값을 자동 검증한다.
    """

    name: str

    age: int = Field(
        ge=0,
        le=120
    )

    email: str


user = User(
    name="홍길동",
    age=25,
    email="test@test.com"
)

print(user)

Validation

User(
    name="홍길동",
    age=-5,
    email="abc@test.com"
)

결과

ValidationError

age
Input should be greater than or equal to 0

JSON 변환

print(user.model_dump())

출력

{
    "name":"홍길동",
    "age":25,
    "email":"test@test.com"
}

JSON 문자열

print(user.model_dump_json())

실무 예

FastAPI Request

from pydantic import BaseModel, EmailStr, Field

class RegisterRequest(BaseModel):
    """
    회원가입 요청 모델

    클라이언트가 보낸 데이터를
    자동으로 검증한다.
    """

    username: str = Field(min_length=3, max_length=20)
    password: str = Field(min_length=8)
    email: EmailStr

클라이언트가 잘못된 이메일이나 너무 짧은 비밀번호를 보내면 Pydantic이 자동으로 검증하여 오류를 반환합니다.


실무에서 가장 많이 쓰이는 패턴

계층사용하는 객체
API RequestBaseModel
API ResponseBaseModel
Service일반 Class
Domain Entitydataclass
Repositorydataclass
설정(Config)BaseModel
Value ObjectNamedTuple 또는 @dataclass(frozen=True)

어떤 것을 선택해야 할까?

                 데이터를 표현하려는가?
                        │
               ┌────────┴────────┐
               │                 │
         검증이 필요한가?      비즈니스 로직이 많은가?
               │                 │
          ┌────┴────┐         ┌──┴──┐
          │         │         │     │
        예          아니오    예    아니오
          │          │         │      │
      BaseModel   dataclass   Class  Immutable?
                                      │
                               ┌──────┴──────┐
                               │             │
                              예            아니오
                               │             │
                    NamedTuple 또는       dataclass
                    @dataclass(frozen=True)

학습 순서 추천

파이썬 중급 과정에서는 다음 순서로 학습하면 개념이 자연스럽게 연결됩니다.

  1. 일반 클래스(Class): 객체지향의 기본 원리와 캡슐화, 메서드 설계

  2. NamedTuple: 불변(Immutable) 데이터와 경량 객체

  3. dataclass: 데이터 중심 객체와 자동 메서드 생성

  4. Pydantic BaseModel: 데이터 검증, 직렬화, API 모델링

  5. 추가 심화 주제

    • __slots__를 이용한 메모리 최적화
    • @dataclass(frozen=True)를 활용한 불변 객체
    • field(default_factory=...)__post_init__()
    • typing.ProtocolABC를 활용한 인터페이스 설계
    • attrs 라이브러리와 dataclass 비교
    • Pydantic v2field_validator, computed_field, model_validator 활용
profile
Hello, I'm Terry! 👋 Enjoy every moment of your life! 🌱 My current interests are Signal processing, Machine learning, Python, Database, LLM & RAG, MCP & ADK, Multi-Agents, Physical AI, ROS2...

0개의 댓글