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

Hoo-Sung.Lee·2023년 12월 23일
0

Database

목록 보기
1/18
post-thumbnail

한 객체가 다른 객체를 참조하는 것처럼, 애그리거트도 다른 애그리거트를 참조한다. 에그리거트 관리 주체는 에그리거트 루트이므로 에그리거트에서 다른 에그리거트를 참조한다는 것은 다른 에그리거트의 루트를 참조한다는 것과 같다.

order.getOrderer().getMember().getId();

Orderer는 다른 에그리게이트를 직접 참조하는 것이 가능한데 이는 개발자에게 구현의 편리함을 제공한다.

하지만 ORM기술로 @ManyToOne, @OneToOne과 같은 에너테이션을 이용해서 연관된 객체를 로딩하는 기능을 제공하고 있으므로 필드를 이용해 다른 에그리거트를 쉽게 참조할 수 있다. 하지만 필드를 이용한 에그리거트 참조는 다음과 같은 문제를 야기할 수 있다.

  1. 편한 탐색 오용
  2. 성능에 대한 고민
  3. 확장 어려움
  1. 에그리거트를 직접 참조할때 발생할 수 있는 문제는 편리함을 오용할 수 있는 것이다. 한 에그리거트 내부에서 다른 에그리거트 객체에 접근할 수 있으면 다른 에그리거트의 상태를 쉽게 변경할 수 있게 된다. 하지만, 한 에그리거트가 관리하는 범위는 자기 자신으로 한정해야 한다.
    한 에그리거트에서 다른 에그리거트의 상태를 변경하는 것은 에그리거트 간의 의존 결합도를 높여서 결과적으로 에그리거트의 변경을 어렵게 만든다.

  2. 성능에 대한 고민
    에그리거트를 직접 참조하면 성능과 관련된 여러 가지 고민을 해야 한다. JPA를 사용하면 참조한 객체를 지연(lazy) 로딩과 즉시(eager)로딩의 두 가지 방식으로 로딩할 수 있다. 두 로딩 방식 중 무엇을 사용할지는 에그리거트의 어떤 기능을 사용하느냐에 따라 달라진다. 단순히 연관된 객체의 데이터를 함께 화면에 보여줘야 하면 즉시 로딩이 조회 성능에 유리하지만, 에그리거트의 상태를 변경하는 기능을 실행하는 경우에는 불필요한 객체를 함께 로딩할 필요가 없으므로 지연 로딩이 유리할 수 있다.

  3. 확장 어려움이다.

초기에는 단일 서버에 단일 DBMS로 서비스를 제공하는 것이 가능하다. 문제는 사용자가 몰리기 시작하면서이다. 사용자가 늘고 트래픽이 증가하면, 자연스럽게 부하를 분산하기 위해 하위 도메인별로 시스템을 분리하기 시작한다. 이 과정에서 하위 도메인마다 다른 종류의 DB를 사용하기도 한다. 이것은 더 이상 다른 에그리거트 루트를 참조하기 위해 JPA와 같은 단일 기술을 사용할 수 없음을 의미한다.

이런 세가지 문제를 완화할때 사용할 수 있는 방법이 ID를 이용해서 다른 에그리거트를 참조하는 것이다.

ID 참조를 사용하면 모든 객체가 참조로 연결되지 않고 한 에그리거트에 속한 객체들만 참조로 연결된다. 이는 에그리거트의 경계를 명확히 하고 에그리거트 간 물리적인 연결을 제거하기 때문에 모델의 복잡도를 낮춰준다. 또한 에그리거트 간의 의존을 제거하므로 응집도를 높여주는 효과도 있다.

또한 구현 복잡도도 낮아진다. 다른 에그리거트를 직접 참조하지 않으므로, 에그리거트 간 참조를 지연로딩으로 할지, 즉시 로딩으로 할지 고민하지 않아도 된다. 참조하는 에그리거트가 필요하면 응용서비스에서 ID를 이용해서 로딩하면 된다.

외부 에그리거트를 직접 참조하지 않기 때문에 에초에 한 에그리거트에서 다른 에그리거트의 상태를 변경할 수 없다.

에그리거트별로 다른 구현 기술을 사용하는 것도 가능해진다. 중요한 데이터인 주문 에그리거트는 RDMS에 저장하고, 조회 성능이 중요한 상품 에그리거트는 NoSQL에 저장할 수 있다. 또한 각 도메인을 별도 프로세스로 서비스하도록 구현할 수 있다.

결론:
지연 로딩 전략을 가져가고, 다른 에그리거트의 경우 ID로 참조하자.

profile
Working towards becoming Backend-Developer

0개의 댓글