Quick Comparison
core rule에서 결과·실패·순서가 필요하면 direct call로 요청과 결과를 연결하고, mutation이 끝난 뒤 UI·audio·analytics 같은 독립 consumer가 반응하면 notification을 발행합니다. event는 direct call의 비동기 버전이 아닙니다.
| 상황 | 먼저 선택 | caller가 확인할 것 |
|---|---|---|
| damage 적용·purchase 승인·save 성공 | direct call | result, error, retry, transaction owner |
| HP 변경 뒤 HUD·sound·quest 갱신 | C# event | subscribe/unsubscribe, listener failure |
| 다음 tick·network·persistence 처리 | queue/message | ordering, duplicate, acknowledgement |
| prefab UI의 단순 button response | UnityEvent | persistent target과 runtime listener |
DamageResult result = health.TryApplyDamage(request);
if (!result.Applied) return;
// source of truth가 바뀐 뒤 notification을 발행한다.
DamageApplied?.Invoke(result);요청과 notification을 분리하기
TryApplyDamage 같은 direct method는 validation, permission, resource consumption, failure code를 caller에게 돌려줍니다. caller가 next step을 정하므로 execution order와 error handling이 표면에 보입니다. 이 경로를 DamageRequested event 하나로 바꾸면 누가 처리했는지, 한 handler가 없거나 실패했을 때 누가 retry하는지 모호해집니다.
반면 DamageApplied는 mutation 뒤의 사실입니다. UI, sound, achievement가 서로를 몰라도 반응할 수 있지만, listener 실행 순서에 combat rule을 의존시키지 않습니다. 하나의 service가 다른 service의 state를 바꿔야 하면 event bus를 거치기보다 explicit method/command가 더 읽기 쉬운 경우가 많습니다.
delivery 조건이 달라질 때
in-process C# event는 일반적으로 같은 call stack에서 handler를 실행합니다. 다음 frame에 처리하거나 network로 보낼 일이 있으면 queue와 scheduling owner를 추가합니다. durable event는 process restart 뒤에도 남아야 하는지, event ID로 duplicate를 무시할지, failed consumer가 retry하는지를 정의해야 하므로 단순 observer보다 훨씬 큰 구조입니다.
event listener는 publisher보다 짧은 scene/view scope일 수 있습니다. OnEnable/OnDisable 또는 Dispose에서 해제하고, scene unload와 async callback 뒤에도 listener가 남지 않는지 test합니다. direct call도 cyclic dependency가 생기면 orchestration owner를 분리합니다.
선택 검증
실패와 취소를 포함한 한 흐름을 trace합니다. damage request가 reject됐을 때 notification을 내보내지 않는지, handler가 없는 상태가 gameplay를 막지 않는지, retry가 어느 layer에서 한 번만 수행되는지 확인합니다. event 수가 늘었다는 것이 decoupling 성공의 증거는 아닙니다.
반환값이 필요한 요청을 notification으로 바꾸면 책임이 사라지는 것이 아니라 여러 listener 사이에 숨습니다. core state mutation의 승인·실패는 direct contract에 남기고, 그 결과만 event로 알리세요.
참고 링크
2 sources