도메인 주도 설계 핵심

출처

redutan님의 블로그

공부 기준

  • 반 버논의 도메인 주도설계 핵심 1~7장까지 선 학습을 목표로한다.

  • 상세한 내용은 출처의 IDDD, 기술 블로그를 활용한다.

1장

2장 바운디드 컨텍스트 및 보편언어와 전략적 설계

챕터 용어정리

  • Big ball of mud (진흙덩어리)

  • Bounded Context (바운디드 컨텍스트)

  • Ubiquitous Language (보편언어)

  • Collaboration Context (협업 컨텍스트)

  • Problem Space (문제 영역)

  • SoftWare Space (해결 영역)

  • 핵심도메인

  • BDD(Behavior-Driven-Develomet) : 행위 주도 개

바운디드 컨텍스트

  • DDD는 바운디드 컨텍스트내 에서 보편언어를 모델링하는 것으로 이야기된다.

  • 바운디드 컨텍스트는 의미적으로 동일한 컨텍스트의 범위를 표현한다.

    • 이 범위 내에서 소프트웨어 모델의 각 컴포넌트는 특정한 의미를 가지고 일을 수행한다.

    • 컨텍스트 내의 존재하는 컴포넌트는 컨텍스트에 특화되어 의미있게 활용된다.

  • 문제 영역(problem space)의 일부로 생각될 수 있으나, 설계되는 모델이 깊은 의미와 명확성을 가지게 되면 바운디드 컨텍스트는 해결영역(software space)로 전환되고 모델들은 프로젝트 소스 코드에 반영된다.

    • 문제영역

      • 상위수준의 전략적 분석을 수행하고 주어진 프로젝트 제약사항 내에서 단계를 설계하는 영역

      • 프로젝트 요인, 주요목표와 위험 사항에 대해서 논의시 간단한 다이어그램을 활용한다.

      • 실제 예로 컨텍스트 맵은 문제 영역에서 잘 활용된다.

      • 필요에 따라 해결 영역과 밀접한 영역을 가지게된다.

    • 해결영역

      • 문제영역의 논의가 핵심 도메인으로 바라보는 해결 방안을 구현하는 곳이다.

      • 바운디드 컨텍스트를 조직의 핵심 전략계획으로 개발시 이를 핵심 도메인이라고 한다.

      • 바운디드 컨텍스트 내에서 메인, 테스트 코드로 해결 방안을 개발한다.

      • 타 바운디드 컨텍스트와의 통합을 지원하는 해결 영역에서도 코드를 생산한다.

  • 즉 바운디드 컨텍스트는 일정한 범위내에 의미를 가지는 모델들이 구현되는 곳이며, 각 바운디드 컨텍스트는 각각의 분리된 소프트웨어 산출물이 나온다.

  • 우리가 사용하는 인간의 언어도 국경을 넘어가면 그 경계가 명확하다. 바운디드 컨텍스트 또한 유사한 의미를 가지고 있다.

  • 단일팀만 할당되어야하며 각 바운디드 컨텍스트 마다 독립적인 소스코드 리포지토리가 필요로 한다.

  • 한 팀이 다수의 바운디드 컨텍스트를 운용이 가능하나, 여러팀이 한 바운디드 컨텍스트를 수행하지 않는다.

    • 이는 다수의 팀이 수행할 경우 발생되는 문제를 원천차단하기 위함이다.

    • 동음이의어 와같은 상황이 발생되는데 비즈니스 지식들이 다른 컨텍스트에 존재하기 때문이다.

    • 타 팀과의 소통은 공식 인터페이스를 정의하여 담당한 바운디드 컨텍스트를 다른 팀이 사용할 수있게 허용한다.

    • 이것이 DDD의 사용의 이점이다.

  • 보편언어를 나눈것과 같은 방법으로 바운디드 컨텍스트 마다 소스코드, 스키마 역시 명확하게 분리해야한다.

  • 메인 소스 및 단위, 인수 테스트 역시 유지해야한다.

  • 바운디드 컨텍스트를 사용하는 이유는 각팀이 각 도메인을 작고 관리할 수있는 정도에서 시작한다 할지라도 수많은 개념이 쌓이는 것을 언제까지 누적해야하는가 판단이 안설 경우가 있다.

  • 각 팀은 더 많은 개념을 추가하게되면서 하나의 거대,혼란,경계가 제한되지 않은 모델안에서 너무 많은 개념이 존재하는 것은 물론 실제로 다수의 언어가 혼재 되면서 점차 모델내의 언어가 모호해지기 시작한다.

  • 위와 같은 상황에서 각 팀이 소프트웨어 제품을 진흙 덩어리로 만들어버린다.

  • 이러한 모델을 사용하게 된다면 큰 문제가 발생되어 알수없게 확장되거나 어울리지 않는 모듈을 상호 연계될 가능성도 존재한다. 이는 테스트 시간의 중가와 건너뛰는 현상을 초례할 수있다. 개판이라는 것이다.

