📜 제목으로 보기

DTO vs VO

혼용 사례

  • 특정 책 1판에 의해서 사람들이 잘못 인지하게 됨.
    • 지금은 데이터 전달은 TO + Data -> DTO로만 사용
    • VO = 값 표현용

DTO(Data Transfer Object)

  • DTO는 프로세스 간에 데이터를 전달하는 객체
  • 주로 비동기 처리를 해야할 때 사용
  • 로직을 갖고 있지 않은 순수한 데이터 전달객체라 setter(보내는쪽)/getter(받는쪽)로만 구성되는데, DB에서 값을 받아오므로 setter가 없이. 생성자에서 값할당한 이후 끝.

  • 정확히는 계층간 데이터 전달 객체 image-20220211092511970
    • Controller(웹)와 Service(서비스)사이에 데이터 전달용으로 사용된다.

예시를 통한 DTO 학습(CrewDto)

image-20220211092647799

  • service layer에서 데이터를 보낼 때 (받는 쪽에서 사용하라고 정의만)

    • createXXX()메서드를 통해 DTO생성 + Dto에 정의한 setter()로 데이터 박아로 데이터전달`을 수행한다. image-20220211092929797
  • controllerlayer( 레이어)에서 데이터를 받을 땐

    • **service에 정의해둔 createXXX()메서드를 통해 -> **
      • 데이터박힌 DTO 생성
      • DTO.getter로 데이터들 받기
  • setter를 제거하고 생성자로만 데이터를 받아 생성된 불변의 DTO주도록 수정

    • setter를 삭제한다 -> VO처럼 불변객체가 됨 -> 데이터 전달과정 시 불변성 보장 -> 안정적

    image-20220211093943190

Entity와 분리

image-20220211094416744

  • View는 요구사항에 의해 자주 변경되는 부분이다.
    • entity기준으로 테이블 생성/ 스키마변경하는 class -> 요청/응닶값 전달 클래스로 사용하지 말 것
      • view변경시마다 entity도 매번 변경해야함.
      • 관련된 수많은 비지니스 로직(class)들이 영향을 끼치게 됨.
    • view변경에 따라 -> 다른 class에 영향을 끼치지 않는 DTO class를 요청/응답값에 사용
      • join한 결과값 조회 -> entity로는 다 표현X

예시(로또, Car 정의)

  • 예시 - 로또 image-20220211085655445

  • 예시 - Car

      class CarDTO {
          private String name;
          private int position;
      }
    
    • 생성이후 OutputView로 가공된 DTO 객체를 보내줄 수 있습니다.

특징

  1. 데이터 접근 메서드만 가진다.
  2. 정렬과 직렬화 메서드는 가질 수 있다.
  3. 데이터 캡슐화 -> 유연하게 대응된다.
    • 데이터 요청수 감소 효과

VO(Value Object)

  • 값 객체
  • VO의 핵심은 equals()와 hashcode()를 오버라이딩하하여 내부에 선언된 속성(필드)의 모든 값들이 같으면 ---> 똑같은 객체라고 판단하게 한다
  • 원시 값을 감싼다 -> validation이 가장 큰 역할 중 하나
    • my) 식별자로 접근해야 데이터 변화에 대응한다

예시를 통한 VO 학습(Money)

  • 고유번호 = 내부 값이 같으면 -> 같은 객체 image-20220211094846843

  • Money class

    image-20220211094904840

    • VO는 값 자체 표현 = DTO처럼 불변 객체
      • DTO처럼, setter성격의 메소드 X 생성자로서만 초기화
      • VO는 DTO와 달리 getter이외에 로직을 포함 ex> getHalfValue
  • 일반적인 객체 -> equals비교와 hashCode비교가 불일치로 나온다.

    image-20220211095135241

  • 완전한 VO를 위하여

    • hashCode()의 return값 비교 -> 같으면 equals()로 한번더 비교 image-20220211095215083

    • 완전한 VO == 객체를 속성값으로만 비교하게 하기 위해 -> 2개 메소드 오버라이딩

      • 속성값인 value로만 비교할 수 있게 된다.

      image-20220211095445918 image-20220211095532262

예시(Car)

  • Car - 움직임이 있다면( 내부 속성이 변함) -> new 새로운 객체로 반환하여 -> 원래 자기가 가지던 값은 변하지 않고 -> 변한 것은 다른 값 객체로 취급

    • 내부속성 변화가 없다면 (움직이지않았다면) -> 자기자신 반환 return this;
      public Car move(int randomNum) {
          if (randomNum >= MOVE_POINT) {
              return new Car(this.name, position+1)
          }
          return this;
      }
    

특징

  1. 값 자체로 의미를 가진다.

  2. 변하지 않는 값을 가진다

    • 불변 보장(변하면 새객체)해서 안전성과 생산성
  3. 객체 비교시 ID를 사용하지 않음

  4. 같은 객체로는 속성들의 값을 비교한다.

DTO와 VO공통점과 차이점

  • DTO: 레이어간 데이터 전달을 위함
    • 객체 동등비교시, 속성값 같다고 같은 객체 아니다.
    • setter를 넣어준다면 가변, 보통 불변
    • getter/setter외 로직X
  • VO: 값 자체 표현
    • 객체 동등비교시, 속성값 같으면 같은 객체 by 오버라이딩
    • setter없이 생성자로 초기화하는 불변
    • getter/setter외 로직을 가질 수 있다.