애그리거트 루트가 단순히 애그리거트에 속한 객체를 포함하는 것으로 끝나는 것은 아니다. 애그리거트 루트의 핵심은 애그리거트의 일관성이 깨지지 않도록 하는 것이다.
불필요한 중복을 피하고 애그리거트 루트를 통해서만 도메인 로직을 구현하게 만들려면 도메인 모델에 대해 두가지를 습관적으로 적용해야한다.
- 단순히 필드를 변경하는 set메서드를 public 으로 만들지 않는다.
- 밸류 타입은 불변으로 구현한다.
set 메서드를 개방시키면 도메인 객체가 아닌 응용영역이나 표현영역으로 분산되게 만드는 원인이 된다. 따라서 도메인 로직이 한곳에 응집되어 있지 않기 때문에 코드를 유지보수 할 때에도 분석하고 수정하는데 더 많은 시간을 들이게 된다.
밸류 객체의 값을 변경할 수 없으면 애그리거트 루트에서 밸류 객체를 구해도 값을 변경할 수 없기 때문에 애그리거트 외부에서 밸류 객체의 상태를 변경할 수 없게 된다.
한 객체가 다른 객체를 참조하는 것처럼 애그리거트도 다른 애그리거트를 참조한다. 애그리거트의 관리 주체가 애그리거트 루트이므로 애그리거트에서 다른 애그리거트를 참조한다는 것은 애그리거트의 루트를 참조한다는 것과 같다.
ORM 기술 덕에 애그리거트 루트에 대한 참조를 쉽게 구현할 수 있고 필드를 이용한 애그리거트 참조를 사용하면 다른 애그리거트의 데이터를 객체 탐색을 통해 조회할 수 있다. 하지만 필드를 이용한 애그리거트 참조는 문제가 있다.
- 편한 탐색 오용
- 성능에 대한 고민
- 확장 어려움
이러한 문제를 해결하기 위해 ID를 이용해서 다른 애그리거트를 참조하는 것이다.
ID를 이용한 참조는 DB 테이블에서의 외래키를 사용해서 참조하는 것과 비슷하게 다른 애그리거트를 참조할 때 ID 참조를 사용한다는 점이다. 단 애그리거트 내의 엔티티를 참조할 때는 객체 래퍼런스로 참조한다.
ID 참조를 사용하면 모든 객체가 참조로 연결되지 않고 한 애그리거트에 속한 객체들만 참조로 연결된다. 이는 애그리거트의 경계를 명확히하고 애그리거트 간 물리적인 연결을 제거하기 때문에 모델의 복잡도를 낮춰준다. 또한 애그리거트 간의 의존을 제거하므로 응집도를 높여주는 효과도 있다.