보편언어

  • 컨텍스트 범위 내의 소프트웨어 모델은 바운디드 컨텍스트 안에서 일하는 팀이 생성하고 소프트웨어 모델을 구현하는 모든 팀 구성원이 사용하는 언어를 반영한다.

  • 이 언어는 팀 구성원이 이야기 시 사용되고 소프트웨어 모델 안에서 구현되기에 보편언어라고 불리운다.

  • 팀 모두가 보편언어로 표현된 의미에 대한 제약사항과 정확한 의미를 이해해야한다.

  • 이 언어의 대표적인 기록형태는 소프트웨어 모델의 소스 코드이다.

  • 팀의 보편언어를 개발하기 위해서 주의할 점은 일생생활에서 명사를 단독으로 사용하는 것보다 여러 말들과 함께 사용한다는 점을 간과하지 말아야한다.

  • 도메인 모델안의 명사에 많은 의미를 부여하는 경향은 배제해야한다. 이러한 경항은 DDD의 다른 측면인 핵심 도메에서 필수적인 모델 요소까지만 제한하는 것에 관심이 생겨서 일수 있다.

  • 보편언어를 만들기 위해서 시나리오를 개발하며 연구를 해봐야하는 것 같다. 위와 같은 행위를 좀더 구체적으로 개발하는 것은 이벤트 스토밍에서 살펴봐야하고 7장의 가속화와 관리도구에서 좀 더 알아본다.

  • 핵심 도메인을 명사에만 제한하지 말라. 도메인 모델에 나타난 개념에 대한 구체적인 시나리오를 나타낼 수 있게 어떻게 도메인 모델이 동작하고 어떤 다양한 컴포넌트가 동작해야하는가 구성해야한다.

  • 스크럼의 보편언어에 맞는 시나리오 사례를 살펴본다.

  • 보편언어를 관리하는 방법은 주기적으로 보편언어를 성장 시켜야하며 보편언어의 발전이 없이 유지되는 상황을 배제, 그렇다고 긴 시간을 투자하는 것도 자제해야한다. 항상 소프트웨어 모델이 전략적 차별요소인 핵심 도메인 인지 매번 반문하자.

각 백로그 아이템을 스프린트에 할당한다. 백로그 아이템은 이미 릴리스에 예정돼 있는 경우에만 할당 될 수 있다. 만일 이미 다른 스프린트에 할당됐다면 먼저 이를 해제해야한다. 할당이 완료되면 관련된 대상에게 알린다.

  • 시나리오는 실제 소프트웨어 모델 컴포넌트들이 스크럼 기반 프로젝트 관리를 지원하기 위해 어떻게 동작할 것인지를 나타내는 세부사항이다.

  • 구체적이지 않지만 대략적인 흐름를 서술하는 것으로 시나리오를 기술해 나간다.

  • DDD는 계속해서 모델을 개선해 나가는 사상을 추구하기 때문에 점진적인 발전을 추구할 수 있는것 같다.

  • 시나리오를 성공적으로 마무리짖기위해 필요한 제약조건을 잘 정해야한다. 실제 도메인 모델이 어떻게 동작하는지 설계된 모델과 대화를 나누듯 풀어나가는 것이 가장 중요하고 도움이 되는 특징이라고 본다.

  • 사진과 다이어그램 등으로 풀어나갈수도 있으나, 장기간 시나리오, 그림, 다이어그램 등을 관리하기 위한 문서를 항상 최신화 하는 경우 도메인 모델링에 허비되는 시간이 많아진다. 문서는 도메인 모델이 아니다. 도메인 모델 개발을 위한 도구일 뿐 "코드 = 모델"이란 점 명시해야한다. 핵심을 놓치지 말아야한다.

