🐱 Meow, meow
도메인 주도 설계(DDD, Domain-Driven Desigin) 는 여전히 많은 기업과 개발자들 사이에서 각광을 받고 있다.특히, 마이크로서비스 아키텍처(MSA) 가 확산이 되면서, DDD 의 개념이 적극적으로 활용되고 있다.
그렇다면, 도메인 주도 설계는 무엇이며, 도메인 주도 설계의 사실과 오해에 대해서 알아보자.
Intro
들어가기에 앞서서, 도메인 주도 설계가 처음 이야기 되었을 때와 현재의 도메인 주도 설계는 조금은 다르다고 할 수 있다.
하지만, 초창기의 도메인 주도 설계의 철학과 핵심 원칙에서는 크게 벗어나지는 않는다.
개인적으로는 에릭 에반스가 작성한, “도메인 주도 설계 - 소프트웨어의 복잡성을 다루는 지혜” 라는 책은 개발자라면, 읽어보기를 권장하고 싶고,
Nextstep 에서 진행하는 조영호님의 강의인 “도메인 주도 설계의 사실과 오해”도 추천한다.
DDD 란 무엇인가?
도메인 주도 설계(Domain-Driven Design, DDD) 는 복잡한 비즈니스 도메인을 효과적으로 다루기 위해 도메인 중심의 사고방식과 설계 원칙을 적용하는 철학적인 관점 에 가깝다.
특정한 방법론이나 아키텍처가 아니라, 순수하게 비즈니스 중심으로 사고하는 방식 이다.
DDD 의 철학과 핵심 원칙
DDD 의 핵심 철학
DDD 의 핵심 철학은
복잡한 소프트웨어를 효과적으로 관리하고, 비즈니스 문제를 올바르게 모델링하여 해결 하는 것
이다.
단순히 코드 작성하는 것이 아닌, 도메인 전문가와 개발자가 협력하여 도메인을 깊이 이해하고, 이를 소프트웨어에 반영하는 방식 을 추구한다.
DDD 는 화려한 기술이나, 기법, 마법이 아니라
복잡한 소프트웨어를 효과적으로 관리하는 철학과 전략
이라고 할 수 있다.
📘 Note - DDD 는 복잡성을 관리하고 문제를 협력적으로 해결하기 위한 것이다.
📌 복잡성 관리 - 복잡한 비즈니스 도메인을 효과적으로 다루기 위한 접근 방식✏️ 복잡한 소프트웨어를 관리 가능한 형태로 모델링한다.
✏️ 불필요한 복잡성을 제거하고, 필요한 복잡성을 효과적으로 관리한다.
📌 협력적 문제 해결 - 도메인 전문가와 개발자 간의 지속적인 협력
✏️ 공통된 언어(유비쿼터스 언어) 를 통한 효과적인 의사소통이 필요하다.
✏️ 비즈니스 문제에 대한 공동의 이해를 바탕으로 해결 방안을 도출한다.
DDD 의 철학을 이루는 핵심 원칙
📌 도메인과 모델 우선 (핵심 철학)
소프트웨어의 본질은 도메인의 개념과 로직을 표현하는 것이다.
“소프트웨어는 현실 세계의 복잡성을 해결하기 위한 것이므로, 도메인을 깊게 이해하고 모델을 만들어야 한다.”
- 기술적 해결책 보다 비즈니스 도메인 문제 해결 을 우선시 한다.
- 도메인 전문가와 협력하여 비즈니스 개념을 정확히 반영 해야 한다.
- 도메인을 단순화 하고, 핵심 개념을 명확히 모델링 해야한다.
📌 유비쿼터스 언어 (Ubiquitous Language)
모든 이해관계자가 같은 언어를 사용해야 한다.
“도메인 전문가와 개발자가 같은 용어를 사용해야 오해를 줄이고 효과적으로 협업할 수 있다.”
- 도메인 전문가와 개발자가 동일한 언어를 사용하여 커뮤니케이션해야 혼선이 일어나지 않는다.
- 이 언어는 코드, 문서, 대화에서 일관되게 유지되어야 한다.
- 모델과 코드가 유비쿼터스 언어를 반영해야 한다.
📌 바운디드 컨텍스트 (Bounded Context)
모델의 적용 범위를 명확히 정의 해야한다.
“하나의 모델이 모든 곳에 통하지 않는다. 바운디드 컨텍스트를 설정한다.”
- 하나의 도메인을 여러개의 경계(Context) 로 나눈다.
- 각 컨텍스트 내에서 유비쿼터스 언어를 일관되게 적용한다.
- 컨텍스트 간 관계를 명확히 정의하고, 통합 전략을 고민해야 한다.
📌 어그리게이트 (Aggregate)
모델을 더 작은 단위로 구조화해야 한다.
“무질서한 객체들 대신, 일관성과 응집력을 가진 어그리게이트를 만들자.”
- 어그리게이트는 도메인 객체의 논리적 그룹이며, 일관성을 유지하는 단위이다.
- Root Entity 가 변경을 관리하고, 외부에서 직접 내부 객체를 조작할 수 없다.
- 트랜잭션 범위를 고려하여 적절한 크기로 모델링 해야 한다.
📌 도메인 이벤트 (Domain Event)
비즈니스 흐름을 명확하게 표현해야 한다.
“중요한 상태 변화는 이벤트로 명확하게 드러내자.”
- 도메인 내에서 중요한 상태 변화를 이벤트로 표현한다.
- 이벤트 기반 설계를 활용하여 시스템 간 결합도를 낮춘다.
- 이벤트는 과거 시제로 표현하며, 도메인 로직의 핵심 흐름을 반영해야 한다.
📌 리포지토리 (Repository)
도메인 객체의 저장과 검색을 추상화해야 한다.
“데이터베이스가 아니라, 도메인 개념을 중심으로 접근하자.”
- 리포지토리는 어그리게이트를 저장하고 검색하는 역할을 한다.
- 도메인 로직에서 직접 데이터베이스 기술을 다루지 않는다.
- 트랜잭션을 고려하여 적절한 데이터 접근 전략을 수립한다.
📌 어플리케이션 서비스 vs 도메인 서비스
도메인 로직과 어플리케이션 로직을 명확히 분리해야 한다.
“비즈니스 로직과 어플리케이션 로직을 혼합하지 말자.”
- 도메인 서비스 : 어그리게이트에 속하지 않는 도메인 로직을 처리한다.
- 어플리케이션 서비스 : 트랜잭션, 외부 API 호출 등 어플리케이션 수준의 처리를 담당한다.
- 도메인 로직은 도메인 모델 내에서 처리하고, 어플리케이션 로직은 별도로 관리해야 한다.
📌 전략적 설계 (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) |
---|---|---|
목적 | 작은 문제 해결, 유지보수 용이한 코드 배치 | 도메인 중심의 사고방식 적용 |
초점 | 데이터 와 알고리즘 을 객체 단위로 배치 | 비즈니스 도메인 로직을 중심으로 코드 구성 |
본질 | 기술적인 개념이 중심 | 도메인의 본질을 코드로 표현하는 것이 중심 |
모델링 범위 | 클래스, 인터페이스 등 기술적인 모델링 | 바운디드 컨텍스트를 기반으로 도메인 모델링 |
변경 관리 | 리팩토링을 통해 설계 개선 | 도메인 전문가와 협업하여 지속적 리팩토링 |
현대의 DDD
📌 CQRS 와 이벤트 소싱의 도입
- 현래 DDD 의 일부는 아니었지만, 최근에는 복잡성을 해결하기 위해서 활용되고 포함해서 이야기 된다.
- CQRS 는 읽기/쓰기 모델을 분리하여 성능을 개선할 수 있다.
- 이벤트 소싱을 통해 상태 변경 이력을 추적 가능하게 한다.
📌 MSA 와 DDD 의 관계
- 바운디드 컨텍스트를 기반으로 MSA 를 설계 할 수 있다.
- 그러나 DDD 를 한다고 반드시 MSA 를 도입할 필요는 없다.
📌 전략적 설계와 전술적 설계의 발전
- 현대의 DDD 에서는 구체적인 전술 패턴(CQRS, 이벤트 소싱)과 전략 패턴(바운디드 컨텍스트, 컨텍스트 맵 등)이 발전
📌 점진적 도입 강조
- 핵심 도메인부터 적용하고, 점신적으로 확장하는 방식이 현실적이다.
- 처음부터 완벽한 설계를 하려 하기 보다 반복적인 리팩토링과 피드백을 통해 발전
CQRS (Command Query Responsibility Segregation) 란?
CQRS는 “명령(Command)와 조회(Query) 의 책임을 분리하는 아키텍처 패턴” 이다.
즉, 읽기(조회)와 쓰기(명령)을 별도의 모델로 나누어 설계하는 방식이다.
📌 CQRS 의 핵심 개념
- Command (명령)
- 생성, 수정, 삭제와 같이 데이터를 변경하는 작업
- 데이터 일관성과 트랜잭션을 유지하는 것이 중요
- Query (조회)
- 검색, 조회와 같이 데이터를 읽는 작업
- 성능 최적활르 위해 별도의 읽기 모델을 구성할 수 있다.
📌 CQRS 를 왜 사용할까?
✅ 읽기/쓰기 성능 최적화가 가능하여 조회가 많은 시스템에서 빠른 성능을 제공할 수 있다.
✅ 읽기와 쓰기를 각각 독립적으로 확장 가능하여 확장성이 향상된다.
✅ 복잡한 도메인 로직을 분리하여 유지보수성이 개선된다.
But,,
⚠️ 구현이 복잡해지고 유지보수가 어려워 질 수 가 있다.
⚠️ 데이터 동기화가 필요할 수 있다.
📗 요약
🖐 DDD 의 핵심 철학은 비즈니스 도메인을 깊게 이해하고 소프트웨어에 정확히 반영하는 것이다.🖐 DDD 는 모든 프로젝트에 적용해야만 하는 것은 아니고, 비즈니스 복잡성에 따라 적절히 활용하는 것이다.
🖐 핵심 도메인에 집중하고, 변화에 유연하게 대응할 수 있도록 설계하는 것이 철학이라고 볼 수 있다.
🖐 DDD 를 적용한다면 모든 문제를 해결할 수 있다는 것은 잘못됐다. 왜냐면 DDD 는 철학과 사상에 가깝기 때문이다.
🖐 도메인 전문가와 개발자가 끊임 없이 협력 유비쿼터스 언어로 소통하고 발전해나가는 것이 중요하다.