book

책 <Domain-Driven Design Distilled> by 반 버논

책 <Domain-Driven Design Distilled> by 반 버논

Wonny (워니)
Wonny (워니)·생성일 2022년 04월 13일 11:47·마지막 수정일 2022년 04월 24일 06:03

Review 🤓

DDD를 공부하기 위해 읽은 첫 번째 책이다. 카일이 DDD에 있는 여러 개념을 핵심만 간결하게 학습할 때 좋은 책이라며 소개해줘서 읽게 됐다. 실제로 주요 개념들이 간략하게 설명되어 있고 어떤 목적을 이루는지 위주로 설명해주고 있다.

중간중간 간단한 사례를 통해서 몇 가지 상황에 대한 이해와 공감을 도와주기는 하지만 대부분 추상적인 개념에 대해 설명할 때가 많아서 처음 공부하는 사람 입장에서는 이해가 쉽지 않은 부분도 꽤 있었다. 그래도 방대하고 어렵기로 소문난 에릭 에반스의 'Domain-Driven Design'로 시작하는 것보다는 좋은 시작인 것 같다.

이 책을 통해 그간 어렴풋이 듣기만 했던 개념들에 대해 보다 명확히 이해하게 되었고, 회사에서 설계 논의를 할 때 사람들이 얘기했던 말들이 무슨 뜻인지 이제야 명확하게 와닿게 되는 찰나들이 있었다. 떠오르는 실제 경험과 코드들이 있어서 재밌게 봤다.

공부할 게 한참 남기는 했지만 DDD를 알아갈수록 설계를 고민할 때 더 정확한 용어를 사용하고, 더 명확한 목적을 이야기할 수 있을 것 같다. 또 DDD를 통해서 이벤트 소싱이나 CQRS 등 앞으로 공부해나가면 좋을 여러 개념과 기술을 조금씩 알게 되는 점도 좋았다.

번역 퀄리티는 나쁘지는 않지만 아쉬운 부분이 있기는 했다. 특히 목적에 대해 이야기를 할 때 원서에서 말하고자 하는 뉘앙스를 다 담지 못할 때가 있는 것 같았다. 그래도 아주 나쁜 수준은 아니라서 가끔만 원서를 보는 것으로 충분했다.

Summary + Notes 💭

What is DDD(Domain-Driven Design)?

DDD가 소프트웨어 개발에 대한 복잡한 접근법이라는 이야기를 들어본 적이 있을 것이다. 사실, 접근 자체가 복잡한 것은 아니다. 정확하게는 복잡한 소프트웨어 프로젝트에 사용할 수 있는 수준 높은 기술들을 모은 것이다.

DDD는 소프트웨어를 설계하고 구현할 때 전략적/전술적 도움을 주는 도구들의 모음이다.

전략적 개발 도구들은 비즈니스를 위한 통합적인 판단을 할 수 있게 도와준다. 조직이 집중해야 하는 것을 신중하게 선택하고, 핵심 역량을 반영하는 소프트웨어 모델을 만들 수 있게 도와준다.

전술적 개발 도구들은 비즈니스의 고유한 활동을 정확하게 모델링하는 유용한 소프트웨어를 설계하도록 도와준다.

DDD는 주로 명확한 바운디드 컨텍스트 내에서 보편언어를 모델링하는 것에 대한 것이다.

DDD 프로젝트를 수행하는 개발자는 핵심 전략 목표의 비즈니스 초점을 받아들이지 못하는 기술 중심의 주장을 하지 않도록 조심해야 한다.

