소프트웨어 개발 에는 늘 따라붙는 과제가 있습니다. 비즈니스 로직이 점점 복잡해질수록 코드 유지보수는 더욱 어려워진다는 것입니다. MVC 아키텍처 기반의 초기 CRUD 애플리케이션은 잘 작동하지만, 비즈니스 요구사항이 심화됨에 따라 개발팀은 "비즈니스 로직을 어디에 배치해야 할까?"라는 딜레마에 빠지게 됩니다.
도메인 주도 설계(DDD)는 이러한 문제를 해결하기 위해 개발되었습니다. 2003년 소프트웨어 전문가 에릭 에반스가 제안한 DDD는 비즈니스 도메인 지식을 시스템 설계의 핵심 동력으로 활용하여 비즈니스 요구사항에 부합하는 소프트웨어 모델을 구축하는 것을 목표로 합니다. DDD는 특정 아키텍처 스타일이 아니라, 복잡한 비즈니스 도메인을 경계 설정을 통해 단순화하고 명확한 도메인 및 애플리케이션 경계를 설계할 수 있도록 돕는 완벽하고 체계적인 설계 방법론입니다.
이 글에서는 DDD의 핵심 개념, 전략적 및 전술적 설계, 그리고 계층적 아키텍처를 체계적으로 설명합니다 . DDD를 처음 접하는 개발자든, 아키텍처 설계 역량을 향상시키고자 하는 제품 관리자나 아키텍트든, 이 글을 통해 영감을 얻을 수 있을 것입니다.
기존 개발 모델에서는 비즈니스 로직이 데이터베이스 연산 및 프레임워크 기능과 뒤섞여 코드 가독성이 떨어지고 유지보수 비용이 높아지는 경우가 많습니다. DDD(도메인 주도 개발)의 핵심 아이디어는 순수한 비즈니스 로직을 기술 구현에서 완전히 분리하여 개발자가 비즈니스 전문가처럼 생각할 수 있도록 하는 것입니다.
DDD의 핵심 원칙은 보편적인 언어를 확립하는 것입니다. 개발자, 테스터, 제품 관리자, 비즈니스 전문가를 포함한 모든 사람이 도메인 모델 기반의 통일된 공통 언어를 사용해야 합니다. 즉, 코드의 클래스 이름과 메서드 이름은 'DataProcessor'나 'Manager'와 같은 모호한 용어가 아닌 비즈니스 개념을 직접적으로 반영해야 합니다. 예를 들어, 전자상거래 시스템에서는 모든 로직을 담는 일반적인 'OrderService' 클래스 대신 'Order' 클래스와 그 안의 'place()' 메서드를 사용하는 것이 적절합니다.
DDD의 두 번째 핵심 개념은 핵심 도메인에 집중하는 것입니다. 복잡한 비즈니스 시스템에서는 각기 다른 하위 도메인이 서로 다른 비즈니스 가치를 지닙니다. 핵심 도메인은 비즈니스 성공의 핵심 요소이며 가장 많은 설계 노력이 필요합니다. 공통 도메인은 여러 하위 도메인이 공유하는 공통 기능을 담당하며, 지원 도메인은 다른 하위 도메인을 지원하는 인프라를 의미합니다.
DDD(도메인 주도 개발)는 전략적 설계와 전술적 설계라는 두 가지 차원으로 구성됩니다. 전략적 설계는 영역 분할 및 경계 정의에 초점을 맞춰 "무엇을 할 것인가"라는 문제를 해결하고, 전술적 설계는 구체적인 코드 구현에 초점을 맞춰 "어떻게 할 것인가"라는 문제를 해결합니다.

대규모 시스템을 다룰 때 단일 모델로 모든 비즈니스 영역을 포괄하려는 것은 비현실적입니다. DDD의 전략적 설계 부분은 복잡한 시스템을 분할하는 강력한 도구를 제공합니다.
도메인이란 기업이 해결해야 할 문제 영역을 의미합니다. 콘텐츠 커뮤니티 시스템을 예로 들면, 전체 " 콘텐츠 커뮤니티 "가 하나의 도메인이며, 이는 사용자 관리 , 독자 , 결제 , 커뮤니티 등 여러 하위 도메인 으로 나눌 수 있습니다 . 이 중 커뮤니티는 핵심 도메인에 속하고, 결제는 지원 도메인에 속할 수 있습니다.
핵심 요점: 전략적 설계에서 중요한 것은 비즈니스의 핵심 역량이 무엇인지 파악하고 해당 영역에 자원을 집중하는 것입니다.

