본문 바로가기
프로그래밍/기타

DTO란 무엇인가, VO와의 비교

by 카프카뮈 2021. 2. 16.

오늘은 다음의 고민 때문에 글을 작성하게 되었다.

  • DTO가 정확히 뭘 의미하는 거지?
  • DTO를 꼭 써야하는 이유가 뭐지?
  • DTO랑 VO를 많이 비교하던데, 뭐가 다른거지?

DTO란 무엇인가

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

이해를 위해, "리팩토링"의 저자로 유명한 마틴 파울러가 DTO에 대해 어떻게 정의했는지 참고해 보자.

 

P of EAA: Data Transfer Object

| P of EAA Catalog | Data Transfer Object An object that carries data between processes in order to reduce the number of method calls. For a full description see P of EAA page 401 When you're working with a remote interface, such as Remote Facade (388), ea

martinfowler.com

위의 본문 중 필요한 내용을 간단히 요약해 보았다.

우리가 원격 인터페이스로 작업을 할 때, 호출에 따른 비용은 매우 비싸다.
그렇기 때문에 우리는 요청의 횟수를 줄여야 하고, 이를 위해 한번의 요청에 더 많은 데이터를 전송해야 한다.

우리는 이를 수행하기 위해 많은 매개변수를 사용할 수 있다.
그러나 이것은 프로그래밍하기 어려운 방법일 뿐더러,
JAVA에서는 반환값으로 여러 개의 값을 받을 수 없으므로 더욱 불가능한 일이라 할 수 있다.

그렇기 때문에, 우리는 요청에 대한 모든 데이터를 보관할 수 있는 데이터 전송 객체, DTO를 만들어 사용한다.

또한 로버트 C.마틴은 그의 저서 "클린 코드"에서, DTO에 대해 다음과 같이 설명한다.

자료 구조체의 전형적인 형태는 공개 변수만 있고 함수가 없는 클래스이다.
이러한 자료 구조체를 때로는 자료 전달 객체(DTO)라고 한다.
DTO는 굉장히 유용한 구조체다.
특히 데이터베이스와 통신하거나 소켓에서 받은 메시지의 구문을 분석할 때 유용하다.

클린 코드: 애자일 소프트웨어 장인 정신, 인사이트, 로버트 C.마틴. 126-127 인용

 

이를 통해 우리는 다음을 알 수 있다.

  • 외부와 통신하는 프로그램에게 있어 호출은 큰 비용이며, 이를 줄이고 더욱 효율적으로 값을 전달할 필요가 있다.
  • 이를 위해 데이터를 모아 한번에 전달하는 방법이 고안되었다. 이때 이 클래스를 DTO라고 한다.

DTO를 써야만 하는 이유

우리는 왜 DTO를 써야 할까?

제일 간단한 이유는 위에서 이미 설명했다. DTO를 쓰지 않으면, 통신의 횟수가 증가할 뿐 아니라 로직이 비효율적이 되기 때문이다.

 

예를 들어, 우리가 도서 관리 앱의 서버를 만들었다고 가정해 보자.

이 때, 사용자가 새 책을 추가하려고 한다.

새 책에는 다음과 같은 정보가 들어간다.

  • 책의 이름
  • 책의 가격
  • 책의 저자

이 때, DTO 없이 생성 로직을 짠다고 상상해 보자.

  • 먼저, 책의 이름을 요청으로 보낸다. 서버는 이를 따로 저장해 둔다. 또한 잘못된 이름인지도 검증해 본다.
  • 이어서, 책의 가격을 보낸다. 서버는 이 가격이 앞서 보낸 책의 가격인지(어떤 방법으로든) 검증을 하고, 가격이 잘못되었는지도 검증한다.
  • 마지막으로, 책의 저자를 보낸다. 서버는 이 저자가 앞서 받은 가격/이름과 짝인지 검증하고, 또한 저자명이 올바른지 검증하며, 종합적으로 모든 것이 올바를 때에 한하여 책을 생성한다.
  • 물론, 이 과정에서 데이터 요청이 하나 빠지거나, 순서가 틀어지거나, 잘못된 값이 전달되어 검증을 통과하지 못하면 처음부터 다시 해야한다.

생각만 해도 끔찍하지 않은가? 물론 이는 좀 과장된 내용이다.

그래도 우리는, 이런 과정을 상상하며 다음을 생각할 수 있다.

  • 데이터를 묶어서 하나의 요청으로 보내면 검증과 로직 처리 역시 한 번에 할 수 있어 편하겠다!
  • 데이터를 묶어서 하나의 요청으로 보내면 하지 않아도 될 고민을, 따로 보낼땐 다 해줘야 해서 불편하겠다!
  • 안정성과 수행시간 모두 묶어 보내는 쪽이 유리하겠다!

물론 이런 단순한 이유만 있는 것은 아니다.

앞서의 DTO에 대한 포스팅에서 마틴 파울러는, 다른 이유 하나를 제시한다.

(...) 또 다른 이점은, 데이터를 전송하기 위한 직렬화 메커니즘을 캡슐화하는 것이다.
이와 같이 직렬화를 캡슐화함으로써, DTO는 이 로직을 코드에서 제외하고,
원하는 경우 직렬화를 변경할 수 있는 명확한 지점을 제공한다.

