감사하게도 조용호님의 회사에 오셔서 DDD 관련 특강을 해주셨다.
DDD의 철학에 대해 많은 인사이트를 얻을 수 있었는데,
본 글은 이에 대해 빠르게 정리한 내용이다.
강의 소개
DDD는 2003년 “도메인 주도 설계(by 에릭 에반스)” 책으로 등장.
책의 배경: 소프트웨어 복잡성을 줄이고 싶다
-> “어떤” 부분 때문에 복잡한 것 같은데
-> 이를 해소하기 위해 도메인 주도 설계를 도입하자.
-> 모두가 이야기하지한 누구도 제대로 이해하지 못한 책
-> 이번 강의는 책을 이해할 수 있는 방법을 이해하는 강의
DDD는 철학이다. 그리고 이를 구현하는 방법은 정말 다양하다.
DDD를 구현부터 공부하면 하나의 구현 방법이 맞다고 생각할 수도 있다. DDD의 철학을 먼저 배우고, 이것이 지향하는 방향대로 구현하는 연습이 필요하다.
도메인 주도 설계 맛보기
✅ 도메인 주도 설계란
도메인 주도 설계는 복잡한 도메인을 다뤄야 하는 소프트웨어 프로젝트에 박차를 가하는 것을 목표로 삼는 사고 방식이자 우선순위의 모음이다.
(도메인 주도 설계 ‘서문’ 중에서)
-> 특정한 기술과는 무관한 사고 방식이라는 것에 집중
✅ 소프트웨어의 본질
그 소프트웨어의 사용자를 위해 도메인에 관련된 문제를 해결하는 능력에 있다.
-> 내가 어떤 기술을 쓰고싶냐가 아닌, 사용자가 원하는 것을 해결하기 위해 어떤 기술을 사용해야 할까
✅ 도메인
사용자가 프로그램을 사용하는 주제 영역
ex)배달(메뉴->주문->조리->배달->결제->식사)
✅모델
도메인 대상의 단순화: 당면한 문제를 해결하는 것과 관련된 측면을 추상화하고 중요하지 않은 세부사항은 생략
-> 배달 도메인을 소프트웨어로 치환할 수 있는 “메뉴, 주문, 결제” 모델로 분리
✅ 지식 탐구
모델링: 어떤 도메인을 심플한 모델로 만드는 것
-> 도메인 전문가와 개발자들이 협업
✅모델 주도 설계
모델과 설계는 서로 영향을 주며 반복을 통해 구체화된다.
-> 분석, 설계, 개발을 다 같은 것으로 본다.
✅ 유비쿼터스 언어
도메인 전문가와 개발자 사이의 커뮤니케이션
✅ 도메인 주도 설계
한 팀(도메인 전문가, 개발자)
-> 유비쿼터스 언어를 함께 만들고 커뮤니케이션에 이용
-> 지식탐구: 함께 도메인 모델을 창조
-> 도메인 모델 (유비쿼터스 언어를 사용)
-> 코드 구현
✅정리
도메인 주도 설계는 도메인과 도메인 로직에 집중한다.
복잡한 도메인은 단순한 모델 기반으로 설계한다.
도메인 전문가와 개발자가 같이 유비쿼터스 언어를 만든다.
도메인 모델과 코드는 반복적인 과정을 거쳐 정제한다.
—> 여기까지 책 Part 1
도메인 주도 설계의 개념적 바탕
도메인 주도 설계는 객체지향과 애자일 관점이 섞임.
객체지향과 도메인 주도 설계
도메인 주도 설계: 객체 모델링을 어떻게 실제 복잡한 소프트웨어 프로젝트에 적용할 것인지
<1990년대>
✅ 객체의 시대
-> why? 90년대 GUI 부흥
-> 객체지향: 원래 UI를 만들 때 쓰던 개념, 서버는 이후에 도입
-> 대부분은 도메인 로직이 클라이언트에 위치
✅ 웹의 부상
브라우저에서 도메인 로직을 처리하기 힘들다 보니 로직이 서버로 내려감
-> 백엔드 개발이 흥함, UI는 심플해짐
✅ 90년대는 분산 객체의 시대
각 객체마다 다른 서버에 위치시키고 싶어 했다
-> 네트워크 부하가 심해서 결국 없어짐
-> 그래서 객체를 묶고 서비스를 기준으로 나누자는 말이 나옴
-> MSA의 방향성
✅ EJB
분산 객체의 네트워크 통신을 위해 미들웨어 도입 (각 미들웨어마다 트랜잭션, 보안, 영속성 개념 도입)
-> EJB 컨테이너
-> 미들웨어 서비스를 제공받기 위한 기술에 특화된 인터페이스 구현
<2000년대>
✅ POJO
어떤 기술에 종속받지 않은 순수한 객체
어떤 특정한 구현 기술보다 객체지향 설계가 더 중요하다 (로드 존슨)
-> 객체지향이 더 중요하고 기술이 이를 서포트 해야 한다.
-
> EJB 컨테이너를 경량 컨테이너로 대체
-> 일반 객체를 써도 트랜잭션, 영속성을 쓰게 해줄게
-> 스프링의 기원
+) 다른 설계 방식
트랜잭션 스크립트: 객체는 getter, setter 정도의 책임, 서비스 단에서 절차적으로 로직 처리
vs
도메인 모델: 객체에 데이터와 로직을 담음
✅ 2000년대 초는 복잡하던 시기
주변에서 계속 EJB를 쓰라고 하는데 SOLID 등의 객체지향의 개념은 계속 발전함
-> 그 시기에 나온 것이 도메인 주도 설계 책
✅ EJB의 문제점
1. 도메인에 대한 멘탈 모델과 소프트웨어 내부적인 구현간의 차이
2. 비즈니스 로직에 기술적인 부분이 침투한다
✅모델 주도 설계
1. 도메인에 대한 멘탈 모델과 소프트웨어 내부 표현 차이를 줄이기 위해 도메인을 기반으로 모델을 만들고 설계와 구현을 주도
-> 도메인 모델 = 설계 = 코드
2. 비즈니스 로직과 기술적인 부분을 분리
-> 도메인 전문가와 커뮤니케이션이 쉬움 (유비쿼터스 언어)
✅ 도메인 구현의 격리
도메인 주도 설계의 전제 조건(핵심)은 도메인 구현을 격리하는 것
도메인이 다른 계층으로 나가면 안된다 (Java에서 import 등)
-> 물론 책이 나올 당시에는 이런 개념이 강하지 않아서 책의 예제는 도메인이 외부로 나가는 경우도 있다.
✅ 모델 주도 설계의 빌딩 블록
빌딩 블록의 목적은 구현에 대한 가이드를 제공하면서 복잡도를 낮추는 것
-> 도메인을 표현하기 위한 빌딩 블록: 밸류, 엔티티, 서비스, ...
-> 생명주기를 관리하기 위한 빌딩 블록: 애그리게잇, 리포지토리, 팩토리, ...
✅ 애그리게잇
요구사항, 제약사항
-> 여러 객체, 도메인이 필요할 수 있다
-> 애그리게잇의 본래 취지: 어떤 제약사항에 따라 한 객체의 변경이 다른 객체에 영향을 미치는 경우를 대비해 두 객체로 하나로 묶음
-> 같이 움직이기 때문에 보통 애그리게잇은 한 트랜잭션의 단위
-> 같이 움직이기 때문에 보통 애그리게잇 단위로 리포지토리 추가
-> 복잡성 감소를 위해 애그리게잇 간에는 ID를 이용한 참조 (특히 JPA에서 주의, 어차피 애그리게잇 단위로 읽어오니까 지연로딩을 안쓰는 경우도 있다)
-> 여러 애그리게잇을 수정해야 하는 경우 별도 트랜잭션으로 분리
-> 도메인 주도 설계 책을 기점으로 이제 스프링 등 POJO 기반으로 개발하는 것이 트렌드
—> 여기까지 책 Part 2
애자일과 도메인 주도 설계
✅ 왜 코드 작성 전에 완벽하게 설계할 수 없을까?
코드를 짜다보면 내가 생각하는 것과 다르다
-> 나는 개발을 못하나...
✅ 왜 일정을 제대로 추정하지 못할까?
코드를 짜다보면 내가 생각하는 것보다 일정이 촉박하다
-> 나는 개발을 못하나...
-> 단순 반복적인 일을 하는 것 아니라면 애초에 추정이 불가능하다.
-> 상황에 따라 일정을 재조정하는 능력이 더 중요하다.
✅ 문제
1. 흐릿한 요구사항
사실 초반에 명확한 요구사항이라는 것은 없다. 시간이 지나면서 명확해질 뿐
-> 개발을 진행하면서 점점 명확해진다.
2. 변경되는 요구사항
사실 제대로 서비스를 만들려면 요구사항이 변경되는 것이 많다. 그러나 우리는 이런 것들을 불편해 한다.
3. 유연하지 못한 개발 방법
시작할 때 전체 일정을 계획한다. (분석 -> 설계 -> 구현 -> 테스트)
설계 따로 구현 따로? 내가 설계를 안하면 구현도 할 수 없다. 설계에는 수많은 가정들이 있다.
-> 특히 SI에서는 설계 문서만 한트럭, 어차피 다 바뀌고 이거 보면서 구현하지도 않는다.
-> 내가 설계한 것도 내가 구현을 못하는데 남이 설계한거를 어떻게 구현해...
✅ 애자일
분석이든 설계든 어차피 다 바뀔꺼니까 그냥 변화에 민첩하게 대응하는 방법을 배우자
-> 애자일의 등장
-> 여기서 이에 맞는 방법론들 (TDD, XP, 지속적 통합)이 등장한다.
-> 짧은 주기로 계획해서 구현해보자. (한달 뒤가 아닌 짧은 주기는 예측하기 쉽다)
-> 반복적이고 점증적인 프로세스
1. 흐릿한 요구사항
일단 중요한 것부터 해보자
-> 반복을 통해 명확해지는 요구사항
2. 변경되는 요구사항
짧은 주기의 반복 단위로 변경을 반영
3. 유연하지 못한 개발 방법
반복 단위로 피드백을 통한 계획 조정
-> 그래서 애자일에서 중요한 것이 리팩토링
-> 도메인 주도 설계 책은 기본적으로 “애자일 개발 프로세스”를 지향한다.
-> 특히, 반복 주기와 리팩토링을 굉장히 강조한다.
—> 여기까지 책 Part 3
실무와 도메인 주도 설계
✅ 중복에 대한 강박관념
중복을 줄이기 위해 하나의 도메인 모델에 모든 데이터를 다 넣는다?
-> 더 복잡해질 수 있다.
-> 여러 개발자들이 하나의 도메인 모델을 개발하다 보면 충돌할 수 있다.
-> 도메인 모델을 여러 개 두는 것이 더 편하다.
실무를 하다 보면,
결합도나 응집도에 비하면 중복은 그렇게 중요하지 않다.
-> 각자 팀마다 표현하기 편한대로 중복을 적당히 두는 것이 더 유용할 때가 많다.
-> 대표적인 중복 -> DTO
✅ 단일 도메인 모델
모든 팀이 하나의 도메인에서 작업한다면?
-> 기능 추가와 코드 수정 시 충돌
-> 협업 오버헤드
-> 우리는 이 도메인을 이렇게 생각하는데 너네가 왜 이렇게 고쳐?
✅ 컨텍스트
컨텍스트에 따라 도메인을 분리하자.
-> 바운디드 컨텍스트: 특정한 도메인 모델이 적용되는 범위
서로 다른 바운디드 컨텍스트 사이에서는 통합성에 신경쓰지 않음
ex)
판매 컨텍스트: Customer, Ticket
배송 컨텍스트: Order, Ticket
컨텍스트 단위로, 표현 - 도메인 - 영속성 - DB까지 하나로 쪼갠다.
-> 그래서 이 구조가 MSA에 적합하다는 이야기가 나온다. (분리하기 쉬움)
✅ 컨텍스트 맵
각각의 바운디드 컨텍스트는 팀 단위로 관리
그러면 팀 간에 어떻게 커뮤니케이션 할거야? 팀 간의 관계를 어떻게 정립할거야?
-> 정치와 협력의 영역
-> DDD는 이런 조직 차원이 이야기도 한다.
✅ 도메인에 따른 리소스 분배
큰 도메인을 여러 서브 도메인으로 나누자
코어 도메인: 이 중 우리 회사에서 가장 핵심이 되는 도메인
-> 이 곳에 핵심 인력을 배치하자.
제네릭 서브 도메인: 경쟁 우위를 제공하지 않고 여러 회사에서 공통으로 존재하는 서브도메인
-> 이곳에는 리소스를 줄이자
—> 여기까지 책 Part 4
도메인 주도 설계 그 후
✅ 책: 도메인 주도 설계 구현(by 반 버논)
현대의 DDD 방식을 정립한 책
문제 공간(서브도메인, 이상), 솔루션 공간(바운디드 컨텍스트, 현실) 개념 도입
-> 구현 관점의 이야기들이 많다.
✅ 도메인 이벤트
두 애그리게잇을 두 트랜잭션으로 나눠서 update를 하고 싶다.
-> 그러나 하나의 코드로 두고 싶지 않아.
-> 하나의 애그리게잇이 바뀌면 도메인 이벤트를 발생시켜 다른 애그리게잇을 바꾸자.
✅ 이벤트 소싱
도메인 이벤트를 사용하다 보니 생겨난 개념.
-> 이벤트 스토어에 모든 객체의 상태를 저장하고,
-> 최종 객체의 상태를 보려면 스토어를 쫙 뽑아서 다 더하면 된다.
-> 이러면 DB가 필요 없다.
-> 외국에서는 많이 사용하긴 하는데, 아직 써본적은 없음.
✅ CQRS
조회 모델과 명령 모델을 나눈다.
-> 도메인 모델 분리를 통한 복잡성 해결.
✅ 마이크로서비스 아키텍처의 유행
객체를 분리하는 것은 복잡하다.
-> 객체들의 모음인 서비스로 분리해보자.
-> 서비스 단위: 바운디드 컨텍스트
+) 헥사고날 아키텍처의 재조명
✅ 책: 도메인 주도 설계 패턴, 원칙, 실천방법 (by 스콧 밀럿)
현대의 DDD를 구현 관점에서 표현한 가장 좋은 책
-> 이 책이 좋지만 앞서 “도메인 주도 설계(by 에릭 에반스)” 책부터 설명한 이유는 DDD를 구현 중심으로 먼저 공부하다 보면 DDD의 철학 에 대해 오해할 수 있기 때문
'ddd' 카테고리의 다른 글
[DDD] 도메인 주도 개발을 실제로 적용해보면서 (2) | 2023.07.18 |
---|