DDD가 도움을 줄 수 있는 문제

  • 비즈니스가 소프트웨어 개발을 이익 중심이 아닌 원가 중심으로 생각하는 것 (전략적 이점이 아닌 안고 가야 하는 골칫거리로 바라보기 때문에 발생함)
  • 개발자가 문제에 집중하기 보다 기술에만 몰두하여 기술적으로 해결하려는 것 (개발자가 유행하는 기술만 좇게 만듬)
  • 데이터베이스에 너무 큰 우선순위를 부여하여 대부분의 논의가 비즈니스 프로세스와 업무보다 데이터베이스 주변 솔루션 센터와 데이터 모델에 집중하는 것
    • 매우 공감되는 문제
      • 힐링페이퍼에서 일하면서 충격적이었던 순간 중 하나는 설계 시 데이터베이스 스키마를 제일 먼저 고민하는 게 좋지 않다는 것을 알게 되었을 때다. 그동안은 데이터베이스가 아랫단에 존재하기 때문에 변경 시 비용이 가장 크게 발생한다고 생각하여 데이터베이스 스미카부터 결정하고 나머지를 그에 맞게 결정해서 데이터베이스의 변경 가능성을 낮추는 게 좋은 설계 방법이라고 생각했다.
      • 가령 풀고자 하는 문제가 있을 때 그 문제 해결에 필요한 모든 데이터를 정의하고 이 데이터들을 어떤 테이블로 묶을지부터 고민하는 식이었다. 그러나 힐링페이퍼에 와서 좋은 설계를 고민하고 볼 일이 늘어나면서 데이터베이스 스키마를 고민하기 이전에 우리가 풀고자 하는 문제 단위를 어떻게 나눌지를 결정하고 그에 따라 적절한 데이터베이스 스키마를 고민하게 낫다는 걸 알게 되었다. 이렇게 쪼갰을 때 오히려 변경에 강한 데이터베이스 스키마가 나온다는 것을 알게 되었다.
      • 사례로 말해보자면 멤버에게 맞춤 컨텐츠를 제공하기 위해 멤버가 선택한 관심 상품 리스트를 저장해야 하는 상황이 있다. 이때 데이터베이스 스키마부터 고민한다면 고작 필드 하나이기 때문에 멤버 테이블에 관심 상품 리스트 필드를 추가하기 쉽다. 그러나 우리가 앞으로 맞춤 컨텐츠 기능을 고도화할 계획이 있어서 멤버가 선택하는 무언가가 계속해서 늘어날 예정이라면 멤버가 선택한 무언가들을 저장하는 별도의 테이블을 분리하는 게 좋다.
  • 개발자가 비즈니스 목적에 따라 클래스와 오퍼레이션 이름을 짓는 것에 크게 관심이 없어서 비즈니스가 담고 있는 멘탈 모델과 개발자가 만들어낸 소프트웨어 사이에 큰 차이가 생기는 것
  • 설계에 대해 고민할수록 훌륭한 개발자는 단순히 개발 지식이 많고 코드를 열심히 작성하는 것으로 그치지 않고 개발 직군 외의 협업하는 사람들과도 적극적으로 소통하고 같이 잘 일할 수 있는 방법을 고민하는 사람인 것 같다.
  • 비즈니스와 개발자들의 협업이 빈약한 것
  • 개발자들이 심사숙고한 설계보다 일정 내에 할 일을 쳐내는 것에 집중하게 되어 비즈니스 동인에 따라 적절하게 분리된 모델이 아닌 큰 진흙 덩어리를 만들어내는 것
  • 개발자가 비즈니스 로직을 사용자 인터페이스 컴포넌트와 영속성 컴포넌트 안에 담거나 영속성 오퍼레이션을 비즈니스 로직 중간에 구행하는 것
  • 문법에 어긋나고 느리거나 권한이 없어 차단되는 데이터베이스 쿼리들이 사용자가 긴급하게 처리해야 하는 비즈니스 업무를 수행하지 못하도록 방해하는 것
    • QUESTION: 무슨 소리인지 전혀 감이 안오는 걸..🤔
  • 개발자가 실제 구체적인 비즈니스 요구 대신 현재와 상상 속 미래의 요구를 고려해서 과도하게 일반화시킨 해결 방안을 선택하여 잘못된 추상화가 존재하게 되는 것
  • 오퍼레이션을 수행하는 서비스가 또 다른 서비스를 직접 호출하는 강하게 결함된 서비스가 존재하여 시스템 유지보수를 어렵게 만들 뿐만 아니라 종종 비즈니스 프로세스에 문제를 일으키고 데이터가 불일치 하게 되는 것

설계에 대하여

"설계가 필수적인 것인지, 안 해도 괜찮은지에 대한 질문은 요점에서 많이 벗어나 있다. 설계는 필연적이다. 좋은 설계의 대안은 나쁜 설계다. 절대 설계하지 않는 것이 아니다." - 책 <Design: A Practical Introduction> by 더글라스 마틴

"대부분의 사람들은 '설계를 고민한다는 것이' '어떻게 생긴 것인지 고민하는 것'으로 착각한다. (...) 설계는 그게 어떻게 동작하는지에 대한 것이다. - 스티브 잡스

