1 분 소요

사용자 인터페이스에서 데이터를 쉽게 추출하기 위해, 도메인 모델은 종종 도메인 또는 비즈니스 로직을 포함하지 않고 데이터를 전달하는 구조체의 형태를 취합니다.

도메인 모델은 비즈니스 지식을 충분히 표현하지 못하고, 누락된 로직은 ‘서비스’라는 행위자에게 집중됩니다. 이로 인해, 비즈니스 로직을 포함하지 않고 단지 데이터 이동 수단이 된 객체는 사용자 인터페이스부터 인프라 계층까지 오가며, 각 계층에 위치한 행위자들에 의해 가공되는 모습을 보입니다.

결국 이러한 데이터 중심 아키텍처에서는 도메인 지식이 충분히 탐구되고 응집되지 못하여 전체를 아우르는 개념으로 발전하지 못하고 단순히 절차적으로 나열됩니다. 새로운 기능이 추가되거나 기존 기능이 변경될 때 많은 수정이 필요하게 되며, 이로 인해 점점 비용이 증가하여 기민한 대응이 어려워집니다.

도메인 모델이 비즈니스 지식을 제대로 표현하려면 명확한 관심사의 분리가 필요합니다. 도메인 모델은 사용자 인터페이스 계층과 인프라 계층 사이에서 단순히 데이터 전달 객체로 활용되는 것을 넘어, 도메인에서 나타나는 개념을 효과적으로 표현할 수 있어야 합니다.

사용자 인터페이스 모델과 도메인 모델이 직접 연결되면, 두 모델 간의 변환이 필요해집니다. 이로 인해 두 모델은 서로 강하게 결합되어 각자의 관심사를 표현하기 어려워집니다.

대신, 데이터 처리를 위한 모델과 비즈니스 로직을 가지고 있는 모델을 분리할 수 있습니다. 데이터 처리를 위한 모델인 명세는 도메인 모델의 상태를 정의합니다. 명세가 수정되면 하나 이상의 도메인 모델이 명세에 맞게 조정됩니다. 도메인 모델이 조정되는 과정은 비동기적으로 이루어질 수 있으며, 이벤트 소싱을 통해 명세의 변경을 추적하여 도메인 모델에 적용되어야 하는 적절한 명령을 도출할 수도 있습니다.

명세는 도메인 모델을 참조하지만, 도메인 모델은 명세를 참조하지 않습니다. 이러한 단방향 관계는 명세가 더 추상적인 도메인 모델을 참조하도록 하여, 도메인 모델이 비즈니스 로직에 집중할 수 있게 돕습니다. 이로 인해 도메인 모델이 가지고 있던 영속성 관리나 데이터 변환과 같은 부가적인 기능이 명세로 이동하게 되며, 엔티티로 모델링되던 도메인 모델이 VO(Value Object)로 변할 수도 있습니다.

CRUD 연산은 도메인 모델을 직접 접근하지 않고 명세를 기반으로 처리됩니다. 도메인 모델은 명세의 변경을 감지하여 적절한 연산을 실행합니다. RESTful HTTP API와 같은 사용자 인터페이스를 사용할 때, 사용자 인터페이스 모델과 명세 사이에 변환 계층을 손쉽게 추가할 수 있습니다. 이로 인해 노출되는 리소스는 명세를 조작하여 도메인 모델의 상태를 선언적으로 나타내게 됩니다. 사용자 인터페이스와 유사하게, 영속성 계층에서도 동일하게 명세를 기반으로 처리가 이루어지며 사용자 인터페이스로 들어온 요청은 도메인 계층에 있는 명세를 거쳐 영속성 계층까지 전달됩니다.

이 방식은 CQRS(Command and Query Responsibility Segregation, 커맨드-쿼리 책임 분리)와 유사하게 도메인 모델의 쿼리 책임을 제거합니다. 그러나 명세는 쿼리 모델과 달리 수정이 가능하며, 커맨드를 도출하기 위해 활용됩니다. 명세는 CQRS와 함께 사용될 수 있으며, 필요에 따라 더 세부적으로 분할될 수 있습니다.

댓글남기기