이는 DDD(데이터 수요 및 의사 결정)에서 가장 중요한 전략적 패턴입니다. 모델의 적용 범위를 명확하게 정의하는데, 즉 "이 단어는 어떤 경계 내에서 의미를 갖는가?"를 명확히 합니다. 예를 들어, 전자상거래 상품의 맥락에서 "제품"은 가격, 설명, 카테고리와 같은 속성을 가지는 반면, 물류 맥락에서 "제품"은 무게와 부피에 더 중점을 둡니다.
각각의 경계 컨텍스트는 독립적인 "의미론적 경계"이며, 통일된 공통 언어와 도메인 모델을 가지고 있습니다. 따라서 시스템은 응집력이 높고 결합도가 낮은 여러 모듈로 분해됩니다.
핵심 원칙: 경계 컨텍스트는 컨텍스트 매핑을 통해 다른 컨텍스트와의 관계를 명확히 함으로써 모델 오염을 방지합니다.

DDD(데이터 의존성 분석)와 마이크로서비스 아키텍처는 자연스러운 조합입니다. 잘 설계된 바운디드 컨텍스트는 마이크로서비스의 좋은 후보가 될 수 있습니다. 반대로, 시스템을 기술적 계층에 따라 맹목적으로 분리하면 분산형 모놀리스가 되기 쉽습니다. 서비스는 분리될 수 있지만 결합도는 여전히 남아 있습니다. 마이크로서비스 아키텍처에서 서비스는 애그리게이트보다 작아서는 안 되며, 바운디드 컨텍스트보다 커서도 안 됩니다.
제한된 컨텍스트 내에서 DDD는 도메인 모델을 구축하기 위한 일련의 전술적 모델링 도구를 제공합니다.
엔티티는 고유 식별자와 생명주기를 가진 객체입니다. 예를 들어, 사용자가 이름을 바꾸더라도 고유 ID는 그대로 유지되며, 여전히 동일한 엔티티로 간주됩니다. 엔티티는 일반적으로 비즈니스 동작이 엔티티 내부에 캡슐화되는 풍부한 모델을 사용합니다.
값 객체는 고유 식별자가 없으며 속성 값으로만 구분되고 일반적으로 불변합니다. 예를 들어 금액(Money)은 통화와 가치에 따라 결정되며, 동일한 금액과 통화를 가진 두 Money 값은 서로 교환 가능합니다. 값 객체를 적절히 사용하면 시스템 복잡성을 줄일 수 있습니다. 예를 들어 주소, 이메일 주소, 전화번호는 모두 값 객체로 모델링할 수 있습니다.
애그리게이션은 전체적으로 관리되는 관련 엔티티 및 값 객체의 모음입니다. 애그리게이션 루트는 애그리게이션 내의 핵심 엔티티로서, 애그리게이션 내의 일관성을 유지하는 역할을 합니다. 예를 들어, Order 애그리게이션 루트는 OrderItem 및 Payment 엔티티를 관리하며, 주문 항목에 대한 모든 접근은 Order 애그리게이션 루트를 통해서만 이루어져야 합니다.
애그리게이트 설계 원칙: 애그리게이트 경계 내의 트랜잭션은 일관성을 유지해야 합니다. 다른 애그리게이트에 대한 참조는 식별자를 통해서만 이루어져야 하며, 애그리게이트 간의 직접적인 참조는 피해야 합니다. 애그리게이트는 가능한 한 작게 설계되어야 합니다.
이는 초보자들이 흔히 혼란스러워하는 개념입니다. 도메인 서비스는 엔티티나 값 객체에 귀속될 수 없는 도메인 동작을 수행합니다. 도메인 계층에 속하며, 도메인 고유성을 유지하고, 기술적인 세부 사항을 포함하지 않습니다. 예를 들어, TransferService는 계좌 간 이체를 처리합니다. 이는 특정 계좌 엔티티에 속하지는 않지만 핵심 비즈니스 로직입니다.
애플리케이션 서비스는 도메인 객체와 도메인 서비스를 조정하고, 애플리케이션 워크플로우를 처리하며, 애플리케이션 계층에 속합니다. 애플리케이션 서비스는 상태를 저장하지 않으며, 유스케이스 스케줄링, 트랜잭션 관리, 보안 인증을 담당하지만 비즈니스 규칙은 포함하지 않습니다.
리포지토리는 도메인 계층과 인프라 계층 사이의 가교 역할을 합니다. 도메인 계층에서는 추상 인터페이스로 정의되고, 인프라 계층에서는 구체적인 저장 로직을 구현합니다. 리포지토리는 집계를 통한 접근 메서드만 제공하며, ORM 관련 세부 정보는 노출하지 않습니다.
도메인 이벤트는 특정 도메인 내에서 발생하는 의미 있는 비즈니스 이벤트로, 후속 비즈니스 로직을 트리거하고 모듈 간 결합도를 낮추는 데 사용할 수 있습니다.

