Search
🏗️

도메인 주도 설계의 사실과 오해 (1) DDD 요약

Tags
Architcture
DDD
Study
Last edited time
2024/11/01 00:24
2 more properties
Search
도메인 주도 설계의 사실과 오해 - 요약 및 목차
도메인 주도 설계의 사실과 오해 - 요약 및 목차

1. Preface

1.1. 소프트웨어 및 도메인 주도 설계의 본질

소프트웨어의 본질
그 소프트트웨어의 사용자를 위해 도메인에 관련된 문제를 해결하는 능력에 있다.
도메인 주도 설계의 핵심
도메인 주도 설계는 복잡한 도메인을 다뤄야 하는 소프트웨어 프로젝트에 박차를 가하는 것을 목표로 삼는 사고 방식이자 우선순위의 모음이다.

1.2. 객체지향과 도메인 주도 설계

도메인 주도 설계는 객체지향과 애자일의 관점이 섞여있음
이 책은 객체 모델링을 어떻게 실제 소프트웨어 프로젝트에 적용할 것인지에 대해 미처 몰랐던 부분을 채워주고 시각 또한 향상 시킬 것이다. - 도메인 주도 설계 ‘서문’ 중에서
1990년대 ~ 2000년대: 객체의 시대
GUI 기반의 서비스/프로그램들. GUI가 되려 객체 지향 스러워 보임 → 객체의 흥행
대부분의 도메인 로직이 GUI가 존재하는 클라이언트에 위치
GUI & 클라이언트 티어 데이터베이스 티어
웹의 부상
클라이언트 티어 애플리케이션 티어 데이터베이스 티어
대부분의 도메인 로직이 애플리케이션 티어로 이동
웹 브라우저 성능이 안 좋음
복잡한 로직을 서버로 내림
객체의 서버 진출
분산 객체 기술의 유행
EJB 컨테이너
서로 다른 위치에 존재하는 객체들을 통신하고 싶어하는 니즈 생김
분산 객체의 네트워크 통신
분산 객체 기술의 문제점
침투적인 아키텍처
컨테이너의 기술적인 지원을 받기 위해 EJB가 강요하는 인터페이스나 추상클래스 상속
해결하려는 문제가 아니라 기술에 집착하는 시절
비즈니스 로직 & 영속성 객체 구현
미들웨어 서비스를 제공받기 위한 기술에 특화된 인터페이스를 구현하게 됨
POJO 와 도메인 주도 설계
POJO
외부 의존성(특정 구현 기술에 종속)이 없는 순수한 객체
도메인 주도 설계
기술에 집중하지 말고 도메인 / 비즈니스 로직에 집중하자
분산객체 기술의 문제점 해결
분산객체기술은 생각하고자 하는 사고 방식이 기술에 묶여 버림.
표현적(의미적 차이)
내가 생각하는 것과 코드로 작성된 것의 구조가 다름. 표현적(의미적) 차이
도메인에 대한 멘탈 모델과 소프트웨어 내부에 표현된 도메인 개념 사이의 거리
모델 주도 설계
표현적 차이를 줄이기 위해 도메인 개념을 기반으로 모델을 만들고 도메인 모델을 기반으로 설계와 구현 진행

2. Eric Evans의 Domain Driven Design 책 내용 요약

2.1. [Part 1] 동작하는 도메인 모델 만들기

목차 정리
1장. 지식 탐구 → 지식 탐구
2장. 의사소통과 언어 사용 → 유비쿼터스 언어
3장. 모델과 구현의 연계 → 모델 주도 설계

2.1.1. 도메인 모델

