개발을 하다가 굳이 domain과 DTO를 왜 같이 써야할까?라는 의문점이 생겼다. 내가 배운 DTO는 client와 controller, controller와 service 사이의 객체 전달을 위해 사용하는 것이라 생각했는데 굳이 객체 전달을 위해서라면 그냥 domain을 가져다가 써도 된다고 생각했다.
DTO(Data Transfer Object)란 계층간 데이터 교환을 위해 사용하는 객체이다. DTO는 클라이언트 요청에 포함된 데이터를 담아 서버 측에 전달하고, 서버 측의 응답 데이터를 담아 클라이언트에 전달하는 계층간 전달자 역할을 한다.
도메인 객체를 View에 직접 전달할 수 있지만, 민감한 도메인 비즈니스 기능이 노출될 수 있으며 Model과 View 사이에 의존성이 생기게 된다.
public class User {
public Long id;
public String name;
public String email;
public String password; //외부에 노출되서는 안 될 정보
public DetailInformation detailInformation; //외부에 노출되서는 안 될 정보
//비즈니스 로직, getter, setter 등 생략
}
@GetMapping
public ResponseEntity<User> showArticle(@PathVariable long id) {
User user = userService.findById(id);
return ResponseEntity.ok().body(user);
}
public class UserDto {
public final long id;
public final String name;
public final String email;
//생성자 생략
public static UserDto from(User user) {
return new UserDto(user.getId(), user.getName(), user.getEmail());
}
}
@GetMapping
public ResponseEntity<UserDto> showArticle(@PathVariable long id) {
User user = userService.findById(id);
return ResponseEntity.ok().body(UserDto.from(user));
}
DTO를 사용하게 된다면 Model을 캡슐화 하고, 사용하는 데이터만 선택적으로 보낼 수 있게된다. 따라서 DTO는 클라이언트 요청에 포함된 데이터를 담아 서버 측에 전달을 하고, 서버 측은 응답 데이터를 DTO에 담아 클라이언트에게 전달하는 전달자 역할을 한다.
Controller와 Clinet 사이에서 DTO를 사용하는 것이 좋은 것인가 Service와 Controller 사이에서 DTO를 사용하는 것이 좋은 사용방법인가? 또한 Repository와 Controller 사이에서는 DTO를 사용하지 않는 것이 옳은 방법인가? 여러 글을 읽고 지금까지의 내가 생각하는 좋은 경우는 Service 단에서 DTO로 변환하여 사용하는 것이 좋다고 생각했다.
Controller에서 DTO를 domain으로 변환하고 이를 Service에 전달한다. Service는 로직을 처리하고 domain을 contoller에 반환하여 controller는 이 domain을 DTO로 다시 변환하여 client에 전달한다. 이 과정에서 생기는 문제점은 무엇일까?
Controller가 View로부터 받은 DTO를 Entity로 변환한 뒤, Service 레이어가 Entity를 전달받아 일련의 비즈니스 로직을 수행한다고 가정한다면 Controller가 View에서만 전달받은 DTO만으로 Entity를 구성하기란 어렵다. 따라서 Repository를 통해 여러 부수적인 정보들을 조회하여 Domain 객체를 구성할 수 있는 경우도 존재한다.
Repository 레이어는 entity의 영속성을 관장하는 역할이라고 한다. 이로 인해, 표현 계층에서 사용할 도메인 계층의 Aggregates를 DTO로 변환하는 작업을 Repository 단에서 책임지게 하는 것을 지양하자는 의견이 다수 존재한다.
Service 단에서 DTO-Entity 변환을 사용하는 것이 타당하다는 글이 많았다. 그러나 답은 정해진 것이 없고 프로젝트의 크기, 역할 등을 고려하여 사용하는 것이 가장 좋다고 생각된다.
-reference-