Intro
DDD 란 무엇인가?
DDD 의 철학
단순히 코드를 작성하는 것이 아니라, 도메인 전문가와 개발자가 협력하여 도메인을 깊이 이해하고, 이를 소프트웨어에 반영하는 방식 을 추구하는 것이고,
DDD 는 화려한 기술이나 기법, 마법이 아니라, 복잡한 소프트웨어를 효과적으로 관리하는 철학과 전략 이라고 할 수 있다.
DDD 의 핵심 원칙
1) 도메인과 모델 우선 (핵심 철학)
소프트웨어는 현실 세계의 복잡성을 해결하기 위한 것이므로, 도메인을 깊게 이해하고 모델을 만들어야 한다.
- 기술적인 해결책 보다는 비즈니스 도메인 문제 해결을 우선시 한다.
- 도메인 전문가와 협력하여 비즈니스 개념을 정확히 반영 해야 한다.
- 도메인을 단순화 하고, 핵심 개념을 명확히 모델링 해야 한다.
2) 유비쿼터스 언어 (Ubiquitous Language)
도메인 전문가와 개발자가 같은 용어를 사용해야 오해를 줄이고, 효과적으로 협업할 수 있다.
- 도메인 전문가와 개발자가 동일한 언어를 사용하여 커뮤니케이션해야 혼선이 일어나지 않는다.
- 이 언어는 코드, 문서, 대화에서 일관되게 유지되어야 한다.
- 모델과 코드가 유비쿼터스 언어를 반영해야 한다.
3) 바운디드 컨텍스트 (Bounded Context)
하나의 모델이 모든 곳에 통하지 않으므로, 모델의 적용 범위를 명확히 정의하는 바운디드 컨텍스트를 설정한다.
- 하나의 도메인을 여러개의 경계(Context) 로 나눈다.
- 각 컨텍스트 내에서 유비쿼터스 언어를 일관되게 적용한다.
- 컨텍스트 간 관계를 명확히 정의하고, 통합 전략을 고민해야 한다.
4) 어그리게이트 (Aggregate)
무질서한 객체들 대신, 모델을 더 작은 단위로 구조화하여 일관성과 응집력을 가진 어그리게이트를 만들자.
- 어그리게이트는 도메인 객체의 논리적 그룹이며, 일관성을 유지하는 단위이다.
- Root Entity 가 변경을 관리하고, 외부에서 직접 내부 객체를 조작할 수 없다.
- 트랜잭션 범위를 고려하여 적절한 크기로 모델링 해야 한다.
5) 도메인 이벤트 (Domain Event)
비즈니스 흐름을 명확하게 표현하기 위해 중요한 상태 변화는 이벤트로 명확하게 드러내자.
- 도메인 내에서 중요한 상태 변화를 이벤트로 표현한다.
- 이벤트 기반 설계를 활용하여 시스템 간 결합도를 낮춘다.
- 이벤트는 과거 시제로 표현하며, 도메인 로직의 핵심 흐름을 반영해야 한다.
6) 리포지토리 (Repository)
데이터베이스가 아니라, 도메인 개념을 중심적으로 접근하여 도메인 객체의 저장과 검색을 추상화한다.
- 리포지토리는 어그리게이트를 저장하고 검색하는 역할을 한다.
- 도메인 로직에서 직접 데이터베이스 기술을 다루지 않는다.
- 트랜잭션을 고려하여 적절한 데이터 접근 전략을 수립한다.
7) 어플리케이션 서비스 vs 도메인 서비스
도메인 로직과 어플리케이션 로직을 명확히 분리하여 비즈니스 로직과 어플리케이션 로직을 혼합하지 않는다.
- 도메인 서비스 : 어그리게이트에 속하지 않는 도메인 로직을 처리한다.
- 어플리케이션 서비스 : 트랜잭션, 외부 API 호출 등 어플리케이션 수준의 처리를 담당한다.
- 도메인 로직은 도메인 모델 내에서 처리하고, 어플리케이션 로직은 별도로 관리해야 한다.
8) 전략적 설계 (Strategic Design)
DDD 는 단순한 전술적 패턴이 아니라 전략적 사고를 요구하므로 시스템 전체적인 설계를 고려해야 한다.
- 핵심 도메인(Core Domain) 을 식별하고, 여기에 집중해야 한다.
- 지원 서브도메인(Supporting Subdomain) 과 범용 서브도메인(Generic Subdomain)을 구분해야 한다.
- 도메인의 전략적 우선순위를 정하고, 각 컨텍스트 간 협력 관계를 정의해야 한다.
DDD 핵심 원칙의 흐름
도메인 이해 → 유비쿼터스 언어 정립 → 바운디드 컨텍스트 설정 → 모델 구조화(어그리게이트, 이벤트, 리포지토리) → 전략적 설계 적용
DDD 의 철학은 소프트웨어가 도메인을 정확하게 반영해야 한다는 원칙 을 중심으로 전술적 패턴과 전략적 설계 로 체계화하는 것이다.
DDD 에 대한 사실 DDD 에 대한 사실과 오해
질문 | 사실 ✅ |
---|---|
특정한 아키텍처(ex: 헥사고날, MSA)를 강제하나요? | 특정한 아키텍처를 강제하지 않지만, 다양한 아키텍처에서 적용 가능하다. |
도메인 모델을 처음부터 완벽하게 설계 해야하나요? | DDD 는 반복적인 개발과 피드백을 통한 도메인 모델을 개선 하는 방식이다. |
도메인 모델이 하나여야 하나요? | 하나의 시스템에서 여러개의 도메인 모델이 존재 할 수 있다.(바운디드 컨텍스트) |
기술적인 요소보다 비즈니스 로직이 우선되어야 하나요? | DDD 의 핵심은 비즈니스 로직을 먼저 고려 하는 것이다. |
복잡한 도메인을 다룰 때 효과적인가요? | 비즈니스 로직이 복잡한 경우 DDD 를 적용하면 효과적이다. |
도메인 전문가와의 협업은 필수 인가요? | 개발자와 도메인 전문과는 밀접한 관계를 가져야하고, 도메인 전문가와의 협업은 DDD 의 핵심요소 중 하나다. |
❌ DDD 에 대한 오해 - MSA, 헥사고날, CQRS..
질문 | 오해 ❌ |
---|---|
반드시 MSA 나 헥사고날 아키텍쳐를 해야 하나요? | 무조건 MSA 를 해야 한다는 것은 오해이고, MSA 가 각광을 받으면서 설명하기 쉬우니 DDD 로 예를 드는 것이다. 도메인 레이어만 분리가 잘되어 있다면 헥사고날이든 MSA 든 필요가 없다. |
처음부터 모든 모델을 이벤트 스토밍으로 정의 해야 하나요? | 한 번에 모든 모델을 정의하는 것은 아니다. |
CQRS 는 원래 DDD 의 일부였나요? | CQRS 는 시스템 복잡성을 낮추기 위해서 나온 것이고, DDD 는 복잡도가 높으면 나누자였는데, 현대의 DDD 에서는 CQRS 가 포함되는데, CQRS 가 DDD 의 복잡성을 해결하기 때문이다. |
모든 프로젝트에서 반드시 필요한가? | 비즈니스 로직이 복잡한 프로젝트에는 적합 하지만, 단순한 CURD 시스템에서는 오히려 부담이 될 수 있다. |
❌ DDD 에 대한 오해 - OOP
구분 | 객체지향(OOP) | 도메인 주도 설계(DDD) |
---|---|---|
목적 | 작은 문제 해결, 유지보수 용이한 코드 배치 | 도메인 중심의 사고방식 적용 |
초점 | 데이터 와 알고리즘 을 객체 단위로 배치 | 비즈니스 도메인 로직을 중심으로 코드 구성 |
본질 | 기술적인 개념이 중심 | 도메인의 본질을 코드로 표현하는 것이 중심 |
모델링 범위 | 클래스, 인터페이스 등 기술적인 모델링 | 바운디드 컨텍스트를 기반으로 도메인 모델링 |
변경 관리 | 리팩토링을 통해 설계 개선 | 도메인 전문가와 협업하여 지속적 리팩토링 |
1) CQRS 와 이벤트 소싱의 도입 현대의 DDD
- 현래 DDD 의 일부는 아니었지만, 최근에는 복잡성을 해결하기 위해서 활용되고 포함해서 이야기 된다.
- CQRS 는 읽기/쓰기 모델을 분리하여 성능을 개선할 수 있다.
- 이벤트 소싱을 통해 상태 변경 이력을 추적 가능하게 한다.
- 바운디드 컨텍스트를 기반으로 MSA 를 설계 할 수 있다.
- 그러나 DDD 를 한다고 반드시 MSA 를 도입할 필요는 없다.
- 현대의 DDD 에서는 구체적인 전술 패턴(CQRS, 이벤트 소싱)과 전략 패턴(바운디드 컨텍스트, 컨텍스트 맵 등)이 발전
- 핵심 도메인부터 적용하고, 점신적으로 확장하는 방식이 현실적이다.
- 처음부터 완벽한 설계를 하려 하기 보다 반복적인 리팩토링과 피드백을 통해 발전
CQRS (Command Query Responsibility Segregation) 란?
- Command (명령)
- 생성, 수정, 삭제와 같이 데이터를 변경하는 작업
- 데이터 일관성과 트랜잭션을 유지하는 것이 중요
- Query (조회)
- 검색, 조회와 같이 데이터를 읽는 작업
- 성능 최적활르 위해 별도의 읽기 모델을 구성할 수 있다.
- 읽기/쓰기 성능 최적화가 가능하여 조회가 많은 시스템에서 빠른 성능을 제공할 수 있다.
- 읽기와 쓰기를 각각 독립적으로 확장 가능하여 확장성이 향상된다.
- 복잡한 도메인 로직을 분리하여 유지보수성이 개선된다.