동작하는 도메인 모델 만들기에서 도메인 모델 부분
도메인
사용자가 프로그램을 사용하는 주제 영역
현실세계의 문제를 해결하는 것을 소프트웨어로 구현할 때, 내가 구현하겠다고 생각한 범위
여기서부터 여기까지만 구현하겠다!
불필요한 것들은 잘라내고 쓸데 없는 짓을 하지 않겠다!
즉, 범위를 잘라내는 것
모델
대상의 단순화, 추상화
당면한 문제를 해결하는 것과 관련된 측면을 추상화하고 중요하지 않은 세부사항은 생략
도메인 모델
정의
사용자가 프로그램을 사용하는 주제 영역 (도메인) 안에서 당면한 문제를 해결하는 것과 관련된 측면을 추상화하고 중요하지 않은 세부사항은 생략
설명
문제를 해결하기 위해 무언가를 만드는데, 여기서 부터 여기까지 만들겠다고 범위를 정함 (도메인)
프로그램을 만드는 사람들끼리 공통적으로 바라볼 수 있게 단순화하고 의견일치를 맞춘 것 (모델)
문제의 범위를 정하고 단순화, 추상화 한 것

2.1.2. 모델 주도 설계

동작하는 도메인 모델 만들기에서 동작하는 부분
동작하는 도메인 모델
도메인 모델을 기반으로 핵심 설계와 코드 작성
코드가 변경되면 핵심 설계와 도메인 모델도 함께 변경 (구현 피드백)
모델 주도 설계
모델과 핵심 설계는 서로 영향을 주며 반복을 통해 구체화됨
도메인 모델 = 코드
코드가 도메인 모델이어야 함

2.1.3. 지식탐구와 유비쿼터스 언어

동작하는 도메인 모델 만들기에서 만들기 부분
지식 탐구 (Crunching Knowledge)
설계의 전 단계에 걸쳐 개발자와 도메인 전문가 사이의 활발한 논의를 거쳐 유용한 도메인 모델 도출
개발자와 도메인 전문가들 사이에도 개념을 잘 맞추고 잘 논의하자
유비쿼터스 언어 (Ubiquitous Language)
도메인 전문가와 개발자 사이의 커뮤니케이션 수단
모델은 모든 팀 구성원들이 사용하는 언어의 중추

2.1.4. 도메인 주도 설계 요약

요약
1.
전체 팀 내에서 (도메인 전문가, 개발자 등) 지식탐구를 통해 도메인 모델을 만들고
2.
쓰이는 용어를 공통의 유비쿼터스 언어로 만들어, 커뮤니케이션에 이용하고
3.
도메인 모델을 기반으로 설계하고 코드로 작성하면서 서로를 영향을 주면서 반복하며 구체화
왜 이걸 하는가?
목표는 유지보수를 잘 하고 싶어서
변경이 바뀔 때 변경이 잘 수용해야함
수정할 코드를 잘 찾아야함
사이드 임팩트가 적어야함
도메인 로직이 바뀌었을때 소스 코드를 도메인과 얼라인해놓으면 잘 찾아 갈 수 있을 것
요구사항이 변경되었을 때 연관 코드를 잘 찾아서 쉽게 수정할 수 있게 하자

2.2. [Part 2] 모델 주도 설계의 빌딩 블록

목차 정리
4장. 도메인의 격리 → 레이어드 아키텍처
5장. 소프트웨어에서 표현되는 모델 → 연관관계, 엔티티, 값 객체, 서비스, 모듈
6장. 도메인 객체의 생명 주기 → 애그리거트, 리파지토리, 팩토리
7장. 언어 사용: 확장 예제

2.2.1. 도메인 로직의 격리

도메인 주도 설계는 패턴이며 협업을 잘하기 위한 방법이자 사고방식임
도메인 주도 설계의 전제 조건은 도메인 구현을 격리하는 것
도메인 로직을 따로 구현할 수 있게 구조화 할 수 있다면 DDD라고 볼 수 있음
도메인 주도 설계에서 특정 아키텍처를 강제하지 않음
레이어드 아키텍처는 DDD를 적용한 하나의 예시

2.2.2. 모델 주도 설계의 빌딩 블록