핵심 도메인

  • 핵심 도메인은 다음과 같은 목표를 가진다.

    • 가치있는 것들을 달성하기 위한 수단

    • 다른 조직과 경쟁에 대한 차별화

    • 최소한 하나의 주요한 사업 부분을 다룬다.

    • 기업이 올바른 정략을 결정하기 위해 무엇이 핵심 도메인인지 분별해야한다.

도메인 전문가와 비즈니스 동인

  • 비즈니스 이해관계자들에게서 기술팀은 더 나은 모델을 설계시 도움이 되는 힌트를 얻어낼 수 있다.

  • 이들과 협업을 하지 않을 경우 제멋대로 노력한 결과가 나올 뿐이다.

  • 그렇기에 각 사업 기능마다 비즈니스 전문가를 두는 경우가 많다. 조직의 구분4과 기능에 대해 관점을 가지고 생각해야한다.

  • 예를들어 정책(policy)이라는 것이 각 기능에 따라 얼마나 다른 의미를 가지는지 살펴본다.

    • 계약심사 내 정책

      • 계약심사를 담당하는 전문부서에서 피보험 자산에 대한 위험평가를 기반으로 정책을 세운다.

    • 검사 내 정책

      • 보험사가 손해 보험관련 업무시 계약 심사시 자산의 검사를 책임지는 검사 전문부서가 존재한다. 보험사는 피보험인이 주장한 자산의 상태만 믿는 것이 아니라 어느정도 검사를 통해 확인된 정보를 의존한다.

      • 자산이 계약심사의 대상이 되는 경우 사진이나 기록등 검사 세부사항은 검사 부서의 정책과 관련이 있고, 계약심사 부서에서는 그 자료를 최종 보험료를 협상하는데 사용할 수 있다.

    • 청구 내 정책

      • 청구 전문부서의 정책은 계약 심사부서에서 세운 정책의 조건에 따라 계약심사된 보험료 지불요청내역을 추적한다.

      • 청구 정책의 일부는 계약 심사의 정책에도 나타나지만 보험에 계약된 심사된 자산에대한 손해와 지급액 결정을 위해 청구 담당자가 수행하는 검토등에 사용할 정책처럼 그 어떤 것이든 청구 관점에서 정책이 세워저야할 것이다.

  • 위와 같은 세가지 정책을 모두 하나의 정책으로 통합하려 하면 많은 문제가 발생 될 것이다. 시작도 안한 제4의 제5의 사업개념까지 지원하기위해 과부화 상태까지 왔다면 문제는 커지고 아무도 해결이 불가능하다.

  • 이러한 점을 해결하기위해 DDD는 서로 다른 개념들을 각기 다른 바운디드 컨텍스트안에 분리하여 개념간 차이를 더욱 중시한다.

  • 위와같은점은 각기 다른 언어와 그에 따른 기능이 존재함을 인정하는 것이다. 한마디로 정리하여 계약심사 내 정책, 검사 내 정책, 청구 내 정책으로 구분 두는 것이 아니라 바운디드 컨텍스트 내에서 정책을 정책이라는 의미로 그대로 사용하는 것이다.

  • 그외의 비행이라는 단어도 다양한게 구분되기에 바운디드 컨텍스트로 관리하길 권장되는 것으로 보인다.

