DDD, 도메인 주도 개발 정리

반 버논의 도메인 주도 설계 핵심을 읽으며 요약 2020-02-16

바운디드 컨텍스트? 보편언어?

  • Bounded Context: Multiple models are in play on any large project.
  • DDD에서는 복잡하고 규모가 커지면 맥락의 경계를 명확하게 정의하라고 제안한다. 그 단위가 바운디드 컨텍스트이다.
  • DDD 는 서로 다른 개념들은 각기 다른 바운디드 컨텍스트 안으로 분리해 놓음으로써 개념간 차이를 더욱 중시한다. 즉 각기 다른 언어와 그에 따른 기능이 존재하는 것을 인정하는 것이다. 가령 보험회사에서의 정책이란 사업부서마다 그 의미가 다른데, 모두 하나의 정책으로 통합하려고 한다면, 분명 문제가 발생할 것이다.

    • In those younger days we were advised to build a unified model of the entire business, but DDD recognizes that we've learned that "total unification of the domain model for a large system will not be feasible or cost-effective" [1]
  • Bounded Contexts have both unrelated concepts (such as a support ticket only existing in a customer support context) but also share concepts (such as products and customers).[2]
  • 보편언어는 바운디드 큰텍스트 안에서 구성원들이 이야기할 때 사용되고, 소프트웨어 모델 안에 구현된다. 따라서 보편언어는 엄격하고, 정확하고, 엄중하며, 단호해야 한다.[3]
  • 바운디드 컨텍스트 안에서의 차이를 더욱 중시한다는 것이 의미있게 다가왔다. 일반적으로 개발자들은 반복을 피하려고 적당한 함수나 객체를 추출하고 적당히 추상화 한다. 이로써 여기 저기에 쓰일 수 있는, 반복없는 코드를 만들 수 있다. 그러나 문제는 이러한 반복을 줄이는 작업에 빠지다보면 같지 않은 것을 과도하게 같게 처리하려고 한다는 점이다.

서브도메인

  • 도메인이란 프로젝트가 다루고 개발하는 무언가를 나타내는데, 쉽게말해서 서브도메인은 큰 도메인을 여러개로 나누겠다는 것이다.
  • 전체 큰 비지니스를 나눈 도메인이 서브도메인일 수도 있고, 프로젝트 하위에 서브도메인이 있을 수도 있다.
  • DDD에서는 일반적으로 바운디드 컨텍스트와 서브도메인은 1:1 관계를 맺어야 한다. 물론 이것이 항상 가능한 것은 아니지만 가능하면 그렇게 해야 한다. 왜냐하면 이는 바운디드 컨텍스트를 정확하게 유지시키고 핵심 목표에 집중하는 데 도움을 주기 때문이다.

컨텍스트 맵핑

  • 결국 컨텍스트간의 상호작용은 일어난다. 이러한 컨텍스트간 통합을 컨텍스트 매핑이라 한다.
  • 공통의 모델을 공유하거나, 반부패 계층(즉 모델 사이의 번역 계층을 만드는 것)을 두거나, 공개 호스트로 프로토콜과 인터페이스를 정의하여 통합한다.
  • 인터페이스로는 RPC, Restful, 비동기 메시징(Queue, PubSub) 주로 둔다. 상황이 나쁜 경우 데이터베이스나 파일 시세팀의 통합을 강요받을 수도 있는데 그런 일은 지양해야 한다.

    • 메시징을 사용한 통합이 가장 견고한데, 이는 RPC/REST 와 달리 분절된 형태와 일시적인 결합을 대부분 제거할 수 있다.
    • 메시징을 사용하는 경우 At least once delivery를 통해 수신을 보장해야 하고, 구독하는 쪽에서는 멱등성을 보장해야 한다. (idempotent Receiver )
  • 이벤트에 소비자가 추후 조회를 통해 데이터를 요청하게 할지, 모든 데이터를 담아줄지는 장단이 있다. 모두 담으면 소비자에게 더 큰 자율성을 허용할 수 있지만, 메시지가 커질수록 복잡해진다.

에그리게잇

  • Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit.[4]
  • 비지니스 로직이 도메인 모델을 넘어 에플리케이션 서비스까지 새어 나가지 않도록 주의한다.
  • 에그리게잇은 일관성있는 트랜잭션 경계를 형성하는 단위가 됨. 일관성이 지켜질 필요가 없는 다른 요소를 에그리게잇에 불필요하게 포함하면 안된다. 모든 에그리게잇이 즉각적인 갱신이 이루워져야 한다는 주장에 주의를 기울여야 한다.
  • 작은 에그리게잇을 유지해야한다.(트랜잭션 범위가 비교적 작아야 한다) 오직 ID 를 통해 다른 에그리게잇을 참고해야한다. ( 객체 맵핑으로 들고있으면 에그리게잇을 침범한느 코드가 구조적으로 발생함 )
  • 에그리게잇이 단일 책임 원칙을 따르는지 점검한다.
  • 도메인 이벤트를 통해 다른 에그리게잇을 갱신하도록 하라. 도메인이벤트는 발행한 컨텍스트에 다시 들어올 수도 있고, 아닐 수도 있다. 나아가 도메인 이벤트는 메시징 미들웨어를 통해 통신할 수 있다.

도메인이벤트

  • 도메인이벤트를 처리하는 곳에서 필요한 정보를 얻기 위해 다시 쿼리를 하지 않도록 데이터를 담아야 하지만, 이벤트에 그 의미를 잃을 정도로 너무 많은 데이터를 가득 채우는 일은 없도록 해야한다. 도메인 자체의 상태를 넣어버리면 이벤트 발생에 의해 실제로 무슨 일이 일어났는지 파악하기 어려울 수도 있다.
  • 이벤트소싱은 에그리게잇 인스턴스 대해 변경 기록으로, 발생했던 모든 도메인 이벤트를 저장하는 것을 말한다.

Reference

Buy Me A Coffee