도메인 모델이 있는데 코드로 작성하려면 이렇게 저렇게 나눠서 구현해야해
정의
구현 가능한 도메인 모델을 구성하는 요소들의 목록
도메인을 표현하기 위한 빌딩 블록
Entity, Value Object, Service, Module, Association
생명주기를 관리하기 위한 빌딩 블록
Aggregate, Repository, Factory
각 구성요소에는 구현과 관련된 다양한 가정 내포
모델과 구현에 관한 의사결정을 내리기 위해 필요한 용어 제공
빌딩 블록의 목적
구현에 대한 가이드를 제공하여 복잡도를 낮추는 것

2.2.3. 애그리거트 (Aggregate)

불변식 (Invariant)
도메인 룰
상태가 변경되더라도 반드시 지켜야하는 규칙
예) Order 의 총 합은 OrderlimitPrice 보다 작아야 한다
애그리거트
불변식을 만족시키는 객체 그룹 단위
애그리거트 단위로 저장하면 불변식이 유지 됨
객체 수정(변경) 단위로 묶으면 유지보수하기 쉬움
도메인에 근간을 둬서 불변식을 만족 시킬 것
애그리거트는 트랜잭션의 단위 및 저장의 단위
리포지토리
애그리거트 단위로 리포지토리 추가
복잡성 감소를위해 애그리거트 간에는 ID를 이용하여 참조

2.2.4. 결과적 일관성

여러 애그리거트를 수정해야하는 경우 별도의 트랜잭션에서 업데이트
도메인 이벤트 활용

2.3. [Part 3] 더 심층적인 통찰력을 향한 리팩토링

목차 정리
8장. 도약
9장. 암시적인 개념을 명확하게 → 리팩토링
10장. 유연한 설계 → 리팩토링
11장. 분석 패턴의 적용
12장. 모델과 디자인 패턴의 연결
13장. 더 심층적인 통찰력을 향한 리팩토링

2.3.1. 고전적인 소프트웨어 개발 프로세스

주요 고민들
왜 코드 작성 전에 완벽한 설계할 수 없을까?
왜 일정을 제대로 산정하지 못할까?
왜 나는 개발을 못할까?
주요 문제점
흐릿한 요구사항
변경되는 요구사항
유연하지 못한 개발 방법 (워터폴)
요구사항 일괄 분석 → 일괄 설계 → 일괄 구현 → 일괄 테스트
예견적인 프로세스
시작전에 전체 일정 계획 & 정해진 계획에 따라 진행
과도한 사전 설계
일괄 설계

2.3.2. 애자일의 등장

C3 (Chrysler Comprehensive Comprehensation)
크라이슬러 급여 시스템 구축 프로젝트
켄트 벡 참여 → XP로 알려진 모든 실천 방법을 통합
Extreme Programming
Embrace Change - 변경을 수용하라! 변경은 나쁜게 아니다
반복을 통한 피드백
애자일 프로세스
전체 요구사항 중 일부(중요한것)만 먼저 개발
반복을 통해 새로운 요구사항 개발
개발된 결과를 바탕으로 다음 반복 계획
반복적이고 점증적인 프로세스
이전의 문제점 해결
전통적인 개발 프로세스 문제점
해결
흐릿한 요구사항
반복을 통해 명확해지는 요구사항
변경되는 요구사항
짧은 주기의 반복 단위로 변경사항 반영
예견적인 프로세스
적응적인 프로세스 - 반복 단위로 피드백을 통한 계획 조정
과도한 사전 설계
진화적인 설계 - 반복 주기를 통해 코드를 점진적으로 구현

2.3.3. 애자일과 도메인 주도 설계

