A. Help와 Progress의 관계 문제
- 처음에는 JPA 연관관계로 만들어야 하니 Progress를 엔티티로 만들고 Progress도 Progress만의 리포지토리가 있었습니다.
- Progress도 하나의 서브도메인이고 트랜잭션을 만드는 애그리거트라 생각하여 스스로의 리포지토리가 필요하다고 생각했습니다.
- 그렇지만 이렇게 되면 Help의 상태를 표현하는 Progress가 스스로 변경 요청을 받는 것이 가능해 Help가 자신의 상태의 일관성을 관리하지 못하게 됩니다.
- 이 문제를 해결하며 DDD의 각 개념들에 대해 혼동이 생겨 다시 개념 정리를 하며 Help와 Progress의 관계에 대해 고민해 보았습니다.
B. DDD의 도메인 모델링 개념 다시 잡기.
1. 도메인(Domain)
- 비즈니스의 한 부분을 의미하며 전체일 수도 있고 부분일 수도 있다.
- 부분인 경우 “서브도메인“이라는 용어로 표현하는 것이 혼동을 줄일 수 있습니다.
2. 서브도메인(Subdomain)
- 비즈니스 분석 결과 나누어진 비즈니스의 기능이나 프로세스의 단위.
- 도메인을 기능적으로 나눌 수 있다면 각각이 서브도 메인입니다.
3. 바운디드 컨텍스트(Bounded Context)
- 모델의 경계로 유비쿼터스 언어가 같은 의미로 쓰일 수 있는 문맥의 범위.
- 이상적으로 하나의 서브도메인당 하나의 바운디드 컨텍스트를 가지는것이 바람직하나 그렇지 않은 경우 하나 또는 그 이상의 서브 도메인을 가질 수 있다.
- 그렇지 않은 경우에는 하나의 바운디드 컨텍스트로 무리하게 여러가지 서브도메인들을 설명하고 있을 수 있다.
4. 애그리거트 (Aggregate, 트랜잭션 일관성의 경계)
: 트랜잭션 일관성의 경계로 단일 트랜잭션에서 비즈니스의 규칙과 제약에 따라 같이 변경되는 범위.
5. 애그리거트 루트 (Aggregate Root)
- 애그리거트 내부에는 여러 객체들이 있을 수 있는데 내부 객체들의 트랜잭션에서 일관성을 책임지는 핵심 엔티티.
- 애그리거티 루트를 기준으로 애그리거트의 영속성을 유지하기위한 리포지토리가 생성됩니다. (애그리거트 루트당 하나)
6. 리포지토리(Repository)
- 애그리거트의 영속성을 가지게 하기 위한 저장소.
7. 엔티티(Entitity)
- 개별적으로 식별이 필요하여 식별자가 있고 변화 가능성이 있는 객체.
8. 값객체(Value Object, VO)
- 관련 특성들이 모여 의미적으로 하나이며, 사이드 이펙트가 없고 값이 생성 후 변하지 않아서 오로지 값만을 표현하기위한 객체.
9. 도메인 서비스 (비즈니스의 규칙과 제약을 담은 비즈니스 로직 구현)
- 특정 규칙과 제약을 따르는 도메인의 비즈니스 로직을 구현한 서비스.
10. 어플리케이션 서비스 (유즈케이스 구현)
- 하나의 사용자의 요청의 시작에서 부터 끝인 유즈케이스를 구현하는 곳으로 여러 애그리거트 루트간 협력이나 외부시스템과 협력이 일어납니다.
11. 표현/ 인터페이스 계층
- 사용자의 요청을 받아들여 응용계층이 사용할 수 있도록 해석해주거나 유즈케이스의 결과를 클라이언트에게 되돌려 주는 책임을 가진 계층.
12. 인프라 계층
- 유즈케이스 완수를 위한 기술적 지원을 하는 계층.
C. 변경사항
- Progress는 Help의 상태의 일부입니다.
- Progress는 Help에 의해 식별되고 변화도 시작되기에 애그리거트 루트라고 보기에 무리가 있다는 생각이 들었습니다.
- Progress는 Help를 통해서 식별이 되면 되지 스스로 식별이 가능할 필요는 없습니다. 그렇기에 엔티티보다 값객체가 더 적합합니다.
- 그렇다면 Progress 자체가 또 다른 애그리거트 루트가 되는 것이 아니라 Help라는 애그리거트 루트와 Help Repository를 통해서 상태 변경의 책임을 가지는 것이 객체지향적으로 더 올바르고 SRP를 위반하지 않습니다.
D. 결론
- Progress는 값객체가 아닐때는 상태 변경되는 경우가 있어서 까다로웠습니다.
- Progress를 값객체로 만든 후에는 불변객체로 사용할 수 있어서 사이드 이팩트 관리도 쉬워졌습니다.
- 알듯 말듯 헷갈리던 DDD관련 용어들이 헷갈렸는데 개념이 확실히 잡히고 나니 애그리거트 루트나 엔티티 같은 각 객체들의 역할을 더 확실히 할 수 있었습니다.
- 또한, 각 바운디드 컨텍스트의 메인 비즈니스가 무엇인지 알기 쉬워 졌습니다.