만약 앞서 이야기했듯 통신을 통해 값이 서버에 전달된다고 하자.

전달된 값을 서버에서 사용하는 값으로 바꾸기 위해, 우리는 직렬화(serialization)를 거쳐야 한다.

그런데, 원시값의 경우 직렬화 로직을 내부에 가지기 어려우므로,

통신을 담당하는 컨트롤러 레이어에서 직렬화에 대한 코드를 가져야 한다.

 

이 코드는 컨트롤러마다 있어야 하니 관리하기도 어렵고,

또한 수정하려고 할 때 정확히 어디를 수정해야 할 지 알기도 어렵다.

그러나 객체로 정리된 DTO의 경우, 직렬화 로직을 내부에 캡슐화하여 가지고 있을 수 있다.

이 경우 책임도 명확하고 코드를 수정하기도 편할 것이다.


그리고 마지막으로 DTO를 써야 하는 이유는, Entity가 아닌 DTO를 전달함으로써 각 레이어 간 역할을 분리할 수 있기 때문이다.

이에 대해서는 최근에 쓴 포스팅을 첨부한다.

 

Controller에서 Service에 값을 어떻게 전달할까?

바로 직전에, 스프링 부트에서 MVC 패턴을 구현하는 방법에 대해 간단한 글을 올렸다. 고민: SpringBoot에서의 MVC 패턴 이 글은 다음의 고민에서 시작한 글이다. 내가 스프링 부트로 지금까지 만든

kafcamus.tistory.com


참고로, 스프링 부트에서는 기본 탑재된 spring-boot-starter-web의 Jackson 라이브러리가 직렬화를 담당한다.

이 때 Jackson은 객체와 JSON 데이터의 상호 변환을 담당하는 라이브러리이다.


VO와 DTO

DTO에 대해 검색해보면 제일 많이 나오는 질문이, "VO와 DTO는 뭐가 다른가요?" 이다.

 

먼저, VO가 무엇인지 설명해 보자.

다행히 마틴 파울러는, VO에 대해서도 저서의 내용을 포스팅해 두었다.

 

P of EAA: Value Object

| P of EAA Catalog | Value Object A small simple object, like money or a date range, whose equality isn't based on identity. For a full description see P of EAA page 486 With object systems of various kinds, I've found it useful to distinguish between refe

www.martinfowler.com

VO(Value Object)는 작고 간단한 객체로, 돈이나 날짜처럼 같은 값임을 검증할 수 있는 객체를 이야기한다.

일단 VO의 중요한 특징은 다음과 같다.

  • 값이 불변한다. 즉 값을 설정한 뒤에는 수정할 수 없다.
  • 값이 같다면 동일성을 보장한다. 그래서 equals & Hash code 메서드를 재정의해야 하낟.

이를 통해, 우리는 DTO와 VO의 차이를 알 수 있다.

  • DTO는 내부의 값이 모두 같은 두 객체가 존재해도 서로 동일하다고 판단하지 않는다.
  • DTO는 (좋은 일은 아니지만) 값을 수정할 수 있다.

그렇다면 왜 사람들은 DTO와 VO를 혼동할까?

마틴 파울러는 앞서의 DTO에 대한 설명에서도 이 둘을 사람들이 혼동한다는 것을 지적한다.

또한, 자신이 명칭을 혼용하여 개발자 커뮤니티에 큰 혼란이 있었다는 것을 언급한다.

Name Collisions
I’ve seen the term Value Object used for this pattern for quite some time.
Sadly recently I’ve seen the J2EE community [Alur et al.] use the term “value object” to mean Data Transfer Object (401),
which has caused a storm in the teacup of the patterns community.

실제 개발해보는 입장에서, 둘을 혼용하는 이유에 대해서는 공감할 수 있었다.

DTO는 Entity처럼 상태가 바뀌기보다는 값을 전달하는 데에 주 목적이 있고,

그렇기 때문에 "불변의 값을 전달할 때 사용되는" VO와 혼동된 것이라고 생각된다.


마지막으로, VO에 대해 더 알고싶다면 이 링크를 추천한다.

https://woowacourse.github.io/javable/post/2020-06-11-value-object/

 

VO(Value Ojbect)란 무엇일까?

프로그래밍을 하다 보면 VO라는 이야기를 종종 듣게 된다. VO와 함께 언급되는 개념으로는 Entity, DTO등이 있다. 그리고 더 나아가서는 도메인 주도 설계까지도 함께 언급된다. 이 글에서는 우선 다

woowacourse.github.io

우아한테크코스를 함께 했던 멋진 크루의 좋은 글!!

VO의 원리에 대해 잘 정리하고 있다.


간단한 호기심을 충족하려고 쓴 글이었는데,

오히려 머리만 아파진 느낌이다.

덕지덕지 발라둔 글이지만 그래도 누군가의 호기심을 푸는 데 도움이 되기를 바란다.

 

잘못된 내용이 있다면 지적 부탁드립니다.

반응형

댓글