[테코톡 공부 🧑‍🏫] DTO vs VO

Hyunjoon Choi·2023년 10월 18일
0

테코톡 공부

목록 보기
1/1
post-thumbnail

DTO와 VO의 혼용 사례와 원인

구글링 해 보면 사람들이 DTO와 VO를 혼용하여 쓰는 경우가 많다

원인

core J2EE Patterns 책의 1판에서는 데이터 전달용 객체를 VO로 정의했지만, 2판부터는 혼동의 여지 때문에 TO로 재정의하였기 때문으로 추측된다. 그리고 현재 데이터 전달용 객체의 정의는 D를 붙여 DTO로 정의하고 있다.

혼동의 여지가 있어 수정한 정의가 오히려 혼동을 초래했다. 이름이 다른 만큼 구별해보자.

결론 먼저!!

DTO는 데이터 전달용이며, VO는 값 표현용이다.

DTO란?

정의

  • Data Transfer Object
  • 데이터를 전달하기 위해 사용하는 객체 (계층 간 데이터를 전달)
  • 데이터를 담아서 전달하는 바구니

특성

  • 오직 getter/setter 메서드 만을 갖는다.
    • setter 메서드를 가질 경우 데이터는 가변적이다.
  • 다른 로직을 갖지 않는다. 순수하게 데이터 전달만을 위한 객체이기 때문이다.

예시

public class CrewDto {
    private String name;
    private String nickname;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }
}

// Service layer
public CrewDto createNewCrew() {
    String newName = "김태희";
    String newNickname = "Inbi";
    
    CrewDto crewDto = new CrewDto();
    crewDto.setName(newName);
    crewDto.setNickname(newNickname);

    return crewDto;
}

// Web layer
public String createNewCrew() {
    CrewDto newCrewDto = sampleService.createNewCrew();
    String nameOfNewCrew = newCrewDto.getName();
    String nicknameOfNewCrew = newCrewDto.getNickname();
    return nameOfNewCrew + nicknameOfNewCrew;
}

DTO를 불변객체로!

DTO에서 setter 메서드들을 없애면 전달 과정 중에서의 데이터 불변성을 보장할 수 있어 더욱 안정적이다.

DTO Class와 Entity Class

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

Entity 클래스를 기준으로 테이블이 생성되고 스키마가 변경되며, 뷰는 비즈니스 요구사항에서 자주 변경되는 부분이다.

만약 Entity 클래스를 요청이나 응답 값을 전달하는 클래스로 사용한다면, 뷰가 변경될 때 마다 Entity 클래스를 그에 맞춰 매번 변경해야 한다.

수많은 서비스 클래스나 비즈니스 로직들이 Entity 클래스를 기준으로 동작한다.

Entity 클래스를 변경하면 이러한 얽힌 많은 클래스들에 영향을 끼친다.

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

또한 응답 값으로 여러 테이블들을 조인한 결과값을 줘야 할 경우가 빈번하기 때문에 Entity 클래스만으로는 응답 값을 표현하기 어려운 경우가 많다.

Entity와 DTO를 분리하자.

VO란?

정의

  • Value Object
  • 값 그 자체를 표현하는 객체

예시

돈: 만 원 짜리 지폐가 고유번호가 서로 다르다고 해서 다른 만 원이라고 하지 않고 똑같은 만 원이라고 판단한다.

public class Money {
    private final int value;

    public Money(int value) {
        this.value = value;
    }

    public int getHalfValue() {
        return value / 2;
    }
}

// 일반적인 객체는 기본적으로 equals, hashcode 비교가 모두 불일치로 나오기 때문에 재정의해야 한다.
@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);
}

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

이펙티브 자바에서도 나오는 내용이다. 요약하자면, 두 객체를 커스텀하게 같을 조건을 설정하기 위해서는 Object 클래스의 equalshashcode를 재정의해야 한다는 것이다. 이펙티브 자바를 정리할 때 새로 달아두겠다.

DTO vs VO

DTOVO
용도레이어 간 데이터 전달값 자체 표현
동등 결정속성값이 모두 같다고 해서 같은 객체가 아니다.속성값이 모두 같으면 같은 객체다.
가변 / 불변setter 존재 시 가변, setter 비 존재 시 불변불변
로직getter/setter 외의 로직을 갖지 않는다.getter/setter 외의 로직을 가질 수 있다.

Reference

profile
개발을 좋아하는 워커홀릭

0개의 댓글