이 책은 특정 방법론에 매여 있지 않으나 “애자일 개발 프로세스” 라는 새로운 진영을 지향한다. 아래의 두가지 실천 방법은 이 책의 접근법을 적용하기 위한 선행 조건이다. 1. 개발은 반복 주기를 통해 진행되어야 한다. 2. 개발자와 도메인 전문가는 밀접한 관계를 가져야 한다. - 도메인 주도 설계 ‘서문’ 중에서
개발은 반복 주기를 통해 진행되어야 한다.
모델 주도 설계
도메인 모델 = 설계 = 코드
도메인 모들을 처음부터 완벽하게 만들 수 없음
요구사항을 가지고 지속적인 리팩토링 진행
도메인 주도 설계의 핵심은 도메인 모델의 리팩토링
개발자와 도메인 전문가는 밀접한 관계를 가져야 한다.
애자일 선언문
공정과 도구보다 개인과 상호작용이 더 중요하다
포괄적인 문서보다 작동하는 소프트웨어가 더 중요하다
계약 협상보다 고객과의 협력이 더 중요하다
계획을 따르기보다 변화에 대응하기가 더 중요하다
애자일의 12가지 원칙
도메인 전문가와 개발자 팀
DDD를 도메인 전문가와 개발자 팀이 함께 만드는 것은 결국 애자일의 개념이 녹아든 것
도메인 전문가와 개발자가 함께 도메인에 대한 통찰을 반영해 도메인 모델을 리팩토링
도약
반복적인 리팩토링을 통해 심층 모델과 유연한 설계로 도약
도메인 모델 설계 = 코드를 잘 짜는 것 = 요구사항이 명확해야 함 = 한방에 할 수는 없다 = 지속적으로 발전 시켜나가는 것

2.4. [Part 4] 전략적 설계

목차 정리
14장. 모델의 무결성 유지 → 바운디드 컨텍스트, 컨텍스트 맵
15장. 디스틸레이션 → 핵심 도메인, 일반 하위 도메인, 지원 도메인
16장. 대규모 구조
17장. 전략의 종합

2.4.1. 핵심 - 여러 도메인

우리가 만드는 시스템은 하나의 도메인 모델만 만드는 것이 아니다.
도메인 모델은 N개 일 수 밖에 없음
따라서, 코드를 나누고 우선순위를 정해야 함 → 중요한 도메인에 집중해야 함

2.4.2. 단일 도메인 모델

실무를 하다보면 응집도가 낮은 코드를 발견함
응집도 낮은 코드란?
하나의 코드를 가지고 여러 팀이 수정하고 있는 상황
문제점
기능 추가와 코드 수정 시 충돌
통제하기 어려운 사이드 이펙트
협업 오버헤드
릴리즈 일정 협의
의미적 충돌로 인한 언어의 모호함
각 팀마다 용어를 해석하는 바가 다를 수 있음
단일 도메인 모델 = 응집도가 낮은 코드
서로 다른 컨텍스트에 필요한 코드들의 집합
price, buy, position - 판매 컨텍스트
position, isStanding, deliver - 배송 컨텍스트
print - 출력 컨텍스트
public class Ticket { public Money price() {} public Order buy() {} public Seat position() {} public boolean isStanding() {} public void deliver() {} public void print() {} }
Java
복사
하나의 커더란 도메인 모델은 비현실적
사용되는 컨텍스트에 따라 모델을 분리
결합도 높은 것 보다는 오히려 코드 중복이 낫다
의도된 중복은 좋을 수 있다

2.4.3. 바운디드 컨텍스트 (Bounded Context)

정의
특정한 도메인 모델이 적용되는 범위
같은 바운디드 컨텍스트 안에서는 도메인 모델의 통합성을 유지
서로 다른 바운디드 컨텍스트 사이에서는 통합성에 신경 쓰지 않음
해석
코드, 구조, 설계를 너희 따로 우리 따로 나누는 것이 바운디드 컨텍스트
도메인 모델을 찢는 것
각각의 컨텍스트 마다 도메인 모델을 별도로 둬라
구현
Presentation Layer / Domain Logic Layer / Persistence Layer / DB 까지 다 나눔
MSA 적용에 용이함 (분리하기 쉬움)

2.4.4. 컨텍스트 맵 (Context Map)

