domain, dto, vo 구분

세 가지를 한 문장으로 요약한다면:

  • Domain (도메인): 우리 서비스의 핵심 주인공 (예: 회원, 주문). 행동(로직)과 생각(규칙)을 가진 실체.
  • DTO (Data Transfer Object): 우체부 또는 택배 상자. 단순히 데이터를 A에서 B로 안전하게 전달하는 역할만 함.
  • VO (Value Object): 돈, 주소, 날짜처럼 값 자체가 중요한 개념 덩어리. ‘5,000원’은 그 자체로 의미가 있음.

비유로 이해하기: “카페에서 커피 주문하기”

카페에서 커피를 주문하는 상황에 이 세 가지를 대입해 보겠습니다.

1. Domain (도메인): “손님”과 “바리스타”

  • 손님 (Domain Object):
    • 데이터: 이름, 멤버십 등급, 보유 포인트
    • 행동(로직): “주문한다”, “포인트를 적립한다”, “멤버십 등급이 오른다”
    • 손님은 우리 카페 이야기의 핵심 주인공입니다. 손님 없이는 아무 일도 일어나지 않습니다.
  • 바리스타 (Domain Object):
    • 데이터: 이름, 경력
    • 행동(로직): “커피를 만든다”, “재고를 확인한다”
    • 바리스타도 이 이야기의 핵심 인물입니다.

2. DTO (Data Transfer Object): “주문서(영수증)”

  • 역할: 손님이 키오스크나 포스기에서 주문을 합니다. 이때 손님이 원하는 **데이터(“아이스 아메리카노 1잔, 시럽 추가”)**가 적힌 주문서가 바리스타에게 전달됩니다.
  • 특징:
    • 단순 데이터 전달: 주문서 자체는 아무런 행동도 하지 않습니다. 그냥 ‘정보’만 담고 있습니다.
    • 특정 목적: 이 주문서는 ‘손님 → 바리스타’로 주문 내용을 전달하는 딱 그 목적 하나만 가집니다.
    • 선별된 정보: 주문서에는 손님의 모든 정보(나이, 주소 등)가 아니라, 주문에 필요한 정보만 담겨 있습니다.
    • “주문 요청 DTO (OrderRequestDto)” 와 같습니다.
  • 바리스타가 커피를 다 만들면, “주문하신 아메리카노 나왔습니다”라는 진동벨이나 영수증 번호를 통해 손님에게 알려줍니다.
    • 이것은 “주문 완료 응답 DTO (OrderResponseDto)” 와 같습니다.

3. VO (Value Object): “5,000원”이라는 “돈”

  • 역할: 손님은 커피 값으로 “5,000원”을 지불합니다.
  • 특징:
    • 값 자체가 중요: 내가 낸 5,000원 지폐와 다른 사람이 낸 5,000원 지폐는 구분할 필요가 없습니다. 그냥 ‘5,000원’이라는 **값(Value)**이 중요합니다.
    • 불변: ‘5,000원’이라는 값은 변하지 않습니다. 5,000원에 1,000원을 더하면 ‘6,000원’이라는 새로운 값이 생길 뿐, 원래의 5,000원이 변하는 게 아닙니다.
    • 개념 덩어리: ‘돈’이라는 개념은 “음수일 수 없다”는 규칙을 가집니다. ‘5,000원’이라는 VO는 이 규칙을 스스로 지킬 수 있습니다.

표로 최종 정리

구분 Domain (도메인) DTO (Data Transfer Object) VO (Value Object)
핵심 역할 비즈니스의 주인공 (실체) 데이터 운반용 상자 의미를 가진 값 덩어리
비유 사람, 자동차, 주문 택배 상자, 신청서, 영수증 돈, 주소, 날짜, 색깔
로직(행동) ⭕️ 가짐 (가장 중요) ❌ 가지지 않음 (절대 금지) ⭕️ 가질 수 있음 (값과 관련된 간단한 로직)
식별 가능? ID로 구분 가능<br/>(동명이인 ‘홍길동’은 다른 사람) 구분할 필요 없음<br/>(내용물만 같으면 됨) 값으로만 구분<br/>(‘5,000원’은 모두 같은 5,000원)
불변성 상태가 변할 수 있음 보통 불변으로 만듦 반드시 불변이어야 함
주요 목적 비즈니스 로직과 규칙을 캡슐화 계층 간 데이터 전달 원시 타입(int, String)을 의미 있는 객체로 포장
위치 domain adapter domain (도메인의 일부)

그래서, 왜 구분해야 할까?

  • 도메인 vs DTO: 핵심 로직을 보호하기 위해!
    • 화면(UI)에 보여줄 데이터 형식이 바뀐다고 해서, 우리 비즈니스의 핵심 주인공인 “손님”의 본질이 바뀌면 안 됩니다. DTO라는 ‘주문서’ 양식만 바꿔주면, “손님”은 안전하게 보호됩니다.
  • 도메인 vs VO: 코드를 더 명확하고 안전하게 만들기 위해!
    • int price 라고 쓰는 것보다, Money price 라고 쓰는 것이 “이것은 ‘돈’이다”라는 의미를 명확하게 해줍니다.
    • Money 객체는 스스로 “음수가 될 수 없다”는 규칙을 지키므로, 개발자가 실수로 -1000 같은 값을 넣는 것을 원천적으로 막아줍니다.

이 비유와 표를 통해 세 가지 개념의 역할과 차이점이 조금 더 명확하게 다가오셨으면 좋겠습니다. 처음에는 분리하는 것이 번거롭지만, 익숙해지면 훨씬 더 안정적이고 이해하기 쉬운 코드를 작성하실 수 있게 될 겁니다.