Backend/Spring

DTO / Entity / VO

seung_soos 2023. 4. 18. 23:51

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