[DDD] AGGREGATE(애그리거트)

0️⃣1️⃣·2024년 1월 29일
0

DDD

목록 보기
1/21
post-thumbnail
post-custom-banner

Aggregate의 루트

먼저 우리는 모델 내의 참조에 대한 캡슐화를 추상화할 필요가 있다. AGGREGATE는 우리가 데이터 변경의 단위로 다루는 연관 객체의 묶음을 말한다. 각 AGGREAGTE는에는 루트(root)와 경계(boundary)가 있다. 경계는 AGGREGATE에 무엇이 포함되고 포함되지 않는지를 정의한다. 루트는 단 하나만 존재하며, AGGREAGTE에 포함된 특정 ENTITYT를 가리킨다. 경계 안의 객체는 서로 참조할 수 있지만, 경계 바깥의 객체는 해당 AGGREGATE의 구성요소 가운데 루트만 참조할 수 있다. 루트 이외의 ENTITY는 지역 식별성(local identity)을 지니며, 지역 식별성은 AGGREGATE 내에서만 구분되면 된다. 이는 해당 AGGREGATE의 경계 밖에 위치한 객체는 루트 ENTITY의 컨텍스트 말고는 AGGREAGTE의 내부를 볼 수 없기 때문이다. (도메인 주도 개발 - Eric evans)

  • AGGREGATE의 경계 밖에 위치한 객체는 루트 ENTITY를 통해서만 AGGREGATE를 접근할 수 있음
  • AGGREGATE의 경계 내의 위치한 객체들은 루트 ENTITY를 통해서 접근할 수 있어야 함

Aggregate의 불변식

불변식은 데이터가 변경될 때마다 유지돼야 하는 일관성 규칙을 뜻하며, 여기엔 AGGREGATE를 구성하는 각 구성요소 간의 관계도 포함될 것이다. 그러나 여러 AGGREGATE에 걸쳐 존재하는 규칙이 언제나 최신 상태로 유지되는 것은 아니다. 다른 의존 관계는 이벤트 처리, 배치 처리, 혹은 다른 갱신 메커니즘을 토대로 특정 시간 내에 해결할 수 있다. 반면, 한 AGGREGATE에 적용된 불변식은 각 트랜잭션이 완료될 때 이행될 것이다. (도메인 주도 개발 - Eric evans)

  • 한 AGGREGATE내의 불변식은 트랜잭션이 완료될 때 이행되어야 함
  • 여러 AGGREGATE에 걸친 규칙은 언제나 최신 상태로 유지되는 것은 아니나 특정 시간 내에 해결이 될 수 있음

Aggregate 구현에 필요한 규칙

루트 ENTITY는 전역 식별성을 지니며 궁극적으로 불변식을 검사할 책임이 있다. (도메인 주도 개발 - Eric Evans)

각 루트 ENTITY는 전역 식별성을 지닌다. 경계 안의 ENTITY는 지역 식별성을 지니며, 이러한 지역 식별성은 해당 AGGREGATE안에서만 유일하다. (도메인 주도 개발 - Eric Evans)

AGGREGATE의 경계 밖에서는 루트 ENTITY를 제외한 AGGREGATE 내부의 구성요소를 참조할 수 없다. 루트 ENTITY가 내부 ENTITY에 대한 참조를 다른 객체에 전달해 줄 수는 있지만 그러한 객체는 전달받은 참조를 일시적으로만 사용할 수 있고, 참조를 계속 보유하고 있을 수는 없다. 루트는 VALUE OBJECT의 복사본을 다른 객체에 전달해줄 수 있으며, 복사본에서는 어떤 일이 일어나든 문제되지 않는다. 이것은 복사본이 단순한 VALUE에 불과하며 AGGREGATE와는 더는 연관관계를 맺지 않을 것이기 때문이다. (도메인 주도 개발 - Eric Evans)

지금까지의 규칙을 바탕으로 결론을 내려보면 데이터베이스 질의를 이용하면 AGGREGATE의 루트만 직접적으로 획득할 수 있다. 다른 객체는 모두 AGGREGATE를 탐색해서 발견해야 한다. (도메인 주도 개발 - Eric Evans)

AGGREGATE 안의 객체는 다른 AGGREGATE의 루트만 참조할 수 있다. (도메인 주도 개발 - Eric Evans)

삭제 연산은 AGGREGATE 경계 안의 모든 요소를 한 번에 제거해야 한다. (도메인 주도 개발 - Eric Evans)

AGGREGATE 경계 안의 어떤 객체가 변경하더라도 전체 AGGREGATE의 불변식은 모두 지켜져야 한다. (도메인 주도 개발 - Eric Evans)

ENTITY와 VALUE OBJECT를 AGGREGATE로 모으고 각각에 대해 경계를 정의하라. 한 ENTITY를 골라 AGGREGATE의 루트로 만들고 AGGREGATE 경계 내부의 객체에 대해서는 루트를 거쳐 접근할 수 있게 해라. AGGREGATE 밖의 객체는 루트만 참조할 수 있게 하라. 내부 구성요소에 대한 일시적인 참조는 단일 연산에서만 사용할 목적에 한해 외부로 전달될 수 있다. 루트를 경유하지 않고는 AGGREGATE의 내부를 변경할 수 없다. 이런식으로 AGGREGATE의 각 요소를 배치하면 AGGREGATE안의 객체와 전체로서의 AGGREGATE의 상태를 변경할 때 모든 불변식을 효과적으로 이행할 수 있다. (도메인 주도 개발 - Eric Evans)

Aggreagte 예제

우리는 경합이 높은 지점을 느슨하게 하고, 엄격한 불변식을 더욱 지켜지게 하는 모델을 찾을 필요가 있다. (도메인 주도 개발 - Eric Evans)

  • Purchas Order(구매주문), Line Item(주문 품목)
  • 각 주문 품목의 합계는 전체적으로 구매주문 한도를 초과할 수 없다는 불변식이 존재

  • 위 그림은, Aggregate의 경계를 결정하지 못한 설계
  • 주문 품목에만 Locking이 존재하는 상황
    • 두 사용자가 동일한 구매 주문의 주문 품목에 대해서
      정할 수 있으나, 커밋이 발생하면 불변식이 어겨지는
      경우가 발생할 수 있다.
  • 구매 주문 전체에 Locking이 존재하는 상황
    • 항상 불변식이 성립하나, Locking의 범위가 크므로 불편함을 초래
    • 특정 품목을 공유하고 있는 여러 구매 주문에서 이전 트랜잭션이 끝나기를 기다려야 함
    • 특정 품목으로 인해서 DeadLock이 발생할 수 있음 (어떤 품목에 대한 Lock을 갖고 있는데, 다른 품목에 대한 Lock을 다른 구매주문에서 갖고 있어서 서로 기다리는 상황 발생)

  • 새로운 업무 지식을 반영해 모델을 개선(도메인 주도 개발)
    • 품목은 여러 구매 주문에서 사용된다(경합이 높음)
    • 구매주분보다는 품목의 변경이 더 적다.
    • 품목 가격에 대한 변경 내역이 반드시 기존 구매주문에 전해질 필요는 없다. 이는 구매주문의 상태와 관련된 가격 변경 시점에 좌우 된다.
  • Part의 가격을 복사해서 사용하므로, 구매 시점의 가격을 반영하고 품목으로 인해서 Locking이 발생하지 않으므로, 불편함이 해소됨

Refrence

  • 도메인 주도 개발 (Eric evans)
post-custom-banner

0개의 댓글