2 분 소요

메소드 호출 수를 줄이기 위해 프로세스 간에 데이터를 전송하는 객체
마틴 파울러, Data Transfer Object

객체는 가능한 작은 책임을 가질수록 유연해집니다. 하지만 프로세스 또는 네트워크 간의 통신에서는 객체가 작을수록 통신 횟수가 늘어 비용이 많이 들어갑니다. 통신 횟수를 줄이기 위해 더 큰 객체를 사용하여 작은 연산을 감출 수 있습니다.

DTO(Data Transfer Object)는 서로 다른 프로세스 간에 데이터를 전송할 때 사용되는 객체로, 여러 호출에서 전달되는 데이터를 통합하여 프로세스 간 통신 비용을 최소화합니다. 행위보다 속성이 중요하여 도메인 로직을 포함하지 않지만, 필요에 따라 직렬화와 역 직렬화 메커니즘이 추가될 수 있습니다.

DTO와 대량 접근 메소드를 활용하여 원격 파사드는 통신 횟수를 줄여 프로세스 간 통신 비용을 최소화합니다. 파사드는 도메인 연산을 가지고 있지 않고 도메인 연산을 감싸고 호출하는 최소한의 기능만을 가지고 있습니다.

초기의 J2EE(Java 2 Platform, Enterprise Edition)가 DTO를 VO(Value Object)로 명명하여 DTO는 종종 DDD(Domain Driven Design)에서의 VO와 혼동되기도 합니다. 하지만 VO와 DTO는 서로 다른 목적을 가지고 있습니다. VO는 도메인의 중요한 부분을 모델링하기 위해 사용되고 DTO는 효과적으로 데이터를 전송하기 위해 사용됩니다.

DDD에서 VO는 식별성을 가지고 있지 않고 도메인의 서술적인 측면을 나타내는 객체를 의미합니다. 도메인 모델의 중요한 속성과 의미를 표현하며 관련 로직을 가지고 있습니다. 동일한 속성을 가지고 있다면 어떤 것을 사용하는지는 중요하지 않으므로, 설계 단순화나 최적화를 위해 공유될 수 있습니다. 공유되는 데이터를 변경하는 데 있어 발생하는 문제를 방지하기 위해 주로 불변적으로 설계 됩니다.

DTO는 프로세스 간 통신에서 사용되는 것을 넘어 여러 모듈과 계층 간에 데이터를 전달하는 객체로 의미가 확장되어 사용되기도 합니다. 하지만 이러한 확장이 성공적으로 이루어진 것 같지는 않습니다.

여러 모듈과 계층 간 통신에 사용됨에 따라 경계에서 전달되는 객체에서 도메인 로직이 제거되어 데이터만 이동하게 되었고, 제거된 행위들은 경계면의 파사드에 응집되었습니다. 결과적으로 파사드는 도메인 연산을 감싸기만 하는 것을 넘어 중요한 도메인 연산을 스스로 수행하게 되어 거대한 행위자로 변형되었습니다. 이로 인해 중요한 도메인 지식은 경계를 넘어서지 못하고 경계 내에서만 소비되며, 행위자들 내에서 정제되지 않은 절차로만 존재하게 되었습니다.

물론 다른 컨텍스트에 속한 도메인 객체를 현재 컨텍스트에서 직접 사용하는 것은 바람직하지 않습니다. 명확한 윤곽 없이 다른 컨텍스트를 연결하게 되면 그 경계가 모호해지고 지식이 섞이게 되어 거대하고 복잡한 객체가 만들어지게 됩니다. 다른 컨텍스트에 속한 모델은 번역을 통해 현재 컨텍스트에 맞게 조정되어야 합니다. 이 프로세스는 일반적으로 단방향으로 이루어지며 고객-공급자 관계를 형성합니다.

이 손상 방지 계층(Anti-Corruption Layer)은 컨텍스트 경계에 있으며 두 컨텍스트가 주의 깊게 관리해야 하지만, 고객의 요구에 따라 생성되므로 고객이 관리 책임을 지고 있어야 합니다. 계층화 아키텍처에서는 상위 계층이 하위 계층을 번역하는 책임을 가집니다. 하위 계층의 도메인 모델은 경계를 넘어 상위 계층에 도착하고 손상 방지 계층을 통하여 상위 계층의 언어로 번역됩니다.

불행히도, 손상 방지 계층이 공급자와 동일한 위치에 있는 경우가 많습니다. 공급자와 손상 방지 계층이 동일한 곳에 위치하면 경계 외부의 고객의 요구사항을 수용하면서 도메인 지식이 역류될 가능성이 높습니다. 고객의 요구사항이 변화하면 경계 내부의 객체 또한 변화되고 서로의 도메인 지식을 알게 되어 순환 참조가 만들어져 결합이 강화될 수 있습니다.

프로세스 간의 통신에서 호출 수를 줄이기 위해 DTO를 사용하는 것이 좋습니다. 프로세스 간의 통신에서는 전송될 데이터의 속성과 형태가 중요한 부분을 차지하여 데이터만 존재하는 객체를 사용하는 것이 자연스럽습니다. 외부 클라이언트와 통신하는 표현 계층이나 데이터베이스와 통신하는 영속성 계층에서 사용될 수 있습니다.

하지만 모듈과 계층 간의 통신에서는 행위가 중요한 부분을 차지합니다. 행위 없이 속성만 경계를 넘어 전달되게 되면 도메인 지식이 전파되기 어렵습니다. 원하는 연산을 수행하기 위해 단일 고객에게 과하게 맞추어진 행위자가 공급자에 형성이 됩니다. 세부적인 도메인 지식이 고객에서 공급자로 역류하게 되고 관심사가 섞여 복잡도가 늘어나게 됩니다. 경계를 명확하게 하고 도메인을 효과적으로 표현하기 위해 손상 방지 계층을 활용하여 도메인 모델을 변역할 수 있습니다.

참고 자료

댓글남기기