DTO(DataTransferObject)는 아주 간단하면서도 인기있는 패턴입니다.
개발자라면 누구나 쓰고 있을 겁니다. 

Martin Fowler는 DTO 패턴을 다음과 같이 설명합니다.

An object that carries data between processes in order to reduce the number of method calls.




내용은 아주 간단합니다.
분산 환경에서는 한번의 호출에 많은 비용이 들기 때문에 호출 횟수를 줄이는 것이 중요합니다. 따라서 한번의 호출로 해당하는 데이터를 모두 가져와야 합니다. DTO를 사용하면 호출 시에 파라미터가 많아지는 것을 방지할 수 있으며 하나의 Return Value만을 허용하는 언어에서는 한번에 모든 데이터를 가져올 수 있습니다.

즉, 위의 그림처럼 Album title과 Artist name을 각각 호출해서 데이터를 가져오지 않고 AlbumDTO로 그 내용을 Wrapping 하여 한번의 호출로 데이터를 가져오거나 전송하는 패턴입니다.

.NET 개발자라면 누구나 무심코 DataTable을 이용하여 DTO를 사용합니다. 자바 개발자라면 ResultSet을 사용하여 DTO를 사용합니다. 이것을 저는 Common DTO라고 부르고 있습니다. (적당한 용어를 찾지 못했기 때문에)
어쨌든 보통은 SQL query로부터 생성되며 수많은 컨트롤과의 Data Binding이 쉽다는 장점 때문에 흔하게 사용합니다만 단점도 있습니다.
그 단점 중 하나는 DTO로부터 다시 Object와의 매핑을 하지 않을 경우 getter 혹은 setter 에 접근하기 위해서는 문자열로 이루어진 key를 통해 계속적으로 접근해야 한다는 것입니다. 
이것이 매우 유연하다는 장점이 있는 반면 잘못된 key에도 컴파일 시 에러를 내지 않는 단점이 있습니다. 또한, IntelliSense 기능을 제공하지 않기 때문에 로직 자체에서 ORM 변환 없이 빈번하게 접근해야할 경우 매우 불편할 뿐만 아니라 형변환으로 인한 Boxing과 Unboxing이 빈번하게 일어날 확률이 높습니다.
그 외에도 getter 시 'yyyyMMdd'와 같이 날짜로 표현된 문자열을 DateTime 형식으로 변환하여 돌려주고 싶을 경우 Common DTO를 사용하기엔 많은 제약이 따르며 setter 시 Validation 체크하기도 쉽지 않지요.

따라서, 저는 DTO를 직접 정의하여 DTO Assembler를 통해(이름과 다른 일을 하게 되버린) Common DTO로부터 한번 더 변환하도록 만드는 경우가 많습니다. 위의 그림처럼 AlbumDTO를 만드는 것이죠. 이것을 저는 Proprietary DTO라고 부릅니다.
특히나 저는 Utility 클래스를 통해 데이터를 여러 형태로 변환할 수 있도록 DTO를 만들곤 하는데 이 경우 유용합니다. 또한 IntelliSense 기능을 제공하여 DTO에 접근할 경우 매우 편하게 접근할 수 있으며 Boxing, Unboxing도 일어나지 않습니다.
그러나 현재 ORM Tool을 사용하지 않기 때문에 일일이 DTO를 만들어주는게 꽤 귀찮은 일입니다. 그래서 단순 조회하며 데이터를 변환할 필요가 없는 경우에는 Common DTO를 사용하여 View 컨트롤에 데이터를 바로 바인딩시켜 버립니다. 

이처럼 두 가지 DTO는 각각 장단점이 있기 때문에 항상 고민을 많이 하게 됩니다.
개발 초기에는 Common DTO만을 사용해도 될 것으로 생각했는데 나중에는 그 필요성이 증가하여 모두 변경해야될 경우가 많기 때문에 조심스럽습니다.


그렇게 고민만 하고 결론을 내리지 못하는 나를 볼 때마다 평범한 개발자로 살아가는 것이 참 어렵다는 생각을 합니다.
Posted by eritaka
TAG