설계하지 않는다는 것은 없다. 5명의 소프트웨어 개발자가 설계 없이 프로젝트를 함께 진행하는 상황에서는 5개의 서로 다른 설계가 하나로 뭉뚱그려진 것을 만들 뿐이다. 즉, 개발자들은 진짜 도메인 전문가의 혜택을 받지 못한 채 개발하면서, 하나의 비즈니스 언어에 제각각 지어낸 5개의 해석을 혼합한 결과를 만드는 것이다.

옛날 도로는 오랜 기간 사용된 자국으로 만들어진 길이다. 몇 안 되는 사람들의 처음 필요에 의해 모퉁이와 갈림길이 생겼고, 일부는 편의를 위해 길을 다듬고 포장하기도 했다. 오늘날에 와서 이렇게 임시변통으로 만들어진 도로를 이동시키지 않는다. 이것은 도로가 잘 설계돼서가 아니라 이미 존재하기 때문이다. 현대 도로는 인구, 환경, 예측된 흐름에 대한 심층적인 연구에 따라 계획하고 설계한다. 이전 도로보다 편하다.

심사숙고한 설계로 소프트웨어를 제작하는 것이 비쌀 것 같아서 두렵다면, 앞으로 얼마나 계속 그 시스템을 사용해야 하고, 더 나아가 나쁜 설계를 수정해야 하는 것에 얼마나 더 큰 비용이 들 것인지 생각해야 한다.

전략적 설계

전략적 설계가 가장 중요하다. 전략적 설계부터 시작하지 않으면 전술적 설계를 효과적으로 적용할 수 없다. 전략적 설계는 1) 비즈니스에서 전략적으로 중요한 것과 2) 중요도에 따라 작업을 나누는 방법, 3) 필요에 따라 잘 통합하는 방법을 강조한다.

바운디드 컨텍스트 (Bounded Context, 이하 BC)

  • 도메인 모델을 분리하는 방법이다. 의미적으로 동일한 컨텍스트의 범위를 표현한다. 그 범주 내에서 소프트웨어 모델의 각 컴포넌트는 컨텍스트에 특화돼 있으며 컨텍스트 안에서 특정한 의미를 갖고, 특정한 일을 수행한다.
  • 바운디드 컨텍스트는 모델이 구현되는 곳이고, 바운디드 컨텍스트마다 각각 분리된 소프트웨어 산출물이 나온다.
  • BC를 사용하는 중요한 이유 중 한 가지는 각 팀이 각자의 도메인 모델을 작고 관리할 수 있는 정도에서 시작했지만 도메인 모델에 점점 더 많은 개념이 추가되어 커다란 문제로 발전하는 상황이다. 하나의 거대하고 혼란스럽고 경계가 제한되지 않은 모델 안에 너무 많은 개념이 존재하는 것은 물론, 다수의 언어가 혼재되면서 점차 모델 내의 언어가 모호해지기 시작한다. 이런 문제 때문에 새로운 소프트웨어 제품은 큰 진흙 덩어리처럼 만드는 팀이 종종 나타난다.
  • BC를 사용하는 것은 "핵심이 무엇인가?"라는 질문에 답하도록 유도한다. 핵심을 파악하기 위해서는 도메인 전문가와 소프트웨어 개발자가 긴밀하게 협업해야 한다.
  • BC는 한 덩어리로 뭉쳐 있지 않기 때문에 이를 사용하면 테스트를 하나의 모델에 집중할 수 있어서 테스트할 양이 적어지고 더 빨리 테스트를 수행할 수 있게 된다는 이점이 있다.
  • 각각의 BC는 단일 팀에만 할당돼야 하고, 각 BC마다 독립적인 소스 코드 레파지토리가 있어야 한다. BC마다 소스 코드와 데이터베이스 스키마도 명확히 분리한다. 메인 소스 코드와 함께 인수 테스트와 단위 테스트를 유지해야 한다.
    • QUESTION: 꼭 레파지토리를 분리해야 하나? 지금 힐링페이퍼에서 처럼 하나의 레파지토리에서 디렉토리나 프로젝트 등으로 분리해서 관리되기만 하면 되는 거 아닌가?
  • 한 팀은 다수의 BC에 대해 일을 할 수 있지만, 다수의 팀이 하나의 BC를 수행할 수 없다. 다른 팀이 소스 코드를 변경할 때 반갑지 않은 문제가 발생할 가능성을 완전히 제거할 수 있기 때문이다.
  • 각 팀은 각자의 소스 코드와 데이터베이스를 소유하고, 공식 인터페이스를 정의해서 BC를 다른 팀이 사용할 수 있게 허용한다. 이것이 DDD 사용의 이점이다.

