DTO vs VO vs Entity

해밀·2024년 2월 1일

❗important

목록 보기
2/2

🤔

객체 지향 프로그래밍에서의 중요한 개념인 DTO와 VO, 그리고 Entity. 대체 무슨 차이가 있길래 비교군으로 자주 언급되는 걸까?

DTO (Data Transfer Object)

In the field of programming a data transfer object (DTO) is an object that carries data between processes.


DTO란 프로세스간 데이터를 전달하는 객체이다.

  • DTO는 프로세스 간의 통신에서 발생하는 호출 비용을 줄이기 위해 사용된다.

  • DTO는 비즈니스 논리를 포함해서는 안 되지만, 데이터를 전송하기 위한 직렬화 및 역직렬화 매커니즘을 포함할 수 있는 간단한 객체이다.

  • 로직을 가지고 있지 않은 순수한 데이터 객체이기 때문에 불변하게 생성되어야 한다. 때문에 getter/setter 메소드만을 가진다.

  • 단일 setter를 가지는 경우 가변 객체로 활용할 수 있으며, 생성자를 통해 초기화하는 경우 불변 객체로 활용할 수 있다.

  • presentation layer와 근본적인 도메인 모델 사이에 상당한 불일치가 존재할 경우, DTO를 사용하는 것이 유용하다.

DTO 예제

public class UserDTO {
	private String userId;
	private String userName;
    private String password;
    
    //기본 생성자
    public UserDTO() {}
    
    //setter
    public setUserDTO(String userId, String userName, String password) {
    	this.userId = userId;
        this.userName = userName;
        this.password = password;
    }
    
    //getter
    public String getUserId() {
    	return userId;
    }
    public String getUserName() {
    	return userName;
    }
    public String getPassword() {
    	return password;
    }
    
    //여기에 디버깅용으로 toString 메소드 정도 추가
}

⭐ 필드를 'private'로 선언하고, 생성자를 통해 값을 설정한 후에는 변경되지 않도록 작성.


VO (Value Object)

In computer science, a value object is a small object that represents a simple entity whose equality is not based on identity: i.e. two value objects are equal when they have the same value, not necessarily being the same object.


value object(vo)는 동일성을 베이스로 하는 것이 아니라 단순히 실체를 나타내는 작은 객체이다. 즉, 두 vo는 같은 값을 가질 때 equal로 판단하며 꼭 같은 객체일 필요는 없다.

  • vo는 불변이어야 한다.

    • 생성된 두 개의 vo가 동일하게 유지되어야 한다는 암묵적 계약에 필요한 성질이다.

    • vo가 불변이어야 클라이언트 코드가 vo를 무효 상태에 놓거나, 인스턴스화 후 버그 동작을 도입할 수 없다.

  • 동일한 entity를 나타내는 동일한 vo를 여러 개 가질 수 있다.

    • 단일 인스턴스에 의존하고 이에 대한 참조를 사용하는 것보다, 새 vo를 만드는 것이 더 간단한 경우가 많다.

    • 참조가 아닌 값을 비교하려면 불변 객체를 생성함으로써 vo를 에뮬레이션 한다.

      • Emulation (에뮬레이션) : 한 시스템이 다른 시스템과 똑같이 따라 행동할 수 있도록 시스템을 복제하는 것.
  • 테이블 내에 있는 속성 외에 추가적인 속성을 가질 수 있다.


VO 예제

public class EmailAddress {
	private final String mail;
    
    // 생성자
    public EmailAddress(String mail) d
      // 이메일 형식 검증 등의 로직은 간소화했다고 가정
      if (isValidEmail(mail)) {
      	this.mail = mail;
      } else {
      	  throw new IllegalArgumentException("Invalid email address");
      }
      
     // Getter
     public String getMail() {
     	return mail;
     }
     
     // 불변성을 유지하면서 새로운 EmailAddress 객체를 생성하는 메소드
     public EmailAddress withNewValue(String newValue) {
     	return new EmailAddress(newValue);
     }
     
     // 값 동일성 비교를 위한 equals와 hashCode 메소드 오버라이드
     @Override
     public boolean equals(Object o) {
     	if (this == o) return true;
        if (o == null) || getClass() != o.getClass()) return false;
        EmailAddress emailAddress = (EmailAddress) o; 
        return Object.equals(mail, emailAddress.mail);
     }
     
     @Override
     public int hashCode() {
     	return Objects.hash(mail);
     }
     
     // 이메일 형식 검증을 위한 메소드 (간소화)
     private boolean isValidEmail(String email) {
     	return email != null && email.contains("@");
     }

}

⭐ 참조가 아닌 값을 비교하려면 equals 및 hashCode의 필수 정의 필요.

Value Object는 도메인의 특정 개념적인 값을 표현하기 위해 사용되며, 주로 비즈니스 로직에 바로 적용된다.


Entity

In computer science, an entity is an object that has an identity, which is independent of the changes of its attributes.

엔터티는 객체가 가진 속성의 변화와는 독립적인 정체성을 가진 객체를 의미한다.

  • 실제 DataBase의 테이블과 1:1로 Mapping 되는 클래스

    • Entity를 기준으로 테이블이 생성되고, 스키마가 변경되기 때문에 요청이나 응답값을 전달하는 클래스로 사용해서는 안 된다.

    • DB의 테이블 내에 존재하는 컬럼만을 속성(필드)로 가져야 한다.

  • 상속을 받거나 구현체여서는 안 된다.

  • id를 통해 각각의 Entity를 구분한다.

  • VO와 마찬가지로 비즈니스 로직을 가질 수 있다.

  • DTO와 마찬가지로 setter를 가지는 경우 가변 객체로 활용할 수 있다.

    • Entity class의 가변성은 데이터베이스와의 연동 및 트랜잭션 처리를 위한 목적으로 사용된다.

    • 도메인 모델의 경우 불변 객체를 사용하는 것이 일반적이므로, 도메인 주도 설계(DDD)에서는 도메인 모델에서 변경이 불가능한 상태를 유지하되 필요한 경우 새로운 객체를 생성하여 상태를 변경하는 것이 권장된다.


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 vs VO vs Entity

  1. DTO
    • 레이어간 데이터를 전송하는 용도의 객체
    • 비즈니스 로직 포함 불가능
    • 가변 객체, 혹은 불변 객체

  2. VO
    • 값을 가지는 객체
    • 비즈니스 로직 포함 가능
    • 불변 객체
    • equals와 hashCode 재정의

  3. Entity
    • DB 테이블과 1:1로 매핑되는 객체
    • 비즈니스 로직 포함 가능
    • 가변 객체, 혹은 불변 객체
    • id를 통해 각각의 Entity를 구분

Data_transfer_object (위키)
LocalDTO (martinfowler, bliki)
Value_object (위키)
DTO와 VO 그리고 Entity의 차이 (github.io, youngjinmo)
Entity, DTO, VO 바로 알기 (velog, @gillog)
[10분 테코톡] 🎼라흐의 DTO vs VO (youtube, 우아한테크)
[10분 테코톡] 📍인비의 DTO vs VO (youtube, 우아한테크)
DTO vs VO vs Entity (tecoble.techcourse, 우아한테크코스)

profile
사랑이란 이름의 용기가 필요해

0개의 댓글