Quick Flow
service boundary는 API 개수가 아니라 source of truth와 mutation owner를 정하는 기준입니다. 다른 service가 collection·field를 직접 바꾸지 않고, owner에게 command를 요청하고 result/notification을 통해 다음 일을 합니다.
RewardService
-> InventoryService.TryAdd(itemId, amount)
-> result: applied / rejected
-> InventoryChanged notification
-> SaveCoordinator creates snapshot
InventoryService만 item count를 변경한다.| state | source of truth | 외부 협력 방식 |
|---|---|---|
| item ownership·count | InventoryService | TryAdd/TryRemove, changed event |
| quest progression | QuestService | command, quest result |
| player combat state | Combat/Player state owner | damage/heal contract |
| serialized snapshot | Save service | read-only snapshot / restore command |
| UI display cache | presenter/view | owner event를 구독 |
mutation을 owner에게 요청하기
RewardService가 inventory.Items.Add(...)를 직접 호출하면 capacity, duplicate stacking, validation, change notification, save dirty mark가 여러 caller에 흩어집니다. InventoryService.TryAdd가 mutation과 result를 소유하면 실패 사유·transaction boundary·notification 시점을 한곳에서 보장할 수 있습니다.
public AddItemResult Grant(string itemId, int amount)
{
AddItemResult result = inventory.TryAdd(itemId, amount);
if (!result.Added) return result;
rewardLog.Record(itemId, amount);
return result;
}owner가 모든 일을 혼자 처리한다는 뜻은 아닙니다. quest completion이 reward를 요청하고 inventory success 뒤 quest state를 확정하는 흐름에서는 coordinator 또는 transaction contract가 순서를 조정합니다. 어느 state가 먼저 바뀌고 compensation/rollback이 필요한지는 direct request path에 남기며, UI·analytics처럼 독립 반응만 post-mutation event로 보냅니다.
읽기, snapshot, 복구
외부 consumer에는 mutable collection 대신 read-only query, immutable snapshot, derived value를 제공합니다. save system은 live object graph를 직렬화 대상으로 삼기보다 owner가 제공한 stable snapshot을 저장하고, load 때는 restore command로 owner가 validation·migration·event policy를 처리하게 합니다. network synchronization도 같은 source of truth와 version policy가 있어야 client cache가 service를 대신하지 않습니다.
두 service가 같은 field를 직접 쓰기 시작하면 owner를 하나로 합치거나, shared domain state와 coordinator를 새 경계로 만듭니다. 이름만 나눈 service 사이에 circular call이 계속 생기면 responsibility와 transaction flow가 잘못 나뉜 신호입니다.
ownership 검증
item add 실패, duplicate request, save/load 직후, network retry, UI가 disable된 상태에서 change event가 올 때를 test합니다. source of truth가 하나인지, event가 mutation 뒤 한 번만 발행되는지, 다른 service가 internal collection을 수정하지 않는지 code search로 확인합니다.
service가 다른 service의 내부 데이터를 직접 고치는 순간 source of truth가 둘이 됩니다. 경계를 넘는 편의 메서드는 늘어도 되지만, state mutation의 최종 owner는 늘리지 마세요.
참고 링크
2 sources