용로그
article thumbnail

우테코 1레벨 마지막 미션인 체스를 진행하면서 배운 DTO에 대해서 글을 써보려 합니다. 리뷰어와 약 하루동안 16,000자의 대화가 오갔으며, 이번 글에서는 이를 기반으로 토론한 내용을 기반으로 작성합니다.

 

그리고 체스라는 게임의 룰을 이해한 상태로 글을 읽으면 이해가 더 잘될 것 같습니다. 😁 😁

사건의 발단


체스라는 게임은 각 기물마다 다른 움직임 전략을 가지고 있습니다. 이를 객체지향으로 구현하는 방법은 여러가지가 있을 것입니다. 가장 대표적인 방법은 상속을 사용하는 방법일텐데요.

 

이는 하나의 Piece 부모 객체를 가지고 나머지 기물들이 Piece를 상속(Inheritance)받아 자신의 전략에 알맞은 전략을 따로 구현하는 방법입니다.  그리고 다른 방법으로는 전략 패턴(Strategy Pattern)이 있을 것 같습니다.

 

전략 패턴을 구현하는 방법은 여러가지가 있을테지만, 그 중 대중적인 방법인 Interface를 구현해 각 기물마다 다른 전략을 구현하도록 하는 방법을 채택했습니다. 

 

 

그런데 리뷰어에게 이러한 리뷰가 왔습니다.

 

 

Domain To Domain인 경우 DTO가 필요한 이유는 무엇인가?


Strategy가 DTO를 아는게 좋은걸까요? 현재 Strategy에서 기물들의 움직임 전략을 파악하기 위해서는 다음과 같은 정보들을 필요로 합니다.

 

  • 모든 기물들의 위치(List<Position> positions)
  • 움직일 기물의 색상(Color color)
  • 움직일 기물의 현재 위치(Position movablePosition)
  • 움직일 기물의 이동할 위치(Position targetPosition)

 

이렇게 많은 정보를 파라미터에 직접적으로 넘겨준다면, 객체간의 강결합이 생기며 연쇄적으로 서로를 직접적으로 알 필요가 없는 도메인에서 다른 도메인의 변경의 여지가 생깁니다.

 

따라서 총 4개의 파라미터를 DTO를 사용해 전달한다면 위와 같은 문제점을 해결할 수 있는 좋은 방안이라고 생각할 수 있습니다. 이 때 리뷰어가 남긴 3가지 질문은 다음과 같습니다.

 

Q. 도메인끼리 현재 상태를 반환하려할 때, DTO를 만들어야 하는가?

A. 현재 상태를 반환하려고 할 때 새로운 객체를 만들어 방어적 복사를 하는 방법도 생각해봤는데, 현재 HashCode&Equals를 재정의 한 상태여서 어려울 수 있다는 판단을 내렸습니다.

Q. 도메인을 DTO로 묶는다고 도메인을 모르는게 되는가?

A. 도메인을 DTO로 묶으면 도메인을 모르게 되는 것은 아니지만 도메인에 대해서 최소한으로 알 수 있다고 생각합니다. 예를 들면 PersonDto가 Name을 가져야한다면 Name 도메인 그 자체를 프로퍼티로 가지는 대신 Name 값만을 가진 NameDto를 가지게 하면 될 것 같습니다.

Q. 도메인을 DTO로 묶었을 때 장점은 무엇이 있는가?

A. 도메인끼리 DTO를 묶었을 때의 장점은 여러 곳에서 같은 도메인들의 데이터를 필요로할 때 코드의 중복성을 줄일 수 있다는 것이 가장 큰 장점인 것 같습니다. (현재의 Strategy와 같은 상황)

 

위의 질답이 필자가 왜 Domain To Domain의 관계에서 DTO를 사용했는지 근거가 될 수 있을거라 생각합니다.

 

DTO에 대한 정확한 정의는 무엇인가?


DTO의 정확한 정의가 무엇일까요? 단순 Data Transfer Object라고 해서 데이터를 전달/변환하는 용도로만 사용하면 올바르게 사용한걸까요?

 

필자가 위에서 사용한 근거에 따르면 다음과 같은 생각으로 DTO를 사용했는데요.

 

DTO에 대한 정확한 정의는 무엇일까요? 어느 부분에서 사용되는 걸까요?

Q. DTO와 VO의 차이에 대해서 알려주세요.

리뷰어가 위의 질문을 던지데에는 단지 다른 도메인의 값을 필요로 하는 도메인에 데이터만 전달해주기 위함인데, 왜 VO 대신 DTO를 사용했는지를 물어보신 것 같습니다.

 

 

Q. DTO는 어디서 어디로 전달해주기 위한 객체인가?

A. 원래는 Domain이 관여하지 않는 레이어인 Controller에서 DTO를 만들어주어야 한다고 생각합니다. 그런데 현재 도메인에서 DTO를 생성해서 도메인으로 넘겨주는 상황입니다.

 

 

근데 뭔가 이상한 부분이 있습니다. 과연 레이어와 도메인 간의 데이터 전송만을 위한 객체일까요? DTO의 특징으로는 레이어 간의 데이터 변환이 특징입니다. 그래서 3번 답변은 틀린 답변이 되고 말았습니다.

 

해당 질문까지가 Domain To Domain 관계에서 DTO를 사용하는 것이 좋은 접근일까에 관한 대화 주제였습니다. 하지만 아직 궁금증이 남았죠.

 

 

그럼 이 녀석은 뭐라고 부르고 정의하는게 맞을까요? ((Position과 Color를 DTO로 감싸지 않은 부분은 추후 리팩토링 예정이니 너무 신경쓰지 말아주세요 ㅎㅎ..

 

Q. 비즈니스 로직이 포함되지 않고 객체의 데이터 자체만 가지고 있어도 VO라고 칭해도 문제 없을까요? 

 

개인적으로 VO를 만드는 것에 대해서는 값만 같으면 같은 객체로 판단하게 되어서 오히려 강결합이 될 수도 있을 것 같다는 생각이 듭니다. VO 자체도 DTO와 마찬가지로 만들어진 의도를 생각해보면 좋을 것 같습니다.

 

그럼 느슨한 결합을 위해 어떻게 해결할 수 있어?


리뷰어가 제안한 느슨한 결합을 위한 해결 방안

 

애초에 DTO가 도메인 관계에서는 필요하지도 않고 VO를 사용하더라도 강결합이 유지될 것 같다고 생각했습니다. 도메인끼리 파라미터로 객체를 받지 않으려고 DTO나 VO를 만들어 사용하는 것은 조금은 무모할 수도 있겠다고 생각이 들기 시작했죠.
 
가장 좋은 방법은 도메인의 역할과 책임을 확실하게 분리하고 가능한 작은 단위로 구분하는 것이 느스한 결합을 만드는 데에 좋다고 생각합니다.
profile

용로그

@용로그

벨덩보단 용덩 github.com/wonyongChoi05