본문 바로가기
IT/Java

Entity, DTO, VO 차이

by 성준하이 2022. 8. 18.
반응형

자바에서는 객체를 구현하는 다양한 방법이 있는데 

대표적으로 Entity, DTO, VO 이렇게 세가지가 있다.

 

이들에 대해서 다뤄보려고 한다.

먼저 세가지를 분명하게 구분하는 이유는 다음과 같다.

 

Entity와 DTO를 분리해서 관리해야 하는 이유는 DB Layer와 View Layer 사이의 역할을 분리 하기 위해서이다.
DB Layer = Persistence Tier, View Layer = Presentation Tier

Entity는 실제 테이블과 매핑되어 만일 변경되게 되면 여러 다른 Class에 영향을 끼치고,

DTO는 View와 통신하며 자주 변경되므로 분리 해주어야 한다.

결국 DTO는 Domain Model 객체(Entity)를 그대로 두고 복사하여,

다양한 Presentation Logic을 추가한 정도로 사용하며 Domain Model 객체(Entity)는 Persistent만을 위해서 사용해야한다.

 

Entity

Entity를 작성할 때 Setter를 무분별하게 사용하면 객체(Entity)의 값을 쉽게 변경할 수 있으므로, 객체의 일관성을 보장할 수 없다.

객체의 일관성을 유지할 수 있어야 유지 보수성이 올라가기 때문에 Setter 사용을 최대한 지양해야하며,

객체의 생성자에 값들을 넣어줌으로써 Setter 사용을 줄일 수 있다.

즉 엔티티는 persistance를 위해 값은 database 와 영속을 하여 변하지 않아야 하고 그러므로 setter 는 사용을 하지 않는것이 바람직하다.

Entity 의 예제는 다음과 같다.

@Getter
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(of = "id")
@Table(name = "member")
@Entity
public class Member {

    @Id
    @GeneratedValue
    private int id;

    @Column(name = "name", nullable = false)
    private String name;

    @Column(name = "password", nullable = false)
    private String passwd;

    @Column(name = "email", nullable = false, unique = true)
    private String email;

    @Column(name = "phone", nullable = false, unique = true)
    private String phone;

    @Column(nullable = true)
    private LocalDateTime createDate;

    private LocalDateTime modifyDate;

    @Builder(
            builderClassName = "init"
            , builderMethodName = "initUser"
    )
    private User(MemberDTO dto) {
        id = dto.getId();
        name = dto.getName();
        ...
    }
}

 

VO(Value Object)

VO는 사용하는 이유가 다양하게 있지만 영어 이름처럼 값을 저장하기 위해 사용을 한다.

그러면서 동시에 비교를 위해서도 사용한다.

VO(Value Object)는 말 그대로 값 객체라는 의미를 가지고 있다.
VO의 핵심 역할은 equals()와 hashcode()를 오버라이딩 하는 것이다.
VO 내부에 선언된 속성(Field)의 모든 값들이 VO 객체마다 값이 같아야, 똑같은 객체라고 판별한다.

예전 포스팅에서 Equals 와 hashcode를 함께 재정의 하는 이유에 대해 다뤄본적이 있는데,

그것을 이 VO에서 해결을 해주고 넘어갈수가 있다.

해당 내용은 아래 참고 포스팅을 확인해보는것을 추천한다.

VO의 예제는 다음과 같다.

@Getter 
@Setter

@Alias("example")
class exampleVO {
    private Long a;
    private String b;
    private String c;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Example example = (Example) o;
        return Objects.equals(id, example.a);
    }

    @Override
    public int hashCode() {
        return Objects.hash(a);
    }
}

 

DTO(Data Transfer Object)

가장 우리에게 친숙한 DTO이다.

DTO는 계층간 데이터 교환을 위한 객체이고 DB의 데이터를 Service나 Controller 등으로 보낼 때 사용하는 객체를 말한다.

즉, DB의 데이터가 Presentation Logic Tier로 넘어올때는 DTO로 변환되어 오고가는 것이다.

로직을 갖고 있지 않는 순수한 데이터 객체이며, getter/setter 메서드만을 갖는다.(lombok으로 대체하는 추세)

또한 Controller Layer(ViewLayer)에서 Response DTO 형태로 Client에 전달한다.

예제는 다음과 같다.

@Getter 
@Setter
class exampleDto {
  private String a;
  private String b;
  private String c;
}

 

결론을 정리한 표는 다음과 같다.

생성 목적 JPA 사용시 DB Table과 직접적으로 매핑하여
DB에 접근할때 사용
객체안의 값을 통해서도 비교해야하는
중요 로직에서 사용할 Data를 담기위해 사용
단순 Data 송, 수신 용도
getter 사용 O O O
setter 사용 X O O
equals & hashCode 구현 O O X
데이터 민감도 100 80 0
Spring Tier 사용 범위 Persistence(DAO, Repository) <-> Business(Service) Business(Service) <-> Presentation(Controller) Business(Service) <-> Presentation(Controller)

참고 포스팅

https://thenicesj.tistory.com/194

 

equals 와 hashCode의 재정의를 같이 해야하는 이유

먼저 아래와 같이 클래스를 정의해두고 public class Person { private final String name; public Person(tring name) { this.name = name; } // intellij Generate 기능 사용 @Override public boolean equals(O..

thenicesj.tistory.com

 

반응형

'IT > Java' 카테고리의 다른 글

querydsl 동적 쿼리 관련  (60) 2022.08.21
jackson annotation 관련  (41) 2022.08.20
JPA, Hibernate, Spring Data JPA  (48) 2022.08.17
자바 직렬화(Serializable)  (34) 2022.08.15
delay 설정하기 (Thread.sleep)  (45) 2022.08.13

댓글