정의
컨텍스트 사이의 관계와 모델 변환 방식 정의
해설
바운디드 컨텍스트 사이에 변환을 해야돼! 를 정의한 것
예시)
회원팀 / 주문팀 - 회원데이터가 각각 다를 것
이걸 맞춰줘야함 따로 따로 갈거니까 맞춰주는 것

2.4.5. 바운디드 컨텍스트 사이의 관계

바운디드 컨텍스트는 조직 관리와 설계가 만나는 곳
각각의 바운디드 컨텍스트는 팀 단위로 관리
A팀: 판매 컨텍스트 (Ticket)
B팀: 배송 컨텍스트 (Ticket)
정치와 협력의 영역
Shared Kernel, Open Host Service 등

2.4.6. 전략적 디스틸레이션

정의
디스틸레이션은 혼란을 줄이고 적절히 주의를 집중 시킴
전체 도메인 모델은 시스템에서 가장 가치를 더하고 특별한 측면을 부각시켜, 그쪽에 집중되도록 구조화 되어야 한다.
이렇기 주의를 집중하면 많은 노력이 시스템에서 가장 중요한 부분으로 향하게 됨
해설
도메인 찢었잖아, 그 중, 어떤 도메인이 중요한 지를 결정하고, 그곳에 집중해
서브도메인의 우선순위를 정해라
서브도메인
도메인을 나눈 것
서브 도메인의 종류
정의
해설
코어 서브 도메인
사업의 성공을 결정하는 핵심 - 코어 서브 도메인을 식별 & 강조 - 최고의 인력 투입
회사에서 중요한 도메인. 이걸 정해서 리소스 넣어
제너릭 서브 도메인
비즈니스에 경쟁우위 제공 X 타사 여러 앱에 공통적으로 존재 - 기성 소프트웨어 구입 - 주니어 개발자 배정
모든 회사가 똑같이해도 돼. 경쟁우위 없어. 복잡하긴 하지만 크게 리소스 많이 안넣어도 돼 우리 회사에서 굳이 이런 리소스를 넣어야 돼요? 외주 줍시다 / 그냥 구매합시다.
서포팅 서브 도메인
비즈니스에 경쟁우위 제공 X 비즈니스 일부로 코어 도메인 지원 - 외주로 해결 - 혹은 개발자들 성장 기회 활용
경쟁우위는 제공하지 않는데, 구매하기는 애매하고 외주주긴 애매하고… 우선순위는 높지 않아
전략적 디스틸레이션의 핵심
리소스를 집중할 영역과 시스템 구축 방법을 결정
코어 서브 도메인은 시간이 흐름에 따라 바뀔 수 있음
전략적 디스틸레이션은 결국 리소스를 어디에 집중할건지를 결정해라는 것

3. 도메인 주도 설계 그후

에릭에반스의 도메인 주도 설계에서 빈약한 구현 개념들이 다음 책에서 채워지기 시작함

3.1. 도메인 주도 설계 구현 (반버논)

현재의 DDD 체계 정립
전술적 패턴과 전략적 패턴, 문제공간과 솔루션 공간이라는 용어를 처음 사용
모델 주도 설계의 빌딩 블록 → 전술적 패턴
전략적 설계 → 전략적 패턴

3.1.1. 문제 공간 (문제 영역)

문제 공간 (이상적인 상황)
소프트웨어의 관점에서 구현 방법에 대한 고려 없이, 단순히 문제를 이해하고 정의하는 것에 초점
도메인 전문가와 개발자팀이 지식 탐구를 통해 유비쿼터스 언어를 설립
유비쿼터스 언어를 통해 도메인 지식을 설명 & 커뮤니케이션
도메인 모델 추출
서브도메인과 도메인 모델이 1:1로 이상적으로 나뉘어져 있음
주문 / 상품 / 결제

3.1.2. 솔루션 공간 (솔루션 영역)

