◇ PART · MVC

DTO · VO · Model

세 객체의 역할과 차이

학습 목표

  • DTO · VO · Model 세 단어의 의미를 안다
  • 「데이터 그릇」 의 다양한 종류를 구분한다
  • 실무에서 어떻게 섞여 쓰이는지 안다
  • 본 과정의 표기 컨벤션을 안다

⚠️ 자주 헷갈리는 세 단어

학생들의 의문

"DTO·VO·Entity·Model — 다 비슷한 자바 클래스인데 왜 이름이 4 개?"

실제로 코드만 보면 비슷합니다. 차이는 「어디서 어디로 가는 그릇이냐」.

🛠️ 식당 비유 — 그릇의 종류

계층 사이의 운반 그릇

식당의 그릇이 용도에 따라 다른 모양이듯, 객체도 어디로 가느냐에 따라 다른 이름.

주방(DB) → 셰프(Service) → 종업원(Controller) → 손님(View) ↓ ↓ ↓ ↓ [ Entity ] [ DTO ] [ DTO/Model ] [ JSP ${data} ]

① DTO (Data Transfer Object)


package com.smhrd.domain;

public class Board {        // 본 과정의 도메인 — DB 한 행과 1:1
    private int    num;
    private String title;
    private String writer;
    private String content;

    // getter/setter (또는 Lombok @Data)
    public int    getNum()    { return num; }
    public void   setNum(int num) { this.num = num; }
    public String getTitle()  { return title; }
    public void   setTitle(String title) { this.title = title; }
    // ...
}
  • 책임: 계층 사이 데이터 운반
  • 특징: getter/setter 위주. 비즈니스 로직 거의 없음
  • 전형적 사용: Controller ↔ Service ↔ Mapper 사이

② VO (Value Object) — 코드


public class Money {
    private final int amount;
    private final String currency;

    public Money(int amount, String currency) {
        this.amount = amount;
        this.currency = currency;
    }

    public Money add(Money other) {        // 「값」으로 의미 있는 동작
        if (!this.currency.equals(other.currency))
            throw new IllegalArgumentException();
        return new Money(this.amount + other.amount, this.currency);
    }

    public int getAmount() { return amount; }
    public String getCurrency() { return currency; }
    // setter 없음 (불변)
}

② VO (Value Object) — 특징

  • 책임: 「값」 자체를 표현 — 동등성이 핵심
  • 특징: 불변(immutable). 같은 값이면 같은 객체
  • 예시: 돈, 좌표, 색상, 기간 등
  • setter 없음 — 상태를 바꾸려면 새 객체를 만든다
  • equals / hashCode 를 값 기준으로 재정의하는 것이 관례

③ Entity (참고만)


// 본 과정에선 사용 안 함 — JPA 의 개념을 참고로만
@Entity
public class BoardEntity {
    @Id @GeneratedValue
    private Long num;
    private String title;
    // ...
}
  • 책임: DB 의 한 행을 표현 (JPA 의 개념)
  • 특징: ID 로 식별. 영속성 컨텍스트가 관리
  • 본 과정에서: 사용 안 함 — 후속 JPA 과정에서

④ Model (Spring 의 인터페이스)


@GetMapping("/board/view")
public String view(@RequestParam int num, Model model) {
    Board b = service.find(num);
    model.addAttribute("board", b);
    return "board/view";
}

<!-- view.jsp 에서 -->
<h1>${board.title}</h1>
<p>작성자: ${board.writer}</p>
<div>${board.content}</div>
  • 책임: Controller → JSP 데이터 전달용 「그릇」
  • 특징: Spring 이 매 요청마다 만들어주는 객체. 우리가 직접 만들지 않음
  • 주의: MVC 의 「M」(Model 패턴) 과 다른 의미 — 헷갈리지 말 것

네 가지 한눈에 비교

이름책임특징본 과정에서
DTO계층 간 운반getter/setter핵심 — Member·Board 같은 도메인 클래스
VO값 표현불변, 동등성드물게 (Money 등)
EntityDB 한 행JPA사용 안 함
ModelJSP 로 전달Spring 인터페이스Controller 매개변수

실무에선 자주 섞여 쓰임

실무 코드에서는 한 클래스가 여러 역할을 하기도 합니다:

  • 본 과정의 Board / Member 는 — VO 처럼 「데이터」 운반, DTO 처럼 계층 간 이동, Entity 처럼 DB 행 표현
  • 이름은 BoardDTO, BoardVO, Board 등 다양 — 본 과정은 접미사 없는 이름으로 통일
  • 같은 코드베이스 안에서는 일관성 이 중요

엄격히 구분하기보다 — 「이 클래스가 어디서 어디로 가는 그릇인가」 를 안다면 충분.

본 과정의 컨벤션

  • 도메인 객체는 단순히 클래스 이름 (Member, Board, Reply) — DTO·VO 접미사 안 붙임
  • 패키지com.smhrd.domain
  • 비즈니스 로직 거의 없음 — getter/setter 위주
  • Lombok @Data 권장 (반복 코드 줄임)
  • 전용 그릇이 필요해질 때만 — MemberJoinDTO 같은 명시적 이름 (후속 차시에서)

Lombok @Data — 짧게 쓰기


package com.smhrd.domain;

import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

@Data @AllArgsConstructor @NoArgsConstructor
public class Member {
    private String id;
    private String pwd;
}

단 몇 줄. @Data 한 줄이 getter / setter / equals / hashCode / toString 을 컴파일 시점에 자동 생성합니다.

Lombok @Data — 풀어쓴 모습


// 위 코드는 다음과 동일 (Lombok 이 자동 생성)
public class Member {
    private String id;
    private String pwd;

    public String getId() { return id; }
    public void   setId(String id) { this.id = id; }
    public String getPwd() { return pwd; }
    public void   setPwd(String pwd) { this.pwd = pwd; }

    public boolean equals(Object o) { ... }
    public int    hashCode() { ... }
    public String toString() { ... }
}

Model 의 함정 — Spring 의 「Model」

두 가지 Model 의 구분
  • MVC 패턴의 Model = 「데이터 + 비즈니스 로직」 의 추상 개념. Service + DAO + DTO 의 묶음.
  • Spring 의 Model = Controller 메서드에서 사용하는 인터페이스. 「JSP 로 데이터를 넘기는 그릇」.

두 Model 이 같은 단어지만 다른 의미. 헷갈리지 마세요.

🔄 Before / After

전 차시 끝

DTO·VO·Model — 모두 「자바 클래스인데 이름만 다른 것」 으로 막연.

이번 차시 끝

각 이름의 의미 차이를 안다. 본 과정에선 단순한 이름으로 통일.

이번 차시의 데이터 흐름

DB 한 행
Member/Board 객체
(DTO 역할)
Service
Model 에 담기
JSP
「그릇」 이 흐름의 모든 단계를 통과 — 데이터의 매개체

정리

오늘 들고 가는 것

  • DTO = 계층 간 운반 / VO = 값 / Entity = JPA 의 DB 행 / Model = Spring 의 JSP 전달 그릇
  • 실무에선 자주 섞여 쓰임 — 엄격한 구분보다 일관성 중요
  • 본 과정 컨벤션: 도메인 객체는 단순한 이름 (Member, Board) · 패키지 com.smhrd.domain
  • Lombok @Data 로 반복 코드 줄임