본문 바로가기
야미스터디/Backend

[Etc] DTO 📌

by 의정부핵꿀밤 2022. 9. 28.
728x90

👜 DTO

  • Data Transfer Object / dto package
  • 계층 간 데이터 교환을 위해 사용하는 객체
  • 로직을 갖지 않는 순수한 데이터 객체이다
  • 데이터를 전달하기 위해 사용하는 객체이기 때문에 오직 getter/setter 메서드만을 가지며 다른 로직은 갖지 않는다
  • 데이터를 담아서 전달하는 바구니라고 생각하면 된다
  • 주로 데이터베이스와 통신하거나 소켓에서 받은 메시지의 구문을 분석할 때 유용하게 사용된다

 

 

DTO를 사용하는 이유

  • Core 클래스인 Entity 클래스 보호
  • View Layer와 DB Layer의 역할 분리
  • 다양한 비즈니스 로직과 요구사항에 대한 유연한 대응
  • Controller와 Service 사이의 강한 의존 방지
  • 트랜잭션으로 처리되어야 하는 DTO 항목이 요청으로 들어온 결과값과 동일하지 않을 수 있다
    • 위의 그림과 같이 Controller가 받은 Web DTO와 Service가 받을 DTO가 다른 경우가 존재한다
    • 이러한 경우에 Service 레이어가 Controller 레이어 DTO에 의존하고 있으면 문제가 발생할 수 있기 떄문에 Service 레이어에 맞는 DTO가 필요하다

 

 

DTO를 불변 객체로?

  • setter를 없애고 final 키워드를 통해 오직 데이터를 가져올 수 만 있도록 수정하면 된다

🧧 VO

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

 

 

VO 특징

  • VO는 값 자체를 표현하기 때문에 불변객체여야 한다
  • 따라서 위처럼 setter 성격의 메서드는 포함해서는 안되고, 생성자를 통해서만 값을 초기화해야 한다
  • getter, setter 메서드 외의 로직을 포함할 수 없는 DTO와 달리, VO는 이외의 로직을 포함할 수 있다

 

 

 

 

💡 DTO vs VO

  • DTO는 인스턴스 개념이고, VO는 리터럴 값 개념이다
  • VO는 값들에 대해 read-only를 보장해줘야 존재의 신뢰성이 확보되지만, DTO의 경우는 단지 데이터를 담는 그릇의 역할일 뿐 값은 그저 전달되어야 할 대상일 뿐이다
  • 값 자체에 의미가 있는 VO와 전달될 데이터를 보존해야 하는 DTO의 특성상 개념이 다르다

 


🎛 Entity

  • domain package
  • 실제 DB와 매칭될 클래스로 가장 core한 클래스라고도 부른다
  • 최대한 외부에서 Entity 클래스의 getter 메소드를 사용하지 않도록 해당 클래스 안에서 필요한 로직 메서드를 구현한다
  • 단, Domain Logic만 가지고 있어야 하고 Presentation Logic을 가지고 있어서는 안된다
  • Entity는 DB의 테이블과 일대일로 대응되기 때문에 테이블이 갖지 않는 컬럼을 필드로 가져서는 안된다
  • 또한 Entity 클래스는 다른 클래스를 상속받거나 인터페이스의 구현체여서는 안된다

 

 

 

💡 DTO Class vs Entity Class

  • Entity 클래스는 데이터베이스와 매핑되어 있는 핵심 클래스이기 때문에 요청이나 응답 값을 전달하는 클래스로 사용하면 안된다
  • Entity 클래스를 기준으로 테이블이 생성되고 스키마가 변경된다
  • 만약 Entity 클래스를 데이터를 전달하는 클래스로 사용할 경우, View의 변경사항이 생길 때마다 맞춰서 변경해야 한다
  • 또한 수많은 서비스 클래스나 비즈니스 로직들이 Entity 기반으로 동작하기 때문에 Entity는 변경되면 안된다
  • 따라서 요청이나 응답 값을 전달하는 클래스로는 반드시 View에 변경에 따라 다른 클래스들에게 영향을 끼치지 않고 자유롭게 변경할 수 있는 DTO를 사용해야 한다
  • 또한 응답값으로 여러 테이블들을 조인한 결과값을 전달해야 할 경우가 빈번하기 때문에 Entity 클래스 만으로는 응답값을 표현하기 어렵다
  • 따라서 Entity 클래스와 뷰의 결과값을 전달해주는 DTO는 꼭 분리해서 사용해야 한다!

 

 

 


🧱 DAO

// JPA인 경우
public interface UserRepository extends JpaRepository<User, Long> {
	// 구현 로직 작성
    // 기본 CRUD method는 JPA가 제공한다
}
  • Data Access Object / repository package
  • 데이터베이스의 data에 접근하기 위한 객체로 Persistence Layer이다
  • Database에 접근하기 위한 로직과 비즈니스 로직을 분리하기 위해 사용한다
  • 쉽게 생각하면 Service와 DB를 연결하는 고리의 역할을 한다
  • DAO를 사용하는 이유는 효율적인 커넥션 관리와 보안성 때문이다
  • DB에 대한 접근을 DAO가 담당하도록 하여 데이터베이스 엑세스를 DAO에서만 하게 되면, 다수의 원격 호출을 통하 오버헤드를 VO나 DTO를 통해 줄일 수 있고 다수의 DB 호출문제를 해결할 수 있다
  • ex) 클라이언트가 데이터를 입력하여 DTO를 통해 전송한다 -> DTO를 받은 서버가 DAO를 통해 DB에 데이터를 넣는다