바운디드 컨텍스트를 사용해야하는 이유와 그에 따른 사례 연구

  • 도메인 모델 사례를 예를 들어 설명하며 구체적인 사례를 살펴본다.

  • 스크럼 기반 애자일 프로젝트 관리 어플리케이션 작업을 살펴본다.

  • 위 작업을 표현하기 위해서 많은 개념을 트리 구조로 살을 붙여나가지만 진흙 덩어리를 만들게 되버린다. 그럼 어떻게 해결해야 하는게 옳은가?

  • 바로 전략절 설계를 하기위한 DDD의 도구인 바운디드 컨텍스트와 보편언어가 이에 해당되는 것이다.

  • 첫쨰로 도메인 전문가와 개발자를 하나로 묶어 협업하는 님을 구성해야한다.

도메인 전문가

  • 비즈니스 문제에 대해 포커스를 두고 비즈니스의 흐름에 대해서 비전을 가진다.

  • 스크럼 도메인에서 스크럼이 프로젝트에서 어떻게 실행되는지 완벽하게 이해하고 있는 스크럼 마스터가 바로 도메인 전문가다.

  • 스크럼 제품 책임자와 DDD 도메인 전문가 사이에 어떤 차이가 있는지 궁금할 수 있다. 동일할 수도 아닐수도 있다.

  • 하지만 제품 책임자는 제품의 백로그를 관리하고 우선순위를 정하는 것 그리고 프로젝트의 개념적이고 기술적인 연관성이 유지되도록하는것에 신경쓰는 것이 바람직하나, 비즈니스의 핵심 경쟁력의 전문가가 될 필요는 없다.

  • 고로 팀내에 진짜 도메인 전문가를 포용하여 하며 제품 책임자가 그를 대신해선 안된다.

개발자

  • 소프트웨어 개발에 중점을 둔다.

  • 핵심 전략 목표의 비즈니스 초점을 받아들이지 못하는 기술중심의 주장을 하지 말아야한다.

  • 근거없는 간결성은 피하며, 해당 팀의 바운디드 컨텍스트 안에 팀이 점진적으로 개발하는 보편언어를 수용해야한다.

  • DDD를 사용하는 목적은 기술적인 측면보다 비즈니스 모델의 복잡도가 매우 높기에 사용한다. 필요 이상의 복잡한 모델링은 삼가하고 도메인 전문가와 함께 비즈니스 모델을 파악해야만 한다

  • 도메인 전문가와 개발자는 모두 문서가 대화를 지배하는 상황을 피해야하고 최고의 보편언어를 협업에 의한 피드백으로 산출해야한다. 이로서 화합된 멘탈 모델을 구성할 수 있다. 열린사고와 깊은 탐구를 현재의 지식기반에 대한도전을 통해 핵심도메인에 대한 통찰을 얻어야한다.

도전과 통합

  • 진흙 덩어리를 해결하기 위해선 바운디드 컨텍스트 내에서 보편언어를 따르는가 확인해보는 관점을 가져야한다.

차례대로 스크럼 바운디드 컨텍스트의 구조를 잡아보자

  • 스크럼과 아무 상관이 없는 Tenant와 그 하위 소프트웨어 모델을 제외시켰다.

  • 제외된 소프트웨어 모델은 스크럼 애자일 컨텍스트 내의 보편언어인 Team, ProductOwner, TeamMember에 더 합리적이고 어울리므로 소프트웨어 모델에 대체가 된다.

  • 이런 식으로 필요한데 대체할 수 있는지 확인해보아야 한다.

도메인모델의 중요한 점 하나

  • 기술은 아키텍쳐 전반에 걸쳐 산재되어 있으나 도메인 모델은 기술로 부터 최대한 자유로워야한다. 예를 들어 트랜잭션은 어플리케이션 서비스에서 관리될 뿐 도메인 모델에 의하여 관리되는 것이 아니다.

3장

4장

5장 애그리게잇과 전술적 설계