핵심 도메인 (Codomain)

  • BC가 조직의 핵심 전략 계획으로 개발되고 있을 때 이를 핵심 도메인이라고 한다. 가치 있는 것들을 달성하는 수단이 되기 때문에 가장 중요한 소프트웨어 모델 중 하나다. 다른 조직과의 경쟁에 대한 차별화를 위해 개발하고, 이 때문에 최소한 하나의 주요 사업 부문을 다룬다.
  • 기업의 올바른 전략적 결정을 위해 무엇이 핵심 도메인이어야 하고, 어떤 것을 제외시켜야 하는지 현명하게 선택해야 한다. 이것이 DDD의 주된 가치 제안이고, 핵심 도메인에 최적의 자원을 투여해서 적절하게 투자해야 한다.
    • 이 부분을 보았을 때 흔히 말하는 BC를 나누는 과정에서 어떤 도메인에 자원을 많이 투자하고 어떤 도메인을 우선순위 낮출 것인지 결정하며 비즈니스 전략을 자야 한다는 이야기 같다. 힐링페이퍼는 이 부분을 더 고민해보면 좋겠다는 생각이 들었다. 모든 도메인의 거의 평등하게 고려되고 리소스가 분배된다. 또 일단 도메인이 분리되어 팀이 생기면 아무리 중요한 도메인의 리소스가 부족하더라도 정해진 도메인 팀을 변경하지 않는다.

보편 언어 (Ubiquitous Language)

  • BC 안에서 기능하는 소프트웨어 모델을 만드는 모든 팀 구성원이 사용하는 언어고, 이 언어의 대표적인 기록 형태는 소프트웨어 모델의 소스 코드다.
  • 보편언어 개발 시 개발자는 물론 도메인 전문가의 참여가 중요하다. 또한 소프트웨어 개발자와 도메인 전문가 팀이 협업하는 방법도 알게 된다. 협업을 통해 함께 개발한 보편언어는 팀 의사소통과 소프트웨어 모델 곳곳에 보편적이고, 널리 퍼져 있게 될 것이다.
  • 엄격하게 핵심만 걸러내어 정의한 이 개념들은 바운디드 컨텍스트를 소유하는 팀이 사용할 보편언어의 일부가 된다. 경계는 그 안의 엄격함을 강조한다.
  • 명사들이 꽤 중요한 역할을 갖고 있지만 일상생활에서는 명사를 단독으로 사용하는 것보다 훨씬 더 많은 말들을 함께 사용한다.

서브도메인 (Subdomain)

  • 전체 비즈니스 도메인의 하위 부분이다. 거대하고 복잡한 프로젝트에서 문제 영역을 이해할 수 있도록 전체 비즈니스 도메인을 논리적으로 쪼개는 데 서브 도메인을 사용할 수 있다.
  • 서브도메인 유형
    • 핵심 도메인
      • 보편언어를 신중하게 만들기 위한 전략적 투자 영역으로, 주요 자원을 할당하는 명시적인 바운디드 컨텍스트이며, 잘 정의된 도메인 모델이 존재한다.
      • 이 도메인은 경쟁자들에 대한 차별화를 만들 영역이기 때문에 기업의 프로젝트 목록에서 높은 우선순위를 갖는다.
    • 지원 서브도메인
      • 이미 존재하는 제품으로 해결할 수 없는 맞춤 제작 개발이 필요한 모델링 영역을 말한다.
      • 지원 서브도메인 없이 핵심 도메인을 성공시킬 수는 없기 때문에 여전히 중요한 소프트웨어 모델이다.
    • 일반 서브도메인
      • 기존 제품 구매를 통해 바로 충족시킬 수 있는 경우에 해당된다.
  • 레거시 시스템을 논할 때 그 안에 몇 가지 논리적 도메인 모델이 존재한다면 이것을 서브도메인으로 생각해볼 수 있다.
  • BC와 서브도메인은 일대일 관계를 맺어야 한다.
  • 만일 하나의 BC 안에 핵심 도메인과 다른 도메인이 있다면 완전히 분리된 모듈 형태로 별도의 영역에 정의해야 한다.

