애그리거트 간에 ID 참조를 해야하는 이유

공병주(Chris)·2023년 1월 25일
1

우아한테크코스 마지막 미션을 하면서 애그리거트라는 개념에 대해서 알았고, 우아한 형제들 조영호님의 유명한 객체지향 강의를 통해 애그리거트 간에 간접 참조를 하는 것이 좋다는 사실을 알았습니다. 해당 영상을 보게되었을 때, 애그리거트 간 간접 참조의 장점에 대해 명확히 깨닫지 못했습니다. 그런데, 도메인 주도 개발 시작하기를 읽으면서 해당 궁금증이 조금은 풀렸는데요. 이에 대해 알아보겠습니다.

애그리거트

먼저, 애그리거트에 대해 정의해보겠습니다.

소프트웨어가 풀려는 영역이 넓어지고 그에 따라 어플리케이션의 덩치가 커지다 보면 여러 하위 도메인들이 존재한다. 따라서, 도메인들의 관계가 복잡해지다보면 전반적인 구조나 큰 수준에서 도메인 간의 관계를 파악하기 어렵습니다.

큰 수준에서의 도메인 관계를 파악하기 어렵다는 것은 코드를 변경하고 확장하는 것이 어려워진다는 것을 의미한다. 상위 수준에서 모델이 어떻게 엮여 있는지 알아야 전체 모델을 망가뜨리지 않으면서 추가 요구사항을 모델에 반영할 수 있는데, 세부적인 모델만 이해한 상태로는 코드를 수정하는 것이 꺼려지기 때문에 코드 변경을 최대한 회피하는 쪽으로 요구사항을 협의하게 된다. 꼼수를 부려 당장 돌아가는 코드를 추가할 수는 있지만 이런 방법은 장기적으로 코드를 더 수정하기 어렵게 만든다.

도메인 주도 개발 시작하기(최범균) 중,

따라서, 상위 수준(조금 더 큰 틀)에서 모델을 조망해야한다. 다른 말로, 큰 수준에서의 도메인 관계를 파악해야한다는 뜻이다. 이를 위한 개념이 애그리거트입니다.

위와 같이 조금은 복잡한 여러 도메인간의 관계들을 조금 더 높은 수준에서의 관계로 바라보는 것입니다.

한 애그리거트에 속해있는 객체는 다른 애그리거트에 속하지 않는 독립적인 것입니다.

경계를 설정할 때 기본이 되는 것은 도메인 규칙과 요구사항이다. 도메인 규칙에 따라 함께 생성되는 구성요소는 한 애그리거트에 속할 가능성이 높습니다.

애그리거트 간 ID를 통한 간접 참조

과거에 봤던 우아한형제들 조영호님의 객체지향 세미나 영상에서,
어떤 객체들을 객체 참조 관계로 가져갈 것인지에 대해 아래와 같은 가이드라인을 제시하십니다.

첫째, 함께 생성되고 함께 삭제되는 객체들을 함께 묶어라

둘째, 도메인 제약사항을 공유하는 객체들을 함께 묶어라

셋째, 가능하면 분리하라

과거에 이 규칙에 따라서 객체 참조 관계를 두었고, 나머지는 Id를 통해서 간접 참조 관계를 가지도록 했습니다. 그때는 왜 이렇게 해야하지? 라는 생각이 들었지만, 이유를 생각해내기가 쉽지 않았습니다.

책을 읽으면서 애그리거트라는 정의를 알게되고 과거에 조영호님이 ID를 통한 참조를 하도록 하는 관계들이 애그리거트인 것 같다는 생각이 들었습니다. 그리고 도메인 주도 개발 시작하기 라는 책을 읽으면서 애그리거트 간에 ID 참조를 해야하는 이유를 찾을 수 있었십니다.

변경 범위를 한정하기가 힘듦

애그리거트 간에 탐색이 가능하면 변경이 발생할 수 있는 범위를 한정하기가 힘듭니다

애그리거트 간에 객체 참조 관계라면, 특정 애그리거트에 다른 애그리거트에 대한 변경을 할 수 있습니다. 다시 말해, 다른 애그리거트에 대한 로직이 포함될 수 있습니다.

애그리거트 단위로 비즈니스 로직이 모여있지 않다면, 애그리거트 단위로 로직을 파악하기 힘들기 때문에 어디서 변경이 일어나는지에 대해 추적하기가 힘듭니다.

애그리거트끼리 객체 참조를 하지 않는다면, 다른 애그리거트의 변경을 원천적으로 차단할 수 있고 애그리거트의 응집도를 높일 수 있습니다.

실제로, 과거에 우테코 팀 프로젝트 당시에 모든 객체들을 객체 참조 관계로 두었습니다. 그 결과, 객체들이 어디서 변경되는지 추적하기가 힘들었던 경험이 있습니다.

JPA와 함께 사용했을 때의 문제점

JPA를 사용하면 객체 참조를 쉽게 할 수 있습니다. 다른 애그리거트 객체 참조 관계를 무분별하게 걸면 탐색을 무분별하게 할 수 있기 때문에, N + 1 문제와 같은 쿼리들을 제어하기가 힘듭니다. 또한, 이를 Lazy Loading 할지 Eager Loading 할지에 대한 고민도 해야합니다.

확장

초기에 단일 DBMS를 사용하던 시스템이 트래픽 증가에 따라 MSA와 같은 형태로 분리되고 DBMS도 분리되는 상황을 고려해보겠습니다. 애그리거트 단위로 시스템이 그대로 분리되는 것은 아니겠지만, 분명히 특정 애그리거트에서 참조하고 있는 애그리거트가 다른 시스템으로 분리되는 상황이 발생할 것입니다. 이런 경우에 해당 시스템의 DBMS에서 다른 애그리거트에 대한 정보를 함께 Loading 할 수 없기 때문에 객체 참조를 모두 걷어내야합니다.


참고자료

0개의 댓글