엔티티이란 무엇인가?

  • 엔티티란 독립적인 것이다.

  • 특성을 구별할 고유한 식별성을 가져야한다.

  • 지속적으로 수정이 이루어질 수 있으나, 때로는 고정될 수 있다.

  • 다른 모델링 수단과 엔터티를 구분해주는 주 요인은 유일성에 있다.

애그리게잇이란 무엇인가?

  • 한 개 이상의 엔티티로 구성되고, 최초로 퍼져나가는 엔티티를 애그리게잇 루트라 명명한다.

  • 구성요소에 값 객체를 포함할 수 있다.

  • 애그리게잇의 루트 엔터티는 모든 요소를 소유한다. 루트 엔터티는 애그리게잇의 개념적 명칭이다.

값 객체란 무엇인가?

  • 값이란 불변의 개념적 완전성을 모델링한다.

  • 엔터티를 서술, 수량 및 측정하는데 사용된다.

애그리게잇의 특성

  • 일관성 있는 트랜잭션 경계를 형성한다.

    • 트랜잭션 제어가 DB에 커밋 시, 한 애그리게잇 내의 모든 구성 요소는 반드시 비즈니스 규칙을 따르면서 일관성 있게 처리된다.

    • 하지만 트랜잭션 이후 일관성이 지켜질 필요가 없는 다른 요소를 포함하면 안된다는 뜻은 아니다.

  • 개념적으로 완전하게 모델링해야한다.

  • 각 애그리게잇 경계 내에서 데이터 처리 원칙을 유지하며 제어하는 트랜잭션으로 분리되어야한다.

  • 이러한 이유는 비즈니스 때문이며, 위와 같은 규칙을 지키지 않는경우 수행된 비즈니스 오퍼레이션은 비즈니스 규칙에 어긋난 것을 간주하여 관리되어야하는 것으로 보인다.

애그리게잇 경험 법칙

DDD를 준수하기 위해 효과적으로 동작하는 애그리게잇을 설계할 수 있도록 도움을 주는 가이드 4가지에 대해서 배워보도록 하자.

애그리게잇 경계내에서 비즈니스 불변사항을 보호하라

  • 트랜잭션이 커밋될 때 비즈니스의 일관성이 지켜지는 것에 기반을 두고 애그리게잇 구성요소를 결정해야한다는 의미를 가진다.

  • 스크럼 바운디드 컨텍스트 내에 존재하는 루트 엔터티와 그 하위에 존재하는 엔터티는 항상 일관되게 처리하도록 설계를 하다.

  • 스크럼 바운디드 컨텍스트내에서 구체적인 예시

    • 모든 작업 인스턴스의 남은 시간(Hour Remaining)이 0 일때, BacklogItem의 Status는 반드시 DONE으로 설정해야한다.

    • 이는 트랜잭션 후 반드시 부합돼야하는 매우 명확한 비즈니스 요청사항이다.

작은 애그리게잇을 설계하라

  • 각 애그리게잇의 메모리 사용량과 트랜잭션의 범위가 비교적 작도록 설계를 해야한다.

  • 많은 수의 인스턴스가 존재해야할때 애그리게잇에 함께 두는경우 좋지 않은 설계가 나올 수 있다.

  • 이들을 적합한 단위의 애그리게잇으로 설계하면 더 빠르고, 작은메모리를 차지하고, 가비지 컬렉팅의 성능이 향상된다.

  • 또한 훨씬 더 자주 성공적인 트랜잭션을 수행할 것이다.

  • 핵심적인 유념할 개념은 단일 책임의 원칙을 준수해야한다.

오직 식별자를 통해서 다른 애그리게잇을 참조하라

  • 작은 단위로 애그리게잇을 설계를 성공적으로 한경우, 각 애그리게잇이 필요한 다른 애그리게잇에 어떤식으로 참조해야하는가 고찰을 해보면 오직 식별자로만 수행해서 다른 방법으로 참조하고자 하는 객체의 레퍼런스를 얻을 수 없도록 구성해야한다.

  • 동일한 트랜잭션 내에 다른 애그리게잇을 수정하지 않는 규칙이 잘 지켜지도록 해준다.

