아키텍쳐 /Domain Driven Design

Domain Driven Design - Modeling

Terry Cho 2009. 7. 7. 23:02
직업이 직업인 만큼 요즘 Domain Driven Design 에 대해서 심도깊게 보고 있습니다.
아키텍쳐 분석 설계와 프로젝트 진행에 있어서 가장 중요한 것중의 하나가 "고객의 요구 사항을 어떻게 파악할것이며 이를 어떻게 모델화 하느냐?" 입니다. 모델 자체가 목적이 아니라 모델이라는 공통된 언어를 사용하여 고객과 소통을 하고 요구 사항을 가급적 정확하게 도출하여 나중에 미도출된 요구사항이나 잘못 분석된 요구사항이 없도록 하는 것이 중요한 포인트 중에 하나입니다.

그리고 프로젝트중에는 프로젝트 구성원, 고객, 각기 다른팀, 비지니스 전문가, 분석가, 아키텍트들간의 생각하고 있는 개념이나 목표가 서로 다른 경우가 있습니다. 그래서 시스템을 구축해놓고 나면 결국 각자가 생각한것과 다른 결과물이 나오거나 구현이 서로 기대했던 바와 달라서 모듈간 통합에서 문제가 발생하거나 많은 비용과 자원이 소요되는 경우가 있습니다.

이런 모든 문제의 공통적인 원인은 프로젝트의 구성원 자체가 현재 프로젝트의 목적,현황,디자인,업무,각자의 역할등 프로젝트에 대한 Context 에 대해서 제대로 이해하지 못해서 발생하는 문제입니다. 어떻게 보면 Communication의 문제입니다.
 프로젝트내에서 이 Context 가 제대로 공유된다면 같은 생각과 같은 현황 파악으로 인해서 프로젝트가 잘못된 방향으로 흘러가는 것을 상당 부분 예방할 수 있습니다.

이러한 관점에서 시작된것이 Domain Driven Design 인데, 기본적으로 도메인(업무 또는 현업)과 개발팀간 그리고 각기 다른 업무 개발팀간의 의사소통 방법과 소프트웨어 디자인 방법에 대해서 설명하고 있습니다. 소프트웨어 디자인 방법이나 패턴에 대해서는 다른 좋은 방법론도 많기 때문에 눈에 확 들어오지는 않았습니다만, 제가 주목하는 것은 어떻게 서로 Context를 공유할것이며, 이를 어떻게 모델링을 할것인가에 대한 기법이 참으로 흥미롭습니다.

그림으로 정리를 해보도록 하지요.

메인 모델의 작성
먼저 구축하고자 하는 시스템이 하는 비지니스 업무를 파악하는 것이 첫단계 인데. 실제 비지니스가 어떻게 돌아가는지를 다이어그램등의 모델을 이용해서 표현한다. 이때 다이어그램은 UML Class Diagram이 되도 좋고, BPM 또는 Use case Model 모두 좋다. 무엇이든 간에, 업무 전문가와 개발팀간에 가능한한 빠르고 명확하게 의사 소통을 할 수 있는 것이면 무방하다.
 업무전문가와 모델링을 하는 사람 (개발자,분석가 또는 아키텍트 이하 모델러라고 지칭하겠다.) 은 같은 언어를 사용해야 한다. 이를 DDD에서는 유비쿼터스 언어라고 하는데,
예를 들어 "메세지"를 표현하는 방법도 금융 업무에서는 "원장", 또는 "전문" 이라는 용어를 사용하고, 개발자들은 "메세지", "PAYLOAD" 등 여러가지 표현을 사용한다. 또 대내,대외계 거래, 계정계,정보계 시스템, 여신 거래,상품 거래 등의 비지니스 업무 용어, 개발쪽에서는 메시징,큐잉, MEP(Message Exchage Pattern) 등 기술 위주의 언어를 사용한다.
 DDD에서는 이와 같은 업무 분석과 모델링에서의 소통을 서로 공통된 언어를 사용하도록 하는데, 업무 위주의 언어를 사용해야 한다. 

 특히 용어가 정의될때 마다 Glossary (용어 사전)에 이를 기록하고 명확하게 정의를 함으로써 추후 또는 다른 사람들도 공통된 언어를 사용할 수 있도록 한다. 예를 들어 중간에 개발자가 새롭게 들어오거나 다른 기반 지식을 가진 아키텍트가 들어왔을때, 각종 산출물이나 회의시간에서 용어가 통일 되지 않아서 혼선이 이루어지는 경우가 많다. 구두로 용어에 대해서 설명하는 것도 가능하겠지만 프로젝트의 규모가 커지면서 많은 사람들이 참여하고 산출물의 양이 많아질때는 점점 통제 불가능 상태로 가기 때문에, Glossary를 사용하는 것이 좋고, 이 Glossary는 항상 쉽게 찾아볼 수 있도록 WIKI같은 곳에 유지 하는 것이 좋다. (엑셀로 만들어놓고 공유 폴더에 넣어놓는것은 거의 효용성이 없다.)

