DTO, VO

Dev_Sanizzang·2023년 5월 19일
0

Spring

목록 보기
1/2

📕 개요

프로젝트를 진행하던 중 DTO와 VO에 대한 궁금증이 생겨 내용을 정리하고자 한다.

이 글은 우아한 Tech에서 진행한 10분 테코톡을 시청한 뒤 정리한 내용을 적고자 한다.

💡 [10분 테코톡] 📍인비의 DTO vs VO

결론

결론 먼저 말하자면

  • DTO = 데이터 전달용
  • VO = 값 표현용
    이것만 기억하면 된다.

DTO?


데이터를 전달하기 위해 사용하는 객체, 데이터를 담아서 전달하는 바구니

DTO의 특징

  • 오직 getter/setter 메서드 만을 갖는다.
  • 다른 로직을 갖지 않는다.

순수하게 데이터 전달 만을 위한 객체이기 때문에 위와 같은 특징을 갖는다.

DTO를 불변객체로!

위에서 DTO는 setter 메서드를 가질 수 있다고 했는데, setter 메서드를 가질 경우 해당 DTO는 데이터가 가변적이라고 할 수 있다.

오른쪽 코드와 같이 setter 메서드를 삭제하고 생성자를 통해 속성 값들을 초기화하게 만들어 불변객체로 만들면 DTO가 전달하는 데이터가 전달 과정 중에 변조되지 않음을 보장할 수 있다.

이를 통해 전달 과정 중에서의 데이터 불변성을 보장할 수 있어서 더욱 안정적이다.

DTO Class와 Entity Class를 분리하라!

Entity 클래스는 절대로 요청이나 응답 값을 전달하는 클래스로 사용하면 안된다.
-> 데이터베이스와 매핑되어 있는 핵심 클래스이기 때문

Entity 클래스를 기준으로 테이블이 생성되고 스키마가 변경된다.

View는 비즈니스 요구사항에서 자주변경되는 부분이다. 만약 Entity 클래스를 요청이나 응답 값을 전달하는 클래스로 사용한다면, Veiw가 변경될 때 마다 그에 맞춰서 매번 같이 변경해야 한다.

Entity 클래스를 변경하면 얽혀있는 무수히 많은 클래스 들에게 영향을 끼치게 된다. 따라서 요청이나 응답 값을 전달하는 클래스로는 반드시 View의 변경에 따라 다른 클래스들에게 영향을 끼치지 않고 자유롭게 변경할 수 있는 DTO를 사용해야 한다.

VO?

Value Object의 약자, 값 그 자체를 표현하는 객체

실생활의 VO 예시 - 돈

각각의 지폐들은 고유번호가 있다.
하지만 우리는 만원짜리 지폐가 고유번호가 서로 다르다고 해서 다른 만원이라고 하지 않고 똑같은 만원으로 본다. 이렇게 값 그 자체만을 나타내고 값으로만 비교되는 객체를 VO라고 한다.

Money VO 클래스 구현

public class Money {
	private final int value;
    
    public Money(int value) {
    	this.value = value;
    }
    
    public int getHalfValue() {
    	return value / 2;
    }
}

VO는 값 자체를 표현하기 때문에 불변객체여야 한다.

따라서 setter 성격의 메서드는 포함하면 안되고 생성자를 통해서만 값을 초기화해야 한다.

DTO가 getter, setter 메서드 외 로직을 포함할 수 없는 것과는 달리 VO는 이 외의 로직(getHalfValue())을 포함할 수 있다.

HashXXX (HashSet, HashMap, Hashtable)의 동등 비교 방식

Hash라는 이름을 갖는 프레임워크들 HashSet, HashMap, Hashtable은 두 객체가 동등한지 비교할 때 다음과 같은 과정을 거친다.

hashCode의 리턴값을 먼저 비교하고 같으면 equals로 한번 더 비교한다. 완전한 VO로 만들기 위해서는 객체를 속성 값들로만 비교하도록 equals 메서드와 hashCode 메서드를 모두 오버라이딩 해줘야 한다.

equals() & hashCode() 오버라이딩

public class Money {
	private final int value;
    
    public Money(int value) {
    	this.value = value;
    }
    
    public int getHalfValue() {
    	return value / 2;
    }
    
    @Override
    public boolean equals(Object o) {
    	if (this == o) {
        	return true;
        }
        if (!(o instanceof Money)) {
        	return false;
        }
        
        Money money = (Money) o;
        return value == money.value;
    }
    
    @Override
    public int hashCode() {
    	return Objects.hash(value);
    }
}

Money 클래스를 이와 같이 속성 값인 value 만을 기준으로 비교하도록 equals와 hashCode를 오버라이딩하여 Money 객체를 완전한 VO로 만들어 준다.

DTO vs VO

profile
기록을 통해 성장합니다.

0개의 댓글