-
DDD 기본개념 톺아보기Spring Boot 2024. 4. 20. 00:23
배경
사내에 MSA를 도입 해보자는 이야기가 있어서,
이왕이면 제대로 해보고 싶어 요즘 열심히 스터디 중이다.
내가 필요하고 판단한 선수지식은 다음과 같다.
- 멀티모듈(https://yeoon.tistory.com/145)
- DDD
- port-adapter pattern (https://yeoon.tistory.com/148)
- Spring Cloud
- event-consistency, 카프카
- AWS EKS
DDD에 관해 작성해본다.
Domain Driven Design의 탄생
- 2005년 마틴 파울러, 로드 존슨 등등등 유명한 개발 아저씨들 모여 토론.
- 주제는 1999년 ~ 2005년 EJB 등장으로 객체지향개발 같은 방법론 적용 못하고, 코드 너무 복잡해져서 해결책 논의.
- 에릭 에반스라는 사람 Domain Driven Design이란 방법이 해결책으로 논의하고 큰 공감을 얻음.
- 에릭 에반스가 자신의 아이디어를 2003년 두꺼운 책으로 출판하여 설득력을 가짐.
- 그 아이디어란 Domain과 닮은 소프트웨어 구조를 설계하자는 아이디어.
- 당시 구성원이 이 아이디어가 산업의 메인 스트림이 되기를 원함. 커뮤니티에서 적극적으로 발전되어 spring 커뮤니티에도 흘러들어옴
- 2016년 스프링 컨퍼런스에서 DDD 발표 내용으로 하루종일 DDD 관련한 세션이 있었다고함 (https://blog.ordina-jworks.io/conference/2016/07/10/SpringIO16-DDD-Rest.html )
- 매일 같이 쓰는 @Service, @Repository 또한 저 파란책에서 나온 개념이라고 한다.
Domain이란?
- 그래서 Domain이 무엇이냐 A domain is something of this world. 현실에 어떤 것이란다.(위 링크 DDD 발표 자료 참고)
- 소프트웨어의 존재가치는 현실의 쓸모이다.
- 소프트웨어는 현실의 어떤 문제를 해결하기 위해 존재한다.
- 즉 도메인을 해결하려는 현실의 something. 비즈니스적으로 돈벌면서 해결하고 싶은 영역이라고 개인적으로는 이해함
무엇이 DDD 공감을 얻었는가
- 소프트웨어 설계는 예술의 영역이다. 개인의 취향을 타기 마련이며, 작성자에 따라서 천차만별로 다르며 은총알이 존재하지 않는다.
- 도메인 주도 개발(DDD)은 현실 세계 something을 추상화해서 버릴 것은 버리고 취할 것은 취해, 엄격하게 조직화한 디자인 방식이다.
- (은총알은 없지만 우리가 풀어나갈 도메인 관점에서는 정답에 가까운..답..? 이런 느낌 받음)
- 당시 DDD 등장 시기 유행했던 개발 방법론의 부족했던 점이 DDD를 매력적이게 만들었다.
- 폭포수개발 → 순서대로 진행하면서 개발 최종 산출물이 이상한 단점
- 애자일, XP → 디자인 결정 같은 것을 최대한 뒤로 미루고 리팩토링 하다보니 결정 자체에 두려움이 생기고 결정 자체를 안 하면서 코드가 이상해지는 문제점 발견 (2001년 애자일 선언 : https://agilemanifesto.org/iso/ko/manifesto.html)
- DDD → 도메인 기준으로 디자인 결정 진행
- DDD를 실행하는 대상으로 개발자만 말하지 않았다. Domain을 가장 잘 아는 것은 사용자가 아니라 Domain 안에서 Player로 뛰고 있는 사람이라고함. (Ex 은행이면 돈 맡기러 오는 고객이 아니라, 은행원이 은행에 대해 가장 잘안다.)
- Banking System을 만든다면 Banking에 대한 모든 것을 알아야 좋은 소프트웨어가 나온다.
- 그래서 DDD를 하려면 개발자만 하는게 아니라 도메인을 가장 많은 것을 알고 있는 실무자, 운영팀, 기획자, 디자이너 등등 함께 설계 하는 것이다 라고 DDD에서 주장.
유비쿼터스 언어
- 실무자, 운영팀, 기획자, 디자이너 다같이 설계하기 위해서는 공통의 언어가 필요함
- 도메인에 속한 구성원 모두가 사용하는 동일한 언어를 추출해서 "도메인 언어"를 만들어 소프트웨어에 반영하여 설계 디자인 해야함 이를 유비쿼터스 언어라고 표현
- 그래서 도메인 언어 다같이 어떻게 추출하느냐
- 이벤트 스토밍이라는 기법을 활용해서 포스트잇으로 기획자, 디자이너, 개발자가이벤트 기반으로 도메인을 추출할 수 있다고함
- https://intro.msaez.io/started/event-storming-learning/#sticker-type
- 이때 추출하는 개념들이 다음과 같으며 DDD로 만드는 소프트웨어의 기본 구성 요소임
- Value Objects
- Entities
- Aggregates
- Repositories
- Bounded Contexts
- Language
- 위 기본 개념이 뭔지 코드 예시들어 설명해주는 것이 유명한 DDD 입문책
- 또는 바쁜 현대인을 위한 개념 요약본 참고 : https://paucls.wordpress.com/2017/03/04/ddd-building-blocks-value-objects/
DDD의 기본 구성 요소 간략하게 정리
- Value Objects
- Avoid Stringly typed code (String으로 데이터 표현을 멈춰라)
- Vital Building Blocks of DDD
- 작은 불변 객체들
- value, validation, behavior를 캡슐화
- 기능적으로 관련 있는 것끼리 묶고
- values가 관계 있는 것끼리 묶는다
- 관련 있는 값을 묶으며 암시적인 것들을 명시적으로 만든다.
- ex) Money, EmailAddress, ZIPCode, Status . . . avoid
- 예를 들어 아래 JSON 구조를 Java로 표현하자면
{ "orderSeq": 1, "orderCreatDateTime": "2024-04-24 20:32:53", "orderNumber": "0000", "orderProductState": "미사용", "expiredDate": 2024-05-25 "driver": { "name": "김철수", "tel": "010-0000-0000", "userLoginId": "hello", }, "product": { "productCode": "9808908", "productName": "오브젝트", "price": 30000, "productState": "판매중" } }
- String으로 퉁치지 말고 아래처럼 VO 객체를 정의해서 사용한다.
- (VO 객체에게 value, validation, behavior를 캡슐화하고 메시지만 보내서 behave하게 한다. - 책 오프젝트)
- Entities
- VO가 VO가 가진 attribute로 식별되는 반면에, Entities는 식별자로 구분된다.
- Entities는 라이프사이클을 가진다. 식별자가 책임과 연관관계를 정의하기 때문이다.
- Mutability를 가진다.
- attribute가 동일하더라도 식별자가 다르면 다른 취급
- Aggregates
- Aggregates는 밀접하게 연관된 Entities의 클러스터이다. (클러스터를 Aggregate Root라 부른다.)
- ex) Order와 OrderLineItems..
- 하나의 Aggregates 변경은 하나의 트랜잭션 안에서 일어나야한다.
- 다수의 Aggregates 변경은 Event Consistency에 의해 이루어진다.
- Aggregates는 밀접하게 연관된 Entities의 클러스터이다. (클러스터를 Aggregate Root라 부른다.)
- Repositories
- Aggregates 저장을 위한 추상 persistence store
- DB 내부 동작은 캡슐화하고 collection 처럼 동작한다. (add, remove)
- Criteria에 충족하는 Aggregate의 attributea만 불러오는 정교한 쿼리 기능도 지원한다.
- Bounded Contexts
- Domain 용어가 맥락에 따라서 다르게 해석 될 수있다.
- 연관된 도메인을 그룹으로 묶어 구조화 한 것이 Bounded Context 이다.
- 도메인, 모델과 언어를 분리해서 시스템간의 디커플링을 줄여, 쉽게 변경 확장이 가능하게 만든다.
- MSA 아키텍처에서 서버를 나눌때 Bounded Contexts를 참고한다. (맹목적으로 따르지 않는다.)
- Multiple Bounded Context를 한 트랜젝션에서 조작하는 것은 피해야한다.
- Domain 용어가 맥락에 따라서 다르게 해석 될 수있다.
- Language
- 도메인 언어는 Bounded Context 안에서만 의미를 가진다.
Domain Events
- 비즈니스과 관련된 과거에 발생한 이벤트
- ex) 주문 됨, 고객 찜하기 누름 . . .
- 이벤트 이름과 속성을 정의 하는 것이 중요
- Bounded Context 내외부 통신이 발생하면 Event Consistency가 사용된다.
- (Event Consistency는 내용이 많아 후에 작성 예정)
- 간략하게 설명하면 동작의 결과(데이터)가 real time으로 저장되는게 아니라 near real time으로 관리되는 .
Domain 성숙도 LEVEL
- 도메인 이벤트 사용에는 4단계 성숙도가 있다.
- Getter, Setter만 있는 절차적 코드
- Operations 추출
- 몇몇의 operations의 이벤트
- 도메인 이벤트가 State 전환에 사용
- 중요한 도메인 이벤트가 feed를 통해 interested parites에 노출
- Event Sourcing - 모든 App 상태 변화가 이벤트 변화가 이벤트 순서대로 저장된다.
- only event logs and snapshots are kapt (Event Store)
- read / write operations의 분리 (CQRS)
반응형'Spring Boot' 카테고리의 다른 글
스프링 개발자가 가장 많이하는 실수 (0) 2024.06.19 Port Adapter 패턴이란? (클린아키텍처) (1) 2024.04.20 멀티모듈 잘 설계해보기 (1) 2024.04.18 디자인 패턴- Builder (0) 2022.01.19 JPA 개념 정리 - 영속성 컨텍스트, 트렌젝션, 1차 캐시, Flush, 쓰기 지연 (0) 2022.01.16