컨텍스트 매핑 (Context Mapping)

  • 여러 개의 바운디드 컨텍스트를 통합하는 방법이다.
  • 매핑의 종류
    • 파트너십
      • 두 팀은 일련의 목표에 대한 의존성에 맞추기 위해 파트너십을 구성한다. 두 팀이 함께 성공하거나 다같이 실패한다는 의미다.
      • 파트너십이 상호간 이점을 제공한다면 관계를 지속시키고, 서로의 의존성이 줄어들어 이점이 사라지는 상황이라면 다른 관계로 매핑을 설정해야 한다.
    • 공유 커널
      • 2개 이상의 팀 사이에 작지만 공통인 모델을 공유하는 관계를 나타낸다. 각 팀은 공유하는 모델 요소에 대해 서로 합의해야 한다.
      • 공유하는 모델의 코드, 빌드를 관리하고 테스트하는 것은 한 팀에서 맡아 수행한다.
    • 고객-공급자
      • 공급자는 고객이 원하는 것을 제공해야 하기 때문에 관계를 주도하는 것은 공급자다. 다양한 기대를 충족시키기 위해 공급자와 함께 계획하는 것은 고객의 역할이지만, 고객이 언제 무엇을 받게 될지는 결국 공급자가 결정한다.
    • 준수자 (Conformist)
      • 상류 팀이 하류 팀의 특정 요구에 지원할 동기가 없는 경우에 나타난다. 이런 상황에서는 하류 팀이 상류팀 모델을 그대로 따른다.
    • 반부패 계층 (Anticorruption Layer)
      • 가장 방어적인 컨텍스트 매핑 관계
      • 하류 팀이 그들의 보편언어 모델와 상류 팀의 보편언어 모델 사이에 번역 계층을 만드는 것이다.
    • 공개 호스트 서비스
      • 일련의 서비스처럼 BC에 대한 접근을 제공하는 프로토콜이나 인터페이스를 정의하고 공개한다.
      • 이 모델의 준수자가 되는 것이 수많은 레거시 시스템들을 맞닥뜨리는 것보다 괜찮은 선택일 수 있다.
    • 공표된 언어
      • BC의 규모와 관계없이, 간단한 사용과 번역을 가능하게 하는 잘 문서화된 정보 교환 언어다.
      • XML 스키마, JSON 스키마, 프로토버프 등의 형식으로 정의할 수 있다.
      • 공개 호스트 서비스는 서드파티에게 최상의 통합 경험을 줄 수 있는 공표된 언어를 제공한다.
    • 각자의 길 (Separate Ways)
      • 1개 이상의 BC를 통합으로 다양한 보편언어를 사용하는 것이 유의미한 결과를 제공하지 못하는 상황을 말한다. 찾는 기능을 다른 보편언어에서 완전히 제공하지 않을 것이다. 이 경우에는 BC 내에서 이를 위한 해결 방안을 만들고 통합은 잊어버리자.
  • 컨텍스트 매핑 활용하기
    • 데이터베이스 통합은 진짜 피해야 한다. 만일, 그래도 통합을 강요받는 상황이 된다면, 반드시 반부패 계층을 사용해서 여러분의 모델을 독립시켜야 한다.
    • 세 가지 통합 형태 (덜 견고한 방법에서 견고한 순으로)
      • SOAP을 이용한 RPC (Remote Procedure Calls)
        • 다른 시스템이 서비스를 사용할 때 마치 단순히 로컬 프로시저나 메서드를 호출하는 것처럼 사용한다는 개념이다.
        • 네트워크상에서의 요청, 원격 시스템에 요청 전달, 성공적 수행, 네트워크를 통한 결과 반환을 보장해야 한다.
        • BC 사이의 강한 결합을 암시한다.
      • RESTful HTTP
        • BC 간에 교환되는 리소스뿐만 아니라 POST, GET, PUT, DELETE 네 가지 주요 오퍼레이션들이 관여된다.
        • 이 방식이 분산 컴퓨팅에 적합한 API들을 정의하는 데 도움을 준다.
        • REST를 사용할 때 저지르는 흔한 실수는 도메인 모델 안에 직접적으로 애그리게잇을 반영하는 리소스를 설계하는 것이다. 이렇게 하면 모든 클라이언트에게 준수자 관계를 강요하면서 모델 변화가 리소스의 형태에 영향을 준다. 리소스가 클라이언트 주도의 유스케이스를 지원할 수 있도록 종합적으로 설계해야 한다.
      • 메시징
        • 비동기 메시징을 사용하면 여러분의 BC 또는 다른 BC가 발행하는 도메인 이벤트를 구독하는 클라이언트 BC가 많은 것을 할 수 있게 해준다.
        • 가장 견고한 형태 중 하나인데 이는 RPC나 REST와 달리 분절된 형태와의 일시적인 결합을 대부분 제거할 수 있기 때문이다.
        • 메시징 케머니즘은 적어도 한 번의 전달(At-least-once delivery)을 통해 모든 메시지의 수신을 보장해야 한다. 이는 구독 BC가 멱등 수신자(Idempotent Receiver)로 구현돼야 함을 의미한다.
        • 도메인 이벤트에 모두 담는 것과 다시 쿼리하는 것 사이의 장단점
          • 충분한 데이터를 모두 담으면 소비자들에게 큰 자율성을 허용할 수 있다.
          • 모든 소비자가 도메인 이벤트에 요구할 모든 데이터를 예측하는 것이 너무 어렵고 모든 것을 제공하려면 너무 많은 것을 담아야 할 수도 있다. 풍부한 도메인 이벤트를 제공하기 위해 보안적인 측면이 부실해질지도 모른다.