솔루션 공간 (현실적인 상황)
문제 영역에서 식별된 문제를 해결하기 위해 고안된 소프트웨어 시스템의 설계 및 구현과 관련된 영역
바운디드 컨텍스트
도메인을 시스템으로 가져 온것
시스템의 구조
유비쿼터스 언어를 적용하여 실제로 서브 도메인 / 바운디드 컨텍스트 / 컨텍스트 맵을 시스템에 적용 시킨 것
바운디드 컨텍스트는 모델의 경계이므로 여러 서브 도메인의 개념을 포함할 수 있음
또는 단일 서브 도메인이 여러개의 바운디드 컨텍스트로 모델링 될 수 있음

3.2. 고도화된 디자인 패턴

3.2.1. 도메인 이벤트

트랜잭션 당 하나의 애그리거트
두 애그리거트를 하나의 코드로 두고 싶지 않아
트랜잭션 나누라고 하는데, 얘가 바뀌면 얘도 바뀌라는거야? → 도메인 이벤트를 던져
도메인 이벤트는 애그리거트 마다 발행

3.2.2. 이벤트 소싱

애그리거트와 도메인 이벤트 기반
DB가 따로 없고 이벤트 스토어만 있음
이벤트 스토어에 있는 이벤트를 다 합치면 현재의 데이터를 얻을 수 있음
cf) DBMS는 최종 상태만 관리
대표적인 것이 계좌
100+ / 100- / 200+ / 200- 등 모두 관리
이 모든 것을 리플레이해서 최근 데이터 추출

3.2.3. 책임이 과도해진 도메인 모델 (CQRS)

조회와 수정 기능을 함께 구현하는 복잡한 도메인 모델
조회를 위한 쿼리 모델
변경을 위한 명령 모델
도메인 모델 분리를 통한 복잡성 해결
하나의 서브 도메인에 바운디드 컨텍스트가 여러개인 것이라고도 볼 수 있음
조회 바운디드 컨텍스트
수정 바운디드 컨텍스트

3.3. 새로운 아키텍처의 유행

3.3.1. MSA의 유행

MSA 유행하면서 DDD가 두각
시스템을 서비스로 나누는 것
바운디드 컨텍스트
애그리거트
DB까지 분리하는 것을 권장

3.3.2. 헥사고날 아키텍처의 재조명

여러 기술 중립적인 모든 것을 받을 수 있게 하는 것
끼워넣을 수 있게 하는 것
모든 경우를 다 커버 할 수 있게 어댑터를 여러개 붙이는 것
헥사고널 아키텍처가 무조건 좋은 것은 아니다
코드 레벨 복잡도가 상당히 증가함 → code readability 하락
우리가 생각해야할 건, 유지보수를 잘하는 것이 목적이지 헥사고널을 만드는 것이 목적이 아님

3.4. 도메인 주도 설계와 도메인 중심 아키텍처

3.4.1. 도메인 주도 설계의 재조명

서비스 단위에 대해 생각하는 유용한 방법은 도메인 주도 설계의 바운디드 컨텍스트의 개념임
도메인 주도 설계는 복잡한 도메인을 여러 개의 바운디드 컨텍스트로 나누고 이들간의 관계로 맵핑함

3.4.2. 도메인 구현의 격리

도메인 계층은 비즈니스 로직에 대한 설계와 구현으로 이루어짐
모델 주도 설계에서 도메인 계층의 소프트웨어 구성물들이 모델의 개념을 반영
도메인 로직이 프로그램상의 다른 관심사와 섞여 있따면 그와 같은 대응이 효과적이지 않음
따라서, 도메인 주도 설계의 전제조건은 도메인 구현을 격리하는 것
비 침투적이고 표현적 차이가 적은 도메인 로직은 외부로 나가는 의존성이 존재하지 않음

3.4.3. 도메인 중심 아키텍처

헥사고널 아키텍처
오니언 아키텍처
클린 아키텍처

3.4.4. 도메인 주도 설계 패턴, 원칙, 실천방식 by 스콧 밀럿

현재 도메인 주도 설계에 대한 관점을 잘 반영한 책
번역본은 없음. 원서만 존재
다음 포스팅으로 이어짐