모델의 분리
전체적인 도메인 모델이 완성이 되었으면 도메인 모델을 세부 모델로 나누도록 한다.
큰 모델에는 전체적인 흐름과 기능에 대해서 서술되어 있으며, 디테일한 내용을 다루게 되면 모델 자체의 크기가 커져서 그 내용을 이해하기가 어려워지면서 모델로써의 효용성이 떨어진다. 또한 각각의 개발팀의 관심사는 자신이 속한 부분의 모델이기 때문에,각 팀에 모델을 나누어주기 위해서라도 모델을 분리하는데, 이 분리하는 기준을 DDD에서는 Boundary Context라고 한다. 업무의 독립단위 또는 프로젝트팀 단위로 나누도록 한다. 이때 타업무(타 도메인 모델과) 연관성이 있을 경우 이를 포함해서 나눠서 나뉘어진 모델 안에서 다른 업무와의 연계성을 파악할 수 있도록 한다.

모델을 나누면서 중요한것이 메인 모델과의 추적성을 부여하는 것인데. DDD에서는 이 방법으로 Context Map이라는 기법을 소개한다. 상위모델의 모듈이 어떤 모델로 분리가 되었는지를 명시적으로 표현하는 방법이다. UML의 Use case모델에서는 흔히 각 use case를 sub usecase diagram으로 나누면서 관계에 대한 추적성을 부여하거나 Use case의 이름에 Numbering을 해서 1. Order 1.1 Billing 1.2 Submit Order식으로 Sub Number를 붙여서 모델간의 상하위 추적성을 제공하기도 한다.
 DDD에서 Context Map이라는 용어를 궂이 사용한 이유는 Numbering을 사용할 경우 텍스트 기반의 추적성 부여이기 때문에 추적성 자체는 살아 있을 수 있지만 가시성이 떨어진다. Context Map이라는 단일의 하나의 다이어그램을 작성함으로써 가시적으로 상위 모델이 하위모델로 어떻게 연결(분리)되는지를 표현함으로써 Context의 전이가 어떻게 되는지가 표현될 수 있다.

하위모델간의 공통 모듈 처리
하위 모델간의 공통적으로 사용하는 모듈이 존재할 수 있는데, 이런 모듈의 변경은 두개의 프로젝트에서 동시에 사용하기 때문에 변경이 있을 경우 두개의 시스템에(업무 모듈)에 동시에 영향을 줄 수 있다. 
이렇게 동시에 두개 이상의 모델에서 공유되는 모듈을 DDD에서는 Shared Kernel이라고 하고, 연관되는 프로젝트 팀이 같이 설계하고 변경에 대해서 서로 협의하여 반영하도록 가이드 하고 있다.
실제 프로젝트에서는 사실 쉽지 않은 일인데, 이러한 공통 모듈에 대한 관리와 교통 정리는 AA (Application Architect)가 관여하여 분쟁이 있을때 조정을 해줄 수 있어야 하며, 이 Shared Kernel에 대한 Model은 항상 Wiki와 같은 Live Document에 최신 상태로 유지되어야 한다.
DDD에서는 이러한 두개 이상의 모델의 의존성에 의한 오류 방지책의 하나로 Continuous Integration (CI)를 권장하고 있다. 본 블로그에서도 Hudson이나 ALM을 통한 CI의 개념을 수차례 설명했다.
간단하게 설명하자면 CI는 지속적으로 빌드와 테스트를 자동화하여, 변경 내용에 의해서 기존 코드가 오동작하는 것을 조기에 발견한다.
즉 Shared Kernel 에 대해서 A팀이 구현을 변경했을때, 이 변경이 기존 동작 방식에 영향을 끼치면 B팀의 CI Test과정에서 모듈이 변경이 되서 기대했던 대로 작동을 하지 않음을 발견한다.

결론
대략 DDD의 Context 기반의 모델링 기법을 정리해보면 이렇습니다.
사실 그이에도 하위 모델간의 관계와 서로간의 의존성을 최소화 하는 여러 기법들을 DDD에서 소개하고 있습니다.
Anticorruption Layer(Facade를 이용하여 완충 레이어를 두는 방법, ESB의 Mediation이나 EAI 패턴과 유사하지요.)
Open Host Service (인터페이스를 추상화된 서비스 계층으로 외부에 서비스한다는 개념인데, SOA의 서비스 개념과 유사합니다.)
Customer Supplier Teams (단방향 의존성을 갖는 경우에 인터페이스 하는 방법에 대한 정의인데, EAI에서 이미 소개되고 사용되는 방법이구요.)
그외에 여러가지가 있는데, 대부분 설계 방법에 관련된것이고, 위에서 소개했던 것과 같은 분석과 모델링 방법에 대한것은 아니라서 자세하게 소개하지는 않았습니다.

디자인 패턴과 설계 방법론에 대해서는 이미 다른 곳에서도 많이 소개된 바가 있고, 도메인 (업무)기반의 설계 방법도 사실 OOP 이전부터도 존재했기 때문에 별다를것이 없지만, DDD에서 주목할만한 것은 모델링에 대한 원래 목적을 뒤돌아보고 그에 대한 접근 방법을 정리했다는 것에 주목하고 싶습니다.