컨텍스트 맵 (Context Map)

  • 2개의 바운디드 컨텍스트를 통합하면서 그 사이에 존재하는 팀의 관계, 기술적 메커니즘을 정의한다.

큰 진흙 덩어리 (Big ball of Mud)

  • 시스템의 명확한 경계 없이 여러 개의 뒤엉킨 모델들을 담고 있는 것이다.
  • 다수의 팀이 이 모델을 활용해 일을 하게 된다면 아주 큰 문제가 될 수 있고, 서로 관련이 없는 다양한 개념들이 수많은 모듈로 확장되거나 어울리지 않는 모듈을 상호 연계시킬 수도 있다. 이런 상황에서는 프로젝트에서 테스트를 수행하는데 아주 오랜 시간이 걸릴 것이고, 이로 인해 중요한 시점에 이 테스트를 건너뛰어야만 하는 상황이 나타날 수도 있다.
  • 이는 너무 많은 사람들이 잘못된 방향으로 너무 많은 일을 하면서 제품을 만드는 것이나 마찬가지다. 결국 보편언어를 개발하고 사용하려는 모든 시도가 갈라지고, 불분명해져, 곧 버려질 모델들을 만들어낼 것이다.
  • 비즈니스 이해관계자들의 이야기에는 기술 담당 팀이 더 나은 모델을 만들 때 선택할 수 있게 도와주는 힌트들이 들어있다. 큰 진흙 덩어리는 이런 비즈니스 전문가의 이야기에 귀를 기울이지 않은 채, 소프트웨어 개발 팀이 제멋대로 노력한 결과다.
  • 이런 큰 진흙 덩어리를 만드는 것을 피하는 데 도움을 줄 수 있는 것이 BC와 보편언어다.
  • 큰 진흙 덩어리를 만들 때 발생하는 문제
    • 부적절한 연결과 의존으로 인해 문제를 확산시키는 애그리게잇이 증가한다.
    • 큰 진흙 덩어리 일부를 관리할 때는 두더지 잡기처럼 한 가지 문제가 해결돼도 또 다른 문제를 계속 야기시킬 수 있다.
    • 오직 전반적 지식과 모든 언어를 한 번에 다룰 수 있는 영웅 같은 사람이 있어야 시스템을 완전한 붕괴로부터 지킬 수 있다.
  • 큰 진흙 덩어리와 반드시 통합해야 한다면, 각 레거시 시스템에 대응한 반부패 계층을 만들어서 형편 없는 결과로부터 여러분의 모델을 보호해야 한다. 무슨 일이 있어도 그 언어를 섞어 쓰면 안 된다!

전술적 설계

  • 전술적 설계는 도메인 모델의 세부사항들을 그리기 위해 얇은 붓을 사용하는 것과 같다.