결과적 일관성을 사용해 다른 애그리게잇을 갱신하라.

  • 일관된 비즈니스 룰에 의거하여 각 애그리게잇이 도메인 이벤트를 발생하고 해당 이벤트를 소모하는 애그리게잇 또한 갱신되는 룰을 의미하는 것으로 보인다.

  • 4장의 컨텍스트 매핑과 전략적 설계를 다시 상기해보자면 도메인 이벤트는 애그리게잇에 의해서 발생되고 관심이 있는 바운디드 컨텍스트가 이를 전달 받는다.

  • 일반화 해서 이야기하자만 좋아하는 문학이 있는 경우, 독자들은 구독을 하여 정기적인 관심을 보이는 형태가 자주 있다. 위와 같은 구조를 메세징 매커니즘으로 본다.

  • 정말 일관성을 가질 수 있는가 의문점이 생길 수 있으나 반드시 비즈니스에 의해 정의된 트랜잭션 경계에 따라 모델을 애그리게잇으로 분리시켜야한다. 위를 통해 트랜잭션의 실패 경험을 줄여줄 수는 있을 것이다.

애그리게잇 모델링

모델링을 진행할 때 주의할점

  • 빈약한 도메인 모델 지양해야한다.

    • 비즈니스보다 기술적인 초점을 맞췄을 때 발생하는 경향이 있다.

    • 이럴 경우 도메인 모델이 주는 혜택을 받지 못하고 모든 오버헤드를 떠안아버리는 상황이온다.

  • 비즈니스 로직이 도메인 모델을 넘ㅇ 애플리케이션 서비스까지 새어 나가지 않도록 해야한다.

    • 비즈니스 로직을 도멩니 모델 안에 정의하지 못한다면, 빈약한 도메인 모델이 만들어낸 버그들 때문에 문제가 발생할 수 있다.

함수형 프로그래밍에서의 애그리게잇 모델링에 대한 고찰

  • 빈약한 도메인 모델이 객체지향에서는 지양되지만, 함수형에서는 그렇지 않다.

  • 함수형 프로그래밍은 데이터와 행위의 분리를 권장하기 때문이다.

  • 불변하는 데이터의 구조나 레코드 유형으로 데이터를 설계하고 이를 제어하는 함수로 행위를 구현하는 방식을 취한다.

  • 늘 새로운 값을 반환하는 구조이기에 애그리게잇의 상태 변환을 나타내주는 도메인 이벤트 또는 집합의 새로운 상태가 된다.

모델링을 진행시 고려할 사항

  • 내부의 상태를 변경시키는 행위와 관련된 메서드들을 사용하여 값을 변경한다.

  • 인자로 받은 값과는 다른 새로운 값을 반환하도록 메서드를 정의한다.

  • 도메인 모델의 속성을 변경시키는 메서드를 공개해버리면 해당 도메인 모델의 값을 설정하는 로직이 모델 밖에서 구현되기 때문에 빈약한 도메인 모델로 구성될 수 있다.

추상화를 선택 시 주의하라

  • 지나친 추상화로 인해 미래에 등장할 가능성을 염두하고 설계를 하는 경우 발생되는 문제가 있다.

    • 소프트웨어 모델의 언어가 도메인 전문가의 멘탈 모델과 일치하지 않는다.

    • 추상화 수준이 너무 높아서 각 개별적인 형태의 세부 사항을 모델링하기 시작하면 어려운상황에 빠질 것이다.

    • 각 클래스 마다 특수한 경우를 정의할 것이고, 클래스 계층 구조가 복잡해진다.

    • 필요 이상의 코드가 작성될 수 있다.

    • 사용자 인터페이스까지 영향을 주어 혼란을 일으킨다.

  • 팀이 정의한 도메인 전문가의 멘탈모델에 따라 보편언어를 모델링 해야한다.

6장

7장

Last updated