본문 바로가기
Back-End/도메인 주도 개발 시작하기

[DDD] 도메인 주도 개발 시작하기 Ch3

by SoyeonCha 2024. 3. 18.

Chapter 3 애그리거트

3.1 애그리거트

∘ 상위 수준에서 모델을 정리한 것이 관계를 이해하기 더 쉬움

∘ 모델을 이루고 있는 객체들을 보는 것보다 보다 상위 수준에서 바라보게 되면 관계 파악이 수월해짐

∘ 추후에 코드 변경 및 확장을 하려면 도메인 모델의 관계 파악이 되어야 함

∘ 코드를 고칠 때 전체적인 것을 고려하지 않고 바꾸려는 세부적인 부분만 보면 안 됨

∘ 애그리거트 : 모델을 상위 수준에서 볼 수 있는 방법. 관련된 객체를 군으로 묶음.

∘ 애그리거트로 묶으면 상위 수준에서도, 그보다 구체적인 수준에서도 모델 파악에 용이함

∘ 한 애그리거트에 속한 객체는 유사하거나 동일한 라이프 사이클을 가짐

∘ 하나의 객체는 하나의 애그리거트에만 속할 수 있음

∘ 도메인 규칙과 요구사항에 따가 경계 설정

 

3.2 애그리거트 루트

∘ 애그리거트의 루트 엔티티 : 애그리거트에 속한 모든 객체가 일관된 상태를 유지하도록 애그리거트 전체를 관리. 애그리거트의 대표 엔티티.

∘ 애그리거트에 속한 객체는 애그리거트 루트 엔티티에 속하게 됨

 

3.2.1 도메인 규칙과 일관성

∘ 애그리거트 루트는 애그리거트의 일관성이 깨지지 않도록 애그리거트가 제공해야 할 도메인 기능을 구현함

∘ 애그리거트 외부에서 애그리거트에 속한 객체를 직접 변경하면 안 됨. 애그리거트 루트의 규칙 적용을 어렵게 함.

∘ 도메인 모델에서 public set 메서드는 가급적 사용하지 말아야 함

∘ 밸류 객체의 값을 불변 타입으로 구현함으로써 애그리거트 외부에서 밸류 객체의 상태를 바꾸는 것을 막음 -> 밸류 객체를 바꾸려면 애그리거트 루트가 제공하는 메서드에 새로운 밸류 객체를 전달하는 방법밖에 없음

 

3.2.2 애그리거트 루트의 기능 구현

∘ 애그리거트 루트는 애그리거트 내부의 다른 객체를 조합해서 기능을 완성

∘ 애그리거트는 구성요소의 상태 참조뿐만 아니라 기능 실행을 대신 하기도 함

 

3.2.3 트랜잭션 범위

∘ 트랜잭션 범위는 작을수록 좋음

∘ 한 트랜잭션이 수정하는 테이블 개수 많음 = 트랜잭션 충돌을 막기 위해 잠그는 대상이 많음 = 동시에 처리할 수 있는 트∘ 랜잭션 개수 적음 = 성능 떨어짐

∘ 한 트랜잭션에서 한 애그리거트만 수정하도록 함

 

3.3 리포지터리와 애그리거트

∘ 객체의 영속성을 처리하는 리포지터리는 애그리거트 단위로 존재

∘ 리포지터리는 애그리거트 전체를 저장소에 영속화해야 함

∘ 리포지터리 구현에 사용하는 기술에 따라 애그리거트의 구현도 영향을 받음

 

3.4 ID를 이용한 애그리거트 참조

∘ 애그리거트끼리 참조할 때 애그리거트의 루트를 참조

∘ 애그리거트 간의 참소는 필드를 통해 구현

∘ JPA는 연관관계 어노테이션으로 필드를 이용해 다른 애그리거트를 쉽게 참조

 

∘ 애그리거트 직접 참조의 문제점

  - 다른 애그리거트의 상태 변경이 쉬우므로 기능을 오용할 수 있음

     ->다른 애그리거트의 상태를 변경하는 것을 막기 위해 한 애그리거트가 관리하는 범위는 자기 자신으로 한정해야 함

  - 성능과 관련해서 여러 고민을 해야 됨 ex. JPA의 객체 지연 로딩 / 즉시 로딩

  - 확장에 어려움이 생길 수 있음. 트래픽이 몰려 시스템을 분리하면 서로 다른 저장소를 사용하게 되면서 JPA와 같은 단일 기술을 사용할 수 없게 됨

 

∘ 이 문제들을 해결하기 위해 애그리거트를 참조할 때 ID를 사용해서 한 애그리거트에 속한 객체들만 참조로 연결

  -> 모델의 복잡도 낮춤, 응집도 높임, 구현 복잡도 낮아짐.

 

∘ 애그리거트마다 다른 구현 기술 사용 가능

 

3.4.1 ID를 이용한 참조와 조회 성능

∘ 매번 애그리거트를 읽어오게 되면 쿼리 실행 횟수 늘어남

∘ ID 참조 방식을 사용하면서 N+1 조회와 같은 문제 발생을 막으려면 데이터 조회 전용 쿼리를 만들면 됨

∘ 애그리거트마다 다른 저장소를 사용하면 한 번의 쿼리로 관련 애그리거트를 조회할 수 없으므로 캐시를 이용하거나 조회 전용 저장소를 따로 만듦

 

3.5 애그리거트 간 집합 연관

∘ 컬렉션을 이용한 연관

∘ 개념적으로는 연관이 있어도 성능을 고려해서 구현에 반영하지 않는 경우도 있음

∘ M-N 연관 ex. 카테고리와 상품. 개념과는 달리 구현할 때는 단방향으로 설정하면 됨

 

3.6 애그리거트를 팩토리로 사용하기

∘  애그리거트를 팩토리로 사용하면 도메인의 응집도가 높아짐

∘ 애그리거트가 가지고 있는 데이터를 이용해서 다른 애그리거트를 생성하려 할 때 애그리거트에 팩토리 메서드를 구현하는 것을 고려해볼 수 있음