개요

스프링으로 백엔드를 포팅하는 과정에서, DDD에서 주로 쓰이는 VO와 기존에 쓰던 DTO의 차이, 그리고 DAO와 Repository같이 상당히 유사한 기능을 함에도 이름이 다르고 용처가 다른 것들에 대해서 그 이유가 무엇인지 궁금해졌고, 이에 대해 알아보려고 한다.

DTO?

DTO(Data Transfer Object)란, 프로세스 간에 데이터를 전달하는 객체다.

현재 웹 서비스에서는 주로 계층들, 특히 컨트롤러 - 서비스(표현 - 도메인) 단계에서 서로 주고 받는 데이터 양식이다. 주클라이언트에서 서버 쪽으로 전송하는 요청 데이터, 서버에서 클라이언트 쪽으로 전송하는 응답 데이터 형식으로 데이터가 전송된다. (Request && Response)

마틴 파울러의 정의에 따르면, 서비스 계층이란 어플리케이션의 비즈니스 로직 즉, 도메인을 보호하는 계층이다. 즉, 이 정의를 명확히 지키기 위해서는 응용 계층(컨트롤러)에 도메인을 노출해서는 안된다. 따라서 도메인은 서비스 계층에서 DTO로 변환되어 컨트롤러로 전달되어야 한다.

DTO는 전송해야 하는 데이터를 담는 컨테이너 역할을 하며, 한 계층에서 다른 계층으로 데이터를 매핑하는 역할을 담당한다. 이를 통해 계층 간의 결합을 줄이고 애플리케이션의 성능과 유지보수성을 개선할 수 있다. DTO는 어떠한 비즈니스 로직을 가져서는 안 되며, 저장, 검색, 직렬화, 역직렬화 로직만을 가져야 한다.

여러 호출에서 전송할 수 있는 데이터를 집계하지만 한 번의 호출로만 제공되는 객체(DTO)를 사용하면 비용을 줄일 수 있다. 또한, 필요한 정보들로만 래핑하기 때문에, 불필요한 정보들을 제공하지 않게끔 할 수 있다 - 데이터를 캡슐화 할 수 있다.

Untitled

왼쪽의 HTML, Json ↔ UserDTO에서 데이터의 변환과정이 직렬화(DTO → HTML, JSON)와 역직렬화(HTML, JSON → DTO)다. 위 사진에서 중요한 것은 Mapper다. DTO Mapper는 데이터 전송 객체(DTO)와 도메인 객체(Domain) 간의 매핑을 담당하는 일종의 변환기다.

위 사진을 아래와 같은 예시로 생각해보자.

public class User {
  private Long id;
  private Roles role;
  private String email;
  
  // 생성자, getter && setter
}

public class UserDTO {
  private Long id;
  private Roles role;
  
    // 생성자, getter && setter
} 

위 방식으로 DTO를 설정한다면, 우리는 ‘email’이라는 데이터를 캡슐화 한 것이다. DTO는 getter와 setter를 가지므로, Mapper를 다음과 같이 작성해볼 수 있다.

public class UserMapper {
  public static UserDTO toUserDTO(User user) {
    UserDTO userDTO = new UserDTO();
    userDTO.setId(user.getId());
    userDTO.setName(user.getName());
    return userDTO;
  }
  
  public static User toUser(UserDTO userDTO) {
    User user = new User();
    user.setId(userDTO.getId());
    user.setName(userDTO.getName());
    return user;
  }
}

DAO?

DAO(Data Access Object)란, 영속성(Persistence) 계층에 인터페이스를 제공하는 패턴이다. DAO는 애플리케이션 호출을 영속성 계층에 매핑함으로써 DB 세부 정보를 노출하지 않고 데이터에 접근하게 해준다. 이러한 분리방식은 단일 책임 원칙(SRP)을 지킬 수 있게 해준다.

DAO 사용의 가장 큰 장점은 서로에 대해 알 필요가 없는 두 계층을 엄격하게 분리할 수 있다는 점이다. 비즈니스 로직은 지속적으로 DAO 인터페이스에 의존할 수 있으며, 이에 따라 영속성 로직 변경은 DAO를 사용하는 계층에 영향을 미치지 않는다.