✔ 참고영상
[10분 테코톡] 🎼라흐의 DTO vs VO
[10분 테코톡] 📍인비의 DTO vs VO
: 데이터 전송 객체
로직을 갖고 있지 않는 순수한 데이터 객체
*getter/setter 메서드만 가짐
계층(Layer) 간 데이터 교환을 위해 사용하는 객체
*계층? View, Controller, Service, DAO 등
DTO : 데이터를 전송할 때 사용하는 바구니
public class ProductDTO {
private String name;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
여기서 <예시 1>의 ProductDTO
는 Setter
를 사용하기 때문에 데이터가 가변적이라고 할 수 있다.
그러나 DTO의 주목적은 데이터 전송이므로 데이터의 불변성(Immutability)을 지키는 것이 좋다. 이를 위해 개발자들은 일반적으로 아래와 같은 규칙을 따른다.
- 데이터를 설정할 때 생성자와 초기화 메서드 사용
- 필드 변수에
final
키워드 추가Setter
메서드 삭제
위 세가지 규칙을 따라 수정한 코드는 다음과 같다.
public final class ProductDTO {
private final String name;
private final double price;
public ProductDTO(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
: 값 객체
ex1)
ColorVO
라는 VO가 있을 때 RCB값이 color1(255, 0, 0), color2(255,0,0) 속성을 가지면 color1과 color2는 이름이 다르더라도 같은 객체로 판단
ex2) 만원짜리 지폐의 고유 번호가 다르다고 해서 각각의 지폐를 다른 지폐라고 생각하지 않고 똑같은 만원 지폐로 판단
public class ColorVO {
private int r;
private int g;
private int b;
public ColorVO(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
}
public double getBrightness() { //밝기 값을 계산하는 로직
return Math.sqrt(0.299 * r * r + 0.587 * g * g + 0.114 * b * b);
}
}
앞서 ‘서로 다른 이름을 가진 VO 인스턴스의 모든 속성 값이 같다면 같은 객체로 판단’한다고 하였는데, 이는 어디까지나 규칙일 뿐, 실제로 구현하는 것은 개발자의 몫이다.
기본적으로 Java에서 equals()
와 hashCode()
메소드는 객체의 주소값을 비교하기 때문에, 만일 <예시 3> 코드 그대로 Test를 돌린다면 객체의 값이 같더라도 다른 객체로 취급되어 두 메서드 모두 실패했다고 뜰 것이다.
따라서 개발자들은 위 그림과 같이 equals()
와 hashcode()
메서드를 오버라이딩하여 해당 기능을 구현해야 한다.
오버라이딩을 적용한 코드는 다음과 같다.
public class ColorVO {
private int r;
private int g;
private int b;
public ColorVO(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
}
public double getBrightness() {
return Math.sqrt(0.299 * r * r + 0.587 * g * g + 0.114 * b * b);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ColorVO)) return false;
ColorVO colorVO = (ColorVO) o;
return r == colorVO.r && g == colorVO.g && b == colorVO.b;
}
@Override
public int hashCode() {
return Objects.hash(r, g, b);
}
}
DTO | VO | |
---|---|---|
사용목적 | 계층(layer) 간 데이터 전송 | 도메인 객체의 값을 나타내고 유지 |
로직유무 | 없음 Getter/Setter만 존재 | 비즈니스 로직 존재 |
가변성 | Setter가 있는 경우 가변 Setter가 없는 경우 불변 | 불변 |
퍼가요~