Servlet => Spring => Spring Boot 순서로 공부를하며 DTO와 Entity의 차이점은 간략하게 파악하였다.
하지만 DTO와 VO는 어떠한 차이점이 있을까?
여러 참고 사이트를 비교하며 정리해본다.
DTO(Data Transfer Object)
DTO는 데이터를 전달하기 위한 객체이다. 계층간의 Getter / Setter를 이용하여 데이터를 주고 받는다.
여러 레이어에서 사용할 수 있지만, 주로 View와 Controller사이에서 사용한다.
DTO는 Getter / Setter 메소드를 포함하고, 그 외의 비즈니스 로직은 포함하지 않는다.
EX)
public class MemberDto {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Setter가 아닌 생성자를 이용해서 초기화하는 경우 불변 객체로 활용 할 수 있다. 불변 객체로 만들시 데이터를 전달하는 과정에서 데이터가 변조되지 않는다.
public class MemberDto {
private final String name;
private final int age;
public MemberDto(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
VO(Value Object)
VO는 값 자체를 표현하는 객체이다. VO는 객체들의 주소가 달라도 값이 같으면 동일한것으로 여긴다.
EX) 고유번호가 다른 만원 2장이 있다. 이 둘은 고유번호(주소)는 다르지만 값(10,000원)은 동일하다.
VO는 Getter 메소드와 함께 비즈니스 로직도 포함 할 수 있다. 단, Setter 메서드는 포함하지 않고, 값의 비교를 위해
equals()와 hashCode() 메소드를 오버라이딩 해줘야한다.
public class Money {
private final String currency;
private final int value;
public Money(String currency, int value) {
this.currency = currency;
this.value = value;
}
public String getCurrency() {
return currency;
}
public int getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Money money = (Money) o;
return value == money.value && Objects.equals(currency, money.currency);
}
@Override
public int hashCode() {
return Objects.hash(currency, value);
}
}
// MoneyTest.java
public class MoneyTest {
@DisplayName("VO 동등비교를 한다.")
@Test
void isSameObjects() {
Money money1 = new Money("원", 10000);
Money money2 = new Money("원", 10000);
assertThat(money1).isEqualTo(money2);
assertThat(money1).hasSameHashCodeAs(money2);
}
}
EX) equals()와 hashCode() 메서드를 오버라이딩 하지 않았을 때
EX) equals()와 hashCode() 메서드를 오버라이딩 하였을 때
Entity
Entity는 실제 DB 테이블과 매핑되는 핵심 클래스이다. 이를 기준으로 테이블이 생성되고 스키마가 변경된다.
따라서, 절대로 Entity를 요청이나 응답값을 전달하는 클래스로 사용해서는 안된다.
그리고 비즈니스 로직을 포함할 수 있다.
public class Member {
private final Long id;
private final String email;
private final String password;
private final Integer age;
public Member() {
}
public Member(Long id, String email, String password, Integer age) {
this.id = id;
this.email = email;
this.password = password;
this.age = age;
}
}
세 객체 비교
분류 | DTO | VO | Entity |
정의 | 레이어간 데이터 전송용 객체 | 값 표현용 객체 | DB 테이블 매핑용 객체 |
상태 변경 여부 | Setter 존재시 가변, Setter 비 존재시 불변 |
불변 | Setter 존재시 가변, Setter 비 존재시 불변 |
로직 포함 여부 | 로직을 포함 할 수 없다. | 로직을 포함 할 수 있다. | 로직을 포함 할 수 있다. |
참고 사이트 : 인비의 DTO vs VO