💡 Persistence Layer : DB에 data를 CRUD하는 계층

 

 


전체 구조로 보는 사용 위치

  • 우선 패키지 구조로 보면 위의 객체들은 위와 같은 위치에 놓으면 된다
  • dao - repository package
  • entity - domain package
  • vo - domain package
  • dto - dto package

 

 

 

DTO의 사용 범위

Layered Architecture

 

  • DB Layer에는 Entity, View Layer에는 DTO를 사용하여 역할을 분리한다
  • DB와 매핑되고 데이터의 CRUD에 대해 데이터를 관리하고 보관하는 Persistence Layer까지는 Entity를 사용하고, Service 영역에서부터 클라이언트 영역까지는 DTO를 사용한다
  • Service -> Controller 에서 Entity와 DTO 중 어떤 것을 사용하는 것이 더 좋을 지에 관해서는 많은 의견이 존재한다
  • 이는 시스템의 규모와 아키텍처 마다 어디까지 DTO와 Entity를 사용하는 것이 효율적인지 다르기 때문에 상황에 맞게 사용하는 것이 중요하다고 생각된다!

 

 

 

Entity <-> DTO 간 객체 변환

  • Entity와 DTO 간 객체 변환은 ModelMapper 라이브러리를 통해 변환이 가능하다
  • ModelMapper를 사용하여 변환하고, Entity에 없는 필드들은 직접 값을 넣어주는 방식으로 변환한다

 

사용 예시

/* ModelMapper를 통한 변환 */

ModelMapper modelMapper = new ModelMapper();

// 매핑 전략 설정
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

// 변환
final UserBasicInfoDto userBasicInfoDto = modelMapper.map(userEntity, UserBasicInfoDto.class);

 

실제 변환 작업은 DTO 내의 static 메서드를 생성하여 변환한다

  • Entity -> DTO = of()
  • DTO -> Entitty = toEntity()
/*DTO 변환 Example*/
public class SampleDto {
  
    private Long          id;
    private String        title;
    private String        interviewee;
    private String        company;
   ...

    // Entity -> DTO   
    public static SampleDto of(Sample sample) {
        return modelMapper.map(sample, SampleDto.class);
    }

    // Entity -> DTO (Page의 경우)
    public static Page<SampleDto> of(Page<Sample> sourcePage) {
        return sourcePage.map(SampleDto::of);
    }
}

 

DTO로 변환하는 내용은 DTO 내부의 of() 메서드에 모두 넣어두고 실제 사용은 아래와 같이 한다

Sample sample = sampleRepository.findById(id)
                                .orElseThrow(() -> new NotExistException("Sample", id));
// DTO로 변환하여 리턴
return SampleDto.of(sample);

 

Entity로의 변환은 static 메서드가 아닌 일반 메서드로 작성하여, 객체 자신의 값을 가지고 Entity를 생성하도록 한다

주로 요청 DTO에서는 toEntity() 메서드 (DTO->Entity) 를, 응답 메서드에는 of() 메서드 (Entity->DTO)를 갖게 된다

// DTO -> Entity
public Sample toEntity() {
    Sample.builder()
          .company(this.company)
          .description(this.description)
             ...
          .build();
    }
public void saveSample(SampleCreateRequest createRequest, Long managerId) {
    // DTO -> Entity
    Sample sample = createRequest.toEntity();

    sampleRepository.save(sample);
}

참고)

https://www.youtube.com/watch?v=z5fUkck_RZM 

https://melonicedlatte.com/2021/07/24/231500.html

 

DAO, DTO, VO 란? 간단한 개념 정리 - Easy is Perfect

 

melonicedlatte.com

https://studyandwrite.tistory.com/402

 

[스프링/Spring] DTO는 왜 써야 하나?

1. 고민? DTO(Data Transfer Object)란 계층간 데이터 교환을 위해 사용하는 객체(Java Beans)입니다. 아래 코드를 보면서 DTO는 왜 필요한가에 대해 생각해보겠습니다. * 실제 엔티티 설계의 일부입니다. 위

studyandwrite.tistory.com

https://dbbymoon.tistory.com/4

 

Entity to DTO, DTO to Entity 그리고 ModelMapper

Entity 클래스란 JPA에서 실제 데이터베이스의 테이블과 매칭되는 클래스입니다. JPA를 사용하면서 Entity 클래스를 작성하였고, 프로젝트 초기에는 Entity로 Repository 뿐만 아니라 Service, Controller 영역

dbbymoon.tistory.com

https://gmlwjd9405.github.io/2018/12/25/difference-dao-dto-entity.html

 

[DAO] DAO, DTO, Entity Class의 차이 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

https://velog.io/@aidenshin/DTO%EC%97%90-%EA%B4%80%ED%95%9C-%EA%B3%A0%EC%B0%B0

 

DTO에 관한 생각

과거 회사에서 DTO를 사용하지 않고 Entity로 통신을 주고 받는 경우가 있었다.. 결국 대참사가 벌어졌고 DTO를 도입하게 되었던적이 있다.대부분의 Entity 클래스들은 대부분 DB 테이블 스키마와 1:1

velog.io

https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/

 

DTO의 사용 범위에 대하여

1. DTO란? DTO(Data Transfer Object)란 계층간 데이터 교환을 위해 사용하는 객체(Java Beans)입니다. 간략하게 DTO의 구체적인 용례 및 필요성을 MVC 패턴을 통해 알아볼까요? 🚀 1.1. MVC 패턴 MVC…

tecoble.techcourse.co.kr

 

728x90

댓글