보드 게임과 전장을 통해 DDD 애그리게이트 이해하기
Source: Dev.to
Aggregate는 보드 게임이다
보드 게임을 떠올려 보세요. 하나의 게임이 하나의 Aggregate입니다. 그 안에는 캐릭터, 아이템, 이벤트가 있지만 가장 중요한 것은 규칙입니다. 그 게임 안에서 이루어지는 모든 행동은 그 규칙을 따라야 합니다. 카탄의 규칙은 카탄 안에서만 적용됩니다. 모노폴리의 “출발점 지나면 $200 받기” 규칙을 카탄에 가져올 수는 없습니다.
카탄 자체가 Aggregate이며, 캐릭터나 아이템이 아니라 게임 전체가 Aggregate입니다. 그 안에 캐릭터와 아이템을 배치하면, 그들을 조작하기 위한 Commands를 설계할 수 있습니다. 따라서 Aggregate가 불변성을 보호하는 것은 보드 게임이 규칙을 강제하는 것과 같습니다. 차이점은 현실 세계에서는 그 규칙을 비즈니스 규칙이라고 부른다는 점이며, 현실에서는 그 규칙을 피할 수 없다는 점입니다.
단일 턴 안에서는 모든 행동이 한 번에 해결되어야 합니다—반만 움직이고 나중에 다시 올 수 없습니다. 이것은 또 다른 핵심 개념과 연결됩니다:
Aggregate는 트랜잭션 일관성 경계이다. 모든 것이 성공하거나, 모든 것이 실패합니다. 중간 단계는 없습니다.
전쟁터와 전쟁 지휘실
실제 전쟁터가 하나의 Aggregate입니다. 지휘관의 모래판은 또 다른 Aggregate입니다. 모래판에서는 깃발이 각 장군을 나타내지만, 깃발 자체가 장군은 아닙니다. 그것은 식별자(ID) 로서 “이 사람이 존재한다”는 것을 지휘관에게 알려줍니다. 장군의 전체 상태는 전쟁터에 존재합니다.
두 Aggregate는 같은 사람에 대해 전혀 다른 관점을 가집니다. 모래판은 장군이 얼마나 심하게 부상했는지, 남은 병력이 얼마나 되는지는 알 필요가 없습니다. 오직 “그가 아직 이용 가능한가?” 만 알면 됩니다.
그래서 Aggregate 경계 사이에서는 객체 참조가 아니라 ID만 저장합니다—절대 객체 참조를 저장하지 않습니다. 경계는 명확히 구분돼야 합니다.
전쟁터에서 무언가가 발생하면, 전령이 전쟁 지휘실로 달려가 지휘관들이 모래판을 업데이트합니다. 이 전령이 DDD에서 Policy 라고 부르는 것입니다. 하나의 Aggregate가 발생시킨 Domain Event 를 듣고, 다른 Aggregate에서 반응을 일으킬지 결정합니다.
이것이 DDD가 EventSourcing 및 CQRS와 자연스럽게 어우러지는 이유입니다—전체 시스템이 경계 사이를 흐르는 이벤트를 통해 협업합니다. 직접 호출이 아니라, 공유 객체가 아니라, 이벤트를 통해서입니다.
마무리
이 두 가지 개념이 맞물리자, 이전에 막혔던 많은 설계 결정들이 명확한 답을 얻게 되었습니다.
이 비유가 모두에게 통할지는 모르겠지만, 저에게는 DDD가 이제는 전문 용어의 무더기가 아니라는 것을 처음으로 깨닫게 해준 사례였습니다. 때때로 여러분이 막힌 이유는 충분히 노력하지 않아서가 아니라, 아직 올바른 관점을 찾지 못했기 때문일 수도 있습니다.
비슷한 깨달음의 순간을 겪으셨다면, 댓글로 공유해 주세요.