DDD는 일반적으로 사용자 인터페이스 계층, 애플리케이션 계층, 도메인 계층 및 인프라 계층의 네 가지 계층으로 구성된 계층형 아키텍처를 권장합니다.
이 컴포넌트는 사용자와 상호 작용하고, 요청을 수신하고, 응답을 반환하는 역할을 합니다. 웹 애플리케이션에서는 컨트롤러에 해당하지만, 매개변수 유효성 검사 및 결과 형식 지정만 담당하고 비즈니스 로직은 포함하지 않습니다.
도메인 객체는 비즈니스 사용 사례를 완료하도록 조정되며, 트랜잭션 경계, 보안 및 인증을 처리합니다. 애플리케이션 계층 서비스는 상태를 유지하지 않고 도메인 서비스 또는 집계 루트 메서드만 호출하며 비즈니스 규칙을 포함하지 않습니다.
DDD의 핵심은 모든 비즈니스 규칙과 모델을 포함합니다. 비즈니스 로직의 무결성을 보장하기 위해 애그리게이트 루트, 엔티티, 값 객체 및 도메인 서비스를 정의합니다.
데이터베이스 접근, 메시지 큐, 외부 API 호출과 같은 기술 구현 지원을 제공합니다. 의존성 역전 원칙을 통해 도메인 계층은 인터페이스를 정의하고 인프라 계층은 이를 구현하여 비즈니스 로직과 기술 구현 간의 완벽한 분리를 달성합니다.
DDD(도메인 주도 설계) 계층형 아키텍처에서는 의존성이 외부에서 내부로 향합니다. 사용자 인터페이스 계층은 애플리케이션 계층에 의존하고, 애플리케이션 계층은 도메인 계층에 의존하며, 인프라 계층의 인터페이스는 의존성 역전 원리를 통해 도메인 계층에서 정의됩니다. 도메인 계층은 특정 프레임워크나 기술에 의존하지 않으므로 핵심 비즈니스 로직을 수정 없이 다른 기술로 대체할 수 있습니다.

DDD(도메인 주도 설계)의 실제 구현에서 시각화는 팀의 합의 도출에 매우 중요한 단계입니다. 전략적 설계 단계의 경계 컨텍스트 정의든 전술적 설계 단계의 도메인 모델 구축이든, 명확한 다이어그램은 필수적입니다. 전문 온라인 다이어그램 도구인 ProcessOn은 DDD 아키텍처의 전체 프로세스 시각화를 효율적으로 지원합니다.
1. ProcessOn 프로필 페이지로 이동하여 "흐름도"를 만들거나 템플릿 커뮤니티에서 DDD 아키텍처 설계와 같은 키워드를 검색하세요.
2. 왼쪽의 "더 많은 그래픽" 아래에서 순서도 및 UML 다이어그램과 같은 그래픽 범주를 선택하여 그래픽 라이브러리에 추가할 수 있습니다. 그래픽 라이브러리에서 사각형이나 원과 같은 도형을 캔버스로 드래그 앤 드롭하고, 화살표가 있는 선을 사용하여 여러 요소를 연결하여 종속성을 표현할 수 있습니다.
3. 하나 이상의 요소가 선택되면 상단 툴바에서 서로 다른 색상을 사용하여 모델의 여러 레벨을 구분할 수 있을 뿐만 아니라 그래픽 정렬 및 레이어 설정과 같은 레이아웃 조정을 수행할 수 있습니다.

4. 다이어그램 작성이 완료되면 오른쪽 상단의 공유 버튼을 클릭하여 DDD 아키텍처 다이어그램을 동료 또는 고객과 공유하고 지속적인 모델 반복 작업을 진행할 수 있습니다. 또한 고해상도 이미지, PDF, SVG 또는 기타 형식으로 내보내어 나중에 참조할 수 있습니다.
도메인 주도 설계는 단순히 기술 패턴이나 아키텍처 명세의 집합이 아닙니다. 이는 소프트웨어의 핵심적인 복잡성을 다루는 사고방식의 혁명이자 체계적인 방법론입니다. 도메인 주도 설계는 소프트웨어 개발이 테이블을 만드는 것에서 시작하는 것이 아니라 비즈니스를 이해하는 것에서 시작해야 한다는 것을 가르쳐줍니다.
DDD(도메인 주도 설계)는 전략적으로 도메인 경계를 정의하고, 전술적으로 응집력 높은 도메인 모델을 설계하며, 계층형 아키텍처를 통해 비즈니스 로직과 기술 구현을 분리함으로써 복잡한 비즈니스 시스템의 유지보수성과 확장성을 크게 향상시킬 수 있습니다. 특히 마이크로서비스 시대에 DDD에서 제공하는 경계 컨텍스트 파티셔닝 방식은 마이크로서비스를 과학적으로 분해하는 데 있어 최적의 방법입니다.