[DesignPattern] DDD 도메인 드리븐 디자인

Domain-Driven Design(이하 DDD)

  • 도메인이라는 개념 자체는 새로운 것이 아니다.
  • 개발의 기술적인 방법론과 접근 방법이 상충되기도 한다.

목적

개념 : Domain

도메인은 사용자가 사용하는(주목하는) 모든 것입니다.

예를 들어서 “고양이는 사과를 먹는다.”라는 상황에서 사용자는 다양한 것에 주목할 수 있습니다. 전통적인 OOP 개념에서 객체 혹은 대상은 고양이 사과뿐입니다.(객체는 추상화 또는 구체화할 수 있는 특징 요소라고 할 수 있습니다.) 하지만 DDD에서 도메인은 사용자가 바라보는 관점에 따라서 다양하고 또 변화할 수 있습니다.

  1. 고양이, 사과
  2. 먹는다.
  3. 사과를 먹는다.
  4. 고양이는 사과를 먹는다.

사용자가 개발자이고 개발자가 if문에 주목하다면 if문이 Domain이 되고, error handling에 주목한다면 이 부분도 Domain이 될 수 있습니다.

도메인을 정의하고 구성한다는 것은 사용자가 사용하는 영역을 정의하고 설계하는 것입니다. 도메인은 최소한의 요구사항이자 최대한의 요구사항이어야 합니다. 즉, 도메인으로 사용자가 사용하는 영역을 가장 작지만 사용자가 기능을 사용하기에 가장 효과적인 범위로 설정해야 합니다.

개념 : DDD

DDD는 소프트웨어를 이해하고 프로젝트를 성공적으로 완성하기 위한 사고방식 중 하나입니다. 도메인은 사용자와 사용자가 바라보는 관점에 따라 지속적으로 변화합니다. 도메인이 변하면 소프트웨어가 직접적으로 변경되어야 합니다. 이에 따라 발생하는 문제들을 어떻게 해결할지에 대한 사고방식입니다.

시스템의 구조는 설계하는 조직의 커뮤니케이션 구조를 닮는다(ConWay’s Law)는 말이 있습니다. 프로젝트에 참여하는 개발자, PM, 인프라 전문가들은 각자의 지식을 가지고 있습니다. 이들이 가지고 있는 전문적인 지식은 각기 다르기 때문에 협업을 통해서 공유하고 서로 맞추어가는 과정이 필요합니다. 예를 들어 DB 개발자는 세상을 DB Table로 이해하는 습관을 가지고 있습니다. 세상을 대응되는 Table로 생각하다가 어느 시점에서는 효율성을 위해 PK, FK를 통해 두 개의 Table로 나누어서 생각합니다. 당연하게도 다른 사람의 Domain은 DB 개발자의 Domain과 다릅니다. 그래서 협업이 필요하고 DDD가 반영된 소프트웨어는 수 많은 Domain의 집합체라고 할 수 있습니다.

DDD를 위한 협업

여러 사람이 가지고 있는 Domain이 다르면 의사소통에 문제가 생깁니다. 따라서 모든 사람이 동일한 의미로 이해하는 보편 언어(Ubiquitous language)가 필요합니다. 이상적으로 모든 전문자가가 자신의 Domain을 보편 언어로 번역해서 대화를 한다면, 한 번의 회의로도 충분합니다. 현실적으로는 각자의 프로세스를 일관된 보편 언어와 맞추기 위해 서로를 이해하기 위해 여러 번의 회의가 필요합니다.

진행 중인 프로젝트 전반에 대해 가장 많은 Domain 지식을 가지고 있는 사람을 도메인 전문가라고 합니다. 각 직군의 사고방식을 가장 넓게 알고 있거나, 진행 중인 프로젝트를 위해 각 직군에서 어떻게 해야하는지 알고 있는 사람이라고 할 수 있습니다.

도메인 전문가는 각 직군이 말하는 Domain을 먼저 이해하고 보편언어로 바꾸어서 의사소통을 원활하게 합니다. 하지만 추가적으로 각자의 도메인 지식을 어느 정도까지 소프트웨어에 반영할 수 있는지 판단해야 하고 이 부분이 어렵습니다. 어느 정도의 세부사항까지 소프트웨어로 구현될 수 있고, 어떠한 기술적 어려움이 예상되는지 개발자와 논의해야 합니다.

개발자 입장에서의 DDD

개발자의 전문 분야는 기술적인 것에 치중되어 있어서, 실제로 개발을 하면서 Domain을 의식하고 진행해야 합니다. 고민을 하지 않으면 정말 쉽게 DDD와 멀어집니다. DDD에서 소프트웨어는 Domain의 집합체로 정의하는데, 일부러 의식하지 않으면 소프트웨어의 결과에 집중하는하는 동안 Domain의 집합으로서의 소프트웨어의 본질을 잃을 수 있습니다.