값 객체 (Value Object)

  • 말그대로 값이다. 값 객체가 어떤 것을 나타낸다기보다는 엔터티를 서술하고, 수량화하거나 측정하는 데 사용된다.
  • 엔터티와 달리 고유한 식별성이 없으며, 값 형태로 캡슐화된 속성을 비교함으로써 동일함이 결정된다.

엔터티 (Entity)

  • 다른 엔터티들과의 특성을 구별할 수 있는 고유한 식별성을 갖는다.
  • 엔터티는 변할 수 있는 것이다.

애그리게잇 (Aggregate)

  • 가장 중요한 도구 중 하나

  • 1개 이상의 엔터티로 구성되고 그중 한 엔터티는 애그리게잇 루트라고 부른다. 값 객체를 포함할 수 있다.

  • 애그리게잇의 루트 엔터티는 애그리게잇 안의 다른 모든 요소를 소유한다. 루트 엔터티의 명칭은 애그리게잇의 개념적 명칭이다. 애그리게잇이 모델링하는 개념적 완전성을 적절하게 표현할 수 있는 명칭으로 루트 엔터티 명칭을 정의해야 한다.

  • 각 애그리게잇은 일관성 있는 트랜잭션 경계를 형성한다. 트랜잭션 제어가 데이터베이스에 커밋될 때, 한 애그리게잇 내의 모든 구성 요소는 반드시 비즈니스 규칙을 따르면서 일관성 있게 처리된다는 것을 의미한다.

  • 애그리게잇 설계 규칙

    • 애그리게잇 결계 내에서 비즈니스 불변사항들을 보호하라
    • 작은 애그리게잇을 설계하라
    • 오직 ID를 통해 다른 애그리게잇을 참고하라
    • 결과적 일관성을 사용해 다른 애그리게잇을 갱신하라
  • 애그리게잇 구현에 대한 작업을 할 때 만나기 쉬운 몇 가지 낚싯바늘

    • 빈약한 도메인 모델 (Anemic Domain Model)
      • 객체지향 도메인 모델을 사용하면서 모든 애그리게잇이 비즈니스 행위가 아닌 읽고(getters) 쓰고(setters) 공개 접근자만을 갖는 것이다. 이는 모델링을 하면서 비즈니스보다는 기술적인 부분에 초점을 맞췄을 때 발생하는 경향이 있다.
      • 빈약한 모데인 모델을 설계하는 것은 도메인 모델이 주는 혜택을 받지 못하고, 모든 오버헤드를 떠안아버리는 상황을 만든다.
    • 비즈니스 로직이 도메인 모델을 넘어 애플리케이션 서비스까지 새어나가는 것
      • 비즈니스 로직을 헬퍼나 유틸리티 클래스에 위임하는 것은 원하는 대로 잘 동작하지 않는다. 서비스 유틸리티는 항상 정체성에 혼란을 주고, 요구사항을 올바르게 유지시키지도 못한다.
  • 추상화를 조심스럽게 선택하라

    • 효과적인 소프트웨어 모델은 항상 일을 하는 비즈니스의 방식을 고려한 일련의 추상화에 기반을 두고 있다.
    • 문제를 푸는 것에 지나치게 몰두한 나머지 소프트웨어 개발자가 지나칠 정도로 추상화를 적용하기도 한다.
    • 팀이 정의한 도메인 전문가의 멘탈 모델에 따라 보편언어를 모델링해야 한다.

도메인 이벤트 (Domain Event)

  • BC 내의 비즈니스 관점에서 중요한 사항들에 대한 기록이다.
  • 도메인 이벤트의 사용은 명확하게 모델링하는 것을 도와주면서, 도메인에 발생한 것에 대해 알아야 하는 내용을 시스템과 공유하는 것을 돕는다. 공유할 대상이 로컬의 바운디드 컨텍스트일 수도, 다른 원격의 바운디드 컨텍스트일 수도 있다.
  • 전술적 설계 노력을 통해 도메인 이벤트가 도메인 모델에 구체화되고, 도메인 이벤트가 만들어지면 BC와 다른 자원들은 이벤트를 받아 활용한다. 이는 중요한 이벤트에 관심이 있는 이벤트 리스너들에게 관련 상황의 발생을 알리는 매우 강력한 방법이다.
  • 이벤트 소싱: 애그리게잇 인스턴스에 대해 변경된 것에 대한 기록으로, 발생했던 모든 도메인 이벤트를 저장하는 것을 말한다.
© 2020 Wonny.