Dto는 어느 레이어까지 사용하는 것이 맞을까?
컨트롤러, 서비스, 레포지토리 레이어로 나누어진 스프링 웹 애플리케이션에서 컨트롤러의 DTO는 어느 레이어까지 전달하는 것이 좋을까?
레이어드 아키텍처?
먼저 레이어드 아키텍처의 목적에 대해서 생각해봤다. 레이어드 아키텍쳐는 복잡한 소프트웨어를 여러개의 레이어로 나누어 모듈화하는 것이다. 이렇게 하면 각 설계 요소가 분리되면서 유지 보수성이 높아진다. (이러한 이유로 크고 복잡한 네트워크도 TCP/IP라는 프로토콜 스택으로 계층화돼있다.) 계층화의 핵심은 한 계층의 모든 요소는 오직 같은 계층에 존재하는 다른 요소 또는 계층상 아래에 위치한 요소에만 의존하는 것이다. 어떤 계층의 상위 계층에 대한 의존, 결합은 최소화 해야한다. 그래야 모듈화의 이점을 볼 수 있다.
DTO는 어디까지 전달하는게 좋을까?
앞서말한 레이어드 아키텍쳐의 장점 때문에 스프링 웹 프로젝트에서 레이어드 아키텍쳐를 적용해봤다. 프론트(뷰)에서 보낸 json 형태의 데이터를 @ResponseBody를 사용해 DTO 객체로 변환하여 컨트롤러에 전달하고, 이 DTO를 그대로 서비스 레이어에 전달해서 비지니스 로직을 구현했다. DTO의 목적은 “계층간 데이터 전달”이므로, 그래도 된다고 생각했었다.
하지만 이렇게 할 경우 문제가 생긴다. 뷰 - 컨트롤러 - 서비스에서 각각 의존이 발생한다. 만약 나중에 기능을 변경해야할 경우 뷰, 컨트롤러, 서비스를 모두 연쇄적으로 수정 해야하는 상황이 발생할 수 있다. 모듈화의 이점을 보려고 레이어드 아키텍쳐를 적용한 것인데, 각 개발 요소에서 종속이 발생하고 있었다. 레이어드 아키텍쳐를 잘못 적용했다고 생각했다.
그래서 내린 내 수준에서의 작은 결론은 "컨트롤러 메서드에서 DTO를 도메인 객체로 변환한 후 서비스 레이어로 넘겨준다."
이다. 이렇게 하면 뷰에서 컨트롤러까지 의존하고 있던 서비스를 분리할 수 있다. 즉, 컨트롤러가 뷰로부터 어떤 DTO 형태로 데이터를 전달받더라도 서비스는 상관 없어진다. 더 이상 컨트롤러의 DTO를 사용하지 않고 도메인에 의존하기 때문이다. 이렇게 하면 여러 종류의 컨트롤러에서 서비스를 사용할 수도 있다.
아래 코드를 참고해보자
@Controller
class PostRestController {
//...
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public PostDto createPost(@RequestBody PostDto postDto) {
Post post = convertToEntity(postDto);
Post postCreated = postService.createPost(post));
return convertToDto(postCreated);
}
@GetMapping(value = "/{id}")
@ResponseBody
public PostDto getPost(@PathVariable("id") Long id) {
return convertToDto(postService.getPostById(id));
}
@PutMapping(value = "/{id}")
@ResponseStatus(HttpStatus.OK)
public void updatePost(@RequestBody PostDto postDto) {
Post post = convertToEntity(postDto);
postService.updatePost(post);
}
}
// 출처 : https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application
여러 자료를 참고해보니 정답이 없는 문제라고 느꼈다. 지금은 여기까지만 고민하도록 하고 나중에 다시 고민해봐야겠다.
참고
- https://www.slipp.net/questions/93
- https://www.slipp.net/questions/23
- https://os94.tistory.com/157
- https://wikibook.co.kr/article/layered-architecture/
- https://wikibook.co.kr/article/layered-architecture/
- https://velog.io/@ljinsk3/About-DTO-Data-Transfer-Object