티스토리 뷰

개요
알라딘 링크: http://aladin.kr/p/CPbs2
2024년 6월에 읽고 너무 좋아서 이번에 재독을 하였다. 과연 재독을 하니 좀더 이해가 되고 놓쳤던 포인트가 보였다. 책 전체를 꼼꼼하게 정리를 하려 하였다가 제풀에 지쳤던 기억이 있어 가능한 책의 큰 줄기만을 따라가며 정리해보려 한다. 한 눈에 책 전체를 조망한다는 의미도 있다. 짧은 정리이다 보니 생략과 일반화를 통해 예외사항등이 빠져있을 수 있다.
Part 1. 전략적 설계
하위 도메인
비즈니스 도메인이 있다면 이를 다시 핵심(core), 일반(generic), 지원(support) 하위 도메인(subdomain)으로 구분할 수 있어야 한다. 각각의 개념, 특징, 구분법을 이야기 한다.
유비쿼터스 언어
해당 도메인을 잘 아는 도메인 전문가와 소프트웨어 개발자 사이의 지식전달과 소통이 중요한데 이를 위해서는 유비쿼터스 언어(Ubiquitous Language)를 찾아 내어야 한다. 서로가 같은 용어를 써야 소통이 된다.
명사는 용어집에 정리할 수 있겠고, 동사는 BDD의 Given, When, Then을 활용하여 정리할 수 있다.
바운디드 컨텍스트
같은 용어가 여러 의미로 쓰인다면 바운디드 컨텍스트로 나누어야 한다. 다시 말해 하나의 용어는 하나의 바운디드 컨텍스트 안에서는 하나의 의미만을 지닌다.
바운디드 컨텍스트의 경계는 정답이 없으며 지속적으로 최적화해야 한다. 하위 도메인은 발견한다고 하면, 바운디드 컨텍스트는 설계한다.
하나의 바운디드 컨텍스트는 하나 이상의 하위 도메인을 가진다.
하나의 바운디드 컨텍스트는 한 팀이 개발해야 한다. 반대로 하나의 팀이 여러 바운디드 컨텍스트를 개발하는 것은 가능하다.
컨텍스트 맵
바운디드 컨텍스트간의 연동 방법을 컨텍스트 맵이라 한다.
- 협력관계: 파트너십(Partnership), 공유커널(Shared Kernel)
- 사용자-제공자: 순응주의자(Conformist), ACL(Anti-Corruption Layer), OHS(Open Host Service)
- 분리: Seperate ways
Part 2. 전술적 설계
비즈니스 로직의 구현
비즈니스 로직의 구현을 네 가지 방법으로 이야기하고 있다.
- 간단한 비즈니스 로직 구현
- 트랜잭션 스크립트(Transaction Script): 트랜잭션으로 감싸고 절차지향적으로 처리한다.
- 액티브 레코드(Active Record): 트랜잭션 스크립트 보다 조금은 복잡한 경우에 사용하며 전용 객체와 객체의 메서드를 이용하여 구현한다.
- 복잡한 비즈니스 로직
- 도메인 모델(Domain Model): 다음 세 요소를 이용하여 구현한다.
- 벨류 오브젝트(Value Object): 벨류(데이터) + 행동(메서드)
- 애그리게이트(aggregate): 트랜잭션의 경계를 의미한다.
- command → aggregate → domain event
- 참고로, 엔티티(entity)는 애그리게이트의 구성요소이다.
- 도메인 서비스: 벨류 오브젝트나 애그리게이트와 무관하거나, 여러 애그리게이트를 다루는 비즈니스 규칙을 담는 상태없는 객체(stateless object)
- 도메인 모델(Domain Model): 다음 세 요소를 이용하여 구현한다.
- 복잡한데 시간 차원의 모델링이 필요한 경우
- 이벤트 소싱 도메인 모델(Event Sourcing Domain Model)
- 애그리게이트는 상태 저장을 단지 현재의 상태만을 저장하는 것이 아니라 계속 변화하는 상태를 저장하는 것이다. 다르게 말하자면 애그리게이트의 상태 저장을 이벤트 소싱으로 하는 것이다 → 발생하는 도메인 이벤트를 원천 데이터로(sourcing) 사용한다. 그래서 이벤트 소싱인 것이다.
- 프로젝션: 도메인 이벤트들(원천 데이터)로 원하는 데이터를 추출하는 것을 프로젝션이라 한다. 예를 들어 어제의 마지막 잔고를 알고 싶다면 어제까지의 도메인 이벤트들을 모두 적용하면 어제 마지막 잔고가 프로젝션 된다.
- 장점: 시간 여행, 통찰력, 감사로그(audit log)
- 단점: 학습 곡선, 모델 진화 대응의 어려움, 아키텍처의 복잡성
- 이벤트 소싱 도메인 모델(Event Sourcing Domain Model)
아키텍처 패턴
앞서 비즈니스 로직의 구현 방법 네가지를 이야기 했고, 이번에는 선택할 수 있는 아키텍처를 세 가지로 분류해보자.
- 계층형 아키텍처: 의존성이 한방향으로 흐른다. 비즈니스 로직으로 요청이 들어오면 비즈니스 로직은 데이터베이스에 저장한다. 트랜잭션스트립트, 액티브 레코드로 비즈니스 로직을 구현시에 보통 적합하다.
- 포트와 어뎁터: 헥사고날, 어니언, 클린 아키텍처등에 해당한다. 핵심은 DIP 원칙으로 비즈니스 로직이 다른 것들에 의존하지 않도록 하는 것이다. 도메인 모델로 비즈니스 로직을 구현시에 보통 적합하다.
- CQRS(Command-Query Responsibility Segregation): 애그리게이트에 대해 커맨드가 가면(command → aggregate) 그 결과로 도메인 이벤트가 발생하는데 그 결과를 프로젝션하여 리드 모델(read model)로 만들어두는 것이다. 이벤트 소싱 도메인 모델로 비즈니스 로직을 구현하였다면 이 아키텍처가 적합하다.
커뮤니케이션 패턴
바운디드 컨텍스트를 넘어선 연동을 위해서는, (유비쿼터스) 언어가 바뀌니깐 모델을 변환해줘야 한다. 이를 위해 컨텍스트 맵을 활용하여 스테이트풀 또는 스테이스리스하게 모델을 변환한다.
애그리게이트들 사이의 연동은 다음 세 가지 패턴을 사용할 수 있다.
- 아웃박스(outbox) 패턴: 비즈니스 데이터를 저장할 때에 이벤트 발행을 위한 테이블에도 트랜잭션으로 저장한다. 이후 이벤트의 발행을 보장할 수 있게 된다.
- 사가(saga) 패턴: 시간의 소요 보다는 트랜잭션의 측면에 집중하여 단순하고 선형적이다. 한 컴포넌트에서 이벤트가 발행되면 이를 수신하고 다른 컴포넌트에 커맨드를 발행하는 것이다. 도중에 실패하면 보상 조치를 발행한다.
- 프로세스 매니저(process manager) 패턴: 사가 패턴이 전체를 관장하는 실체가 없다면 프로세스 매니저 패턴은 명시적으로 전체를 챙기는 주체가 있다. 상대적으로 좀더 복잡하다. 프로세스 매니저 패턴은 사가 패턴에 if-else 문이 추가된 것으로 생각해볼 수도 있다.
Part 3. 도메인 주도 설계 적용 실무
휴리스틱 설계
정답은 아니지만 경험칙에 따라 다음과 같이 선택을 한 다음 도메인의 특성에 따라 조정을 하면 되겠다. 일종의 가이드라 생각하자.
- 비즈니스 로직: 비즈니스 로직의 복잡도, 이벤트 소싱의 필요여부에 따라 다음 중 하나를 선택한다.
- 트랜잭션 스크립트, 액티브 레코드, 도메인 모델, 이벤트 소싱 도메인 모델
- 아키텍처: 비즈니스 로직의 구현에 따라
- 트랜잭션 스크립트, 액티브 레코드 → 계층형 아키텍처
- 도메인 모델 → 포트와 어댑터
- 이벤트 소싱 도메인 모델 → CQRS
하위 도메인 유형의 진화
하위 도메인의 유형(핵심, 일반, 지원)은 여러가지 이유로 진화, 변경된다. 예를 들어 핵심 도메인이었는데 저렴하고 더욱 성능 좋은 상용 서비스가 나왔다면 더 이상 핵심 도메인이 아니게 된다.
하위 도메인 유형이 바뀌면 구현 방법, 통합 패턴도 따라서 바뀐다.
조직이 커지면 바운디드 컨텍스트 역시 더 쪼개어야 할 수 있다.
도메인 지식이 늘어남에 따라 진화하기도 한다. 프로젝트 초기에는 넉넉하게 하나의 컴포넌트에 모아 두었다가(CCP, Common Closure Principle), 도메인 지식이 늘어나면 함께 재사용되는 것들로만 컴포넌트들을 나누게 된다(CRP, Common Reuse Principle)
이벤트스토밍
도메인 주도 설계의 시작은 유비쿼터스 언어를 찾아내고 정리해두는 것이다. 이벤트스토밍은 비즈니스 도메인 지식의 공유, 복구의 전술적 도구이며, 유비쿼터스 언어 발굴, 구축의 도구이기도 하다.
실무와 DDD
모든 DDD 도구를 사용해야만 도메인 주도 설계인 것은 아니다. 도메인 주도 설계의 본질은 비즈니스 도메인이 소프트웨어 설계시의 의사결정을 주도하는 것을 말한다. 이를 위해 필요한 도구를 사용하고, 심지어는 새로이 도구를 만들어도 된다.
Part 4. 다른 방법론 및 패턴과의 관계
다른 방법론들과 도메인 주도 설계와의 관계를 알아보자.
마이크로서비스
존 오스터하우트의 APoSD(A Philosopy of Software Design)에서는 깊은 모듈이라는 개념이 나온다. 퍼블릭 인터페이스(무엇을 할 수 있는지)는 간단해야 하고, 할 수 있고 해내는 일(어떻게)은 많아야 한다는 것이다. 부하 직원에게 백엔드 서버 하나 만들어 달라고만 해도 일관성, 가용성, 보안 등등을 모두 고려하여 구현을 해준다고나 할까?
마이크로서비스는 이와 같은 깊은 서비스여야 한다. DDD와의 연관성으로 보면 마이크로서비스는 바운디드 컨텍스트만큼 커질수도 있고, 애그리게이트만큼 작아질 수 있지만 경험칙으로(휴리스틱) 보아서는 하위 도메인 정도를 마이크로서비스로 만들면 적당하다.
이벤트 주도 아키텍처
이벤트 주도 아키텍처(EDA, Event-Driven Architecture)는 서비스들 사이의 통신을 의미하지만, 이벤트 소싱은 서비스 내부에서 발생한다. 둘은 다르다.
EDA에서는 이벤트는 세 유형으로 나눌 수 있다.
- 이벤트 알림: 이벤트 발생만을 알려주고 자세한 것은 질의하도록 한다.
- 이벤트를 통한 상태 전송(ECST, Event-Carried State Transfer): 상태에 대한 정보를 전송
- 도메인 이벤트: 이벤트에 대한 정보를 담고 있다.
EDA의 성공여부는 메시지의 성공적인 전달 여부에 달려있다. 아웃박스, 사가, 프로세스 매니저 패턴을 잘 활용하자.
데이터 메시
데이터 웨어하우스, 데이터 레이크 방식의 가장 큰 문제(?)는 OLTP로 데이터를 생산하는 쪽과 OLAP로 데이터를 분석하는 쪽이 떨어져 있다는 것이다.
데이터 메시는 DDD의 바운디드 컨텍스트 수준에서 OLTP로 데이터를 생산하는 팀이 OLAP로 데이터를 분석하는 일까지 맡는 것이다.
'book-movie' 카테고리의 다른 글
| 영화이야기: 영화를 음악처럼 (0) | 2025.10.13 |
|---|---|
| 책: 요즘 개발자를 위한 시스템 설계 수업 (0) | 2025.10.11 |
| 서평: 현장에서 통하는 도메인 주도 설계 실전 가이드 (0) | 2025.09.05 |
| 책: 에도의 장인들 1권 (0) | 2025.09.03 |
| 책과 영화: 파워 오브 도그 (0) | 2025.09.02 |
- Total
- Today
- Yesterday
- Gin
- 체호프
- MCP
- golang
- ChatGPT
- 티스토리챌린지
- gocore
- Echo
- 독서후기
- agile
- postgres
- 영화
- 잡학툰
- strange
- websocket
- clean agile
- github
- 독서
- 오블완
- bun
- go
- OpenAI
- intellij
- notion
- API
- claude code
- 클린 애자일
- backend
- solid
- 인텔리제이
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