DDD를 반영함에 따라 개발자는 설계나 개발 과정에서 Domain을 신경써야합니다. 예를 들어보면 DB Table의 Attribute name을 설정 할 때 보편 언어에 속하는 이름을 사용해야 합니다. 이렇게 하지 않으면 PM과 같은 도메인 전문가와 의사소통을 할 때 보편언어로의 변환을 한 번 거쳐야합니다.

이 때 관점에 따라서 개발자의 자율성이 좁아졌다고 볼 수도 있고, 넓어졌다고 볼 수도 있습니다. 개발자와 도메인 전문가의 표현이 다를 때는 보편 언어에 맞추어야 하기 때문에 개발자의 자율성이 좁아집니다. 반면에 개발자와 도메인 전문자의 표현이 동일하다면, 그 표현의 하위 영역에서 설계와 개발의 자율성이 주어집니다. 또 개발자의 관심이 기술적인 영역에서 도메인의 영역으로 넓어졌다고 생각할 수 있습니다. 즉, 개발자가 자유롭게 움직일 수 있는 영역이 달라집니다. 좁아지거나 넓어지는 것은 절대적이지 않습니다.

자율성, 복잡성, 일관성, 의존성

DDD에서 개발자가 Domain의 영역에서 멀어지는 방향으로 자율성을 키우면

  • 소프트웨어의 복잡성이 증가합니다.
  • 소프트웨어의 일관성이 없어집니다.

DDD에서 개발자가 Domain의 영역을 의식하면서 Domain의 내부에서 자율성을 키우면

  • 소프트웨어를 구성하는 요소들이 필요한만큼 연결되고, 일관성을 유지할 수 있습니다.

Domain 사이의 의존성은 아래와 같은 부작용을 가지고 옵니다.

  • 요구사항이나 기술적 요소가 변경되면 관련된 모든 것을 확인 및 변경해야 합니다.
  • 팀 사이의 의존 관계는 각 팀의 담당자들이 더 회의하도록 만듭니다.
  • 의존 관계가 많고 복잡할수록 인수인계 시간이 크게 늘어납니다.

인터페이스를 통한 의존성 관리

의존성이 높아지면 소프트웨어가 복잡해집니다. 하지만 의존 관계를 어쩔 수 없이 추가되어야 하는 경우가 있습니다. 이 때에는 인터페이스를 사용합니다. 인터페이스는 의존 객체의 기능을 제한적으로 사용할 수 있도록 한정하는데에 의미가 있습니다. 그래서 사용자 인터페이스라는 말도 사용자가 사용할 수 있는 기능을 제한한다는 의미와 범위 내에 포함된 기능을 쉽게 사용할 수 있도록 한다는 두 가지 의미가 있습니다.

의존성 관리는 사용자에게 제공할 인터페이스를 설계하고 정의하는 것을 말합니다. 이 과정에서 UX(User eXperience)를 고려해야 합니다. 연결 관계를 추가하면서 복잡도를 줄이기 위해서 인터페이스를 사용하고, 인터페이스를 어떻게 제공할 것인지를 판단하기 위해 UX를 고민합니다. 하지만 개발자가 UX까지 공부하기는 불가능하기 때문에 UX 디자이너, 다른 개발자, 기획자, 고객들의 요구사항대로 개발을 합니다.

의존성을 관리하는 패러다임에는 여러 가지 방법이 있습니다.

  • 애자일
  • 폭포수
  • 절자 치향 개발
  • 객체 지향 개발
  • 함수형 프로그래밍
  • Server Oriented Architectue
  • MSA
  • DDD

이 중에서 여러 개의 패러다임이 복합적으로 사용될 수 있습니다. 예를 들어 DDD와 MSA를 함께 사용할 수 있습니다. DDD를 적용하는지 여부를 판단하는 방법은 Domain의 개념이 적용되는지 여부를 보면됩니다. 바꿔말하면, 사용자가 생각하고 바라는 것 그대로 interface로 표현하느냐(DDD)와 내가 표현하는 interface를 사용자가 생각하고 바라보게 하느냐(non-DDD)로 말할 수 있습니다.

DDD가 적용된다면

사용자로부터 요구사항을 수집하고 최종적으로 배포할 때까지 모든 것을 Domain으로 일관성있게 유지할 수 있습니다. 사용자가 버그가 발생했다고 말하는 용어가 그대로 코드의 변수 이름이나 DB Table의 이름으로 대응되기 때문에 더욱 빠르게 대처할 수 있습니다.

문제점

역시 의사소통의 한계에서 문제가 발생합니다. 연과된 요소가 만흔 경우 Domain에 대한 해석이 서로 달라집니다. 서로 해석하는 것이 같더라도 말하는 표현이 조금이라도 달라지면 의사소통 문제가 발생하기 쉽습니다.

보완 방법

도메인이 설명하는 범위와 도메인 간의 경계를 명확히 드러내야 합니다. 이 경계를 Bounded Context라고 부릅니다.

보완 방법에 대한 이야기는 DDD를 직접 더 개발해본 뒤에 이해하도록 하겠습니다.

DDD — Bounded context

설계, 구현 단계에서의 DDD

Aggregates

WIP

Reference

Leave a comment