저는 DTO랑 VO를 구분하지 않고 비슷한 맥락으로 보고 있었는데요. 이 들의 차이를 구분하고 어떤 상황에서 DTO를 도입하고, VO를 도입해야 하는지 하나씩 알아보도록 하겠습니다.
DTO(Data Transfer Object)
- 순수하게 데이터를 담아 계층 간으로 전달하는 객체, Getter/Setter 메서드만을 가집니다.
- "데이터 전달"이 주목적입니다.
- 이를 통해 보내는 쪽에서 setter를 이용하여 값을 담아 전달하고, 받는 쪽에서는 getter를 이용하여 값을 꺼내서 쓰게 됩니다.
- setter의 경우, 변조 가능성이 있기 때문에(setter 사용 지양) 생성자로 값을 넣어주면, 전달하는 과정에서 변조가 불가능합니다.
VO(Value Object)
- DTO(Data Transfer Object)와는 반대로 로직을 포함할 수 있으며, VO의 경우 특정 값 자체를 표현하기 때문에 불변성의 보장을 위해 생성자를 사용해야 합니다.
- 타입도 같고, 내부의 속성 값도 같기에 equals & hashcode 메서드를 재정의해야 합니다.
- 수정자(setter)가 없는 불변 객체여야 합니다.
- VO는 서로 다른 이름을 갖는 VO 인스턴스라도 모든 속성 값이 같다면 두 인스턴스는 같은 객체인 것이 핵심입니다.
- 예를 들어, 모두 똑같은 옷이 색깔만 다르다고 하더라도 이를 별개의 객체로 보는 것이 아니라 하나의 객체로 보는 것과 같습니다.
class ClothesVOTest {
@Test
void ClothesVOEqualTest() {
prviate static final String color = "black";
ClothesVO c1 = new ClothesVO(color);
ClothesVO c2 = new ClothesVO(color);
assertThat(c1).isEqualTo(car2);
assertThat(c1).hasSameHashCodeAs(c2);
}
}
// 이것은 당연하게도 객체의 주소값을 비교하기 때문에 값이 같은 것과는 상관없이 테스트에서 에러가 납니다.
// 이러한 문제가 있기 때문에 값만을 비교하기 위해서 equals()와 hashCode()를 오버 라이딩해주어야 합니다.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClothesVO clothesVO = (clothesVO) o;
return Objects.equals(color, clothesVO.color);
}
@Override
public int hashCode() {
return Objects.hash(color);
}
비교
<참고 자료>
https://maenco.tistory.com/entry/Java-DTO%EC%99%80-VO%EC%9D%98-%EC%B0%A8%EC%9D%B4
https://tecoble.techcourse.co.kr/post/2020-06-11-value-object/
'Java > Spring' 카테고리의 다른 글
[Spring] @PropertySource, @Value 어노테이션에 대해 알아보자 (0) | 2023.11.25 |
---|---|
[Spring] JPA Auditing 기술을 사용하여 생성일자, 수정일자 컬럼의 데이터 형식을 깔끔하게 지정하는법 (0) | 2023.11.24 |
[Spring] 웹 애플리케이션과 영속성 관리 (0) | 2023.11.14 |
[Spring] Filter, Interceptor, ArgumentResolver (0) | 2023.10.15 |
[Spring] Nginx를 이용하여 http(80 Port)로 들어오는 요청을 springboot(8080 Port)로 Redirect 시키기 (0) | 2023.09.27 |