이벤트 드리븐 아키텍처
주문 한 건을 동기 사슬(지연 합산·장애 전파)과 이벤트 발행(즉시 응답·장애 격리·이벤트 보존)으로 처리해 비교하고, 발행자를 안 건드리는 소비자 추가까지 실행한다.
사용자 응답: 실패 · 응답 시간 —
단계 목록 · 키보드 ←/→ 이동, Space 재생
EDA는 '해 줘(명령·호출)'를 '일어났다(사실·이벤트)'로 바꾸는 것이다 — 발행자는 구독자를 모르고, 그래서 지연·장애·조직 결합이 한꺼번에 풀린다.
왜 헷갈리는가
"비동기 처리 = EDA"가 아니다. 큐에 '이메일 보내 줘' 작업을 넣는 것은 비동기 명령(받는 이를 안다)이고, '주문됨' 이벤트를 발행하는 것은 사실의 공표(누가 듣는지 모른다)다. 이 방향 차이가 결합도의 차이를 만든다.
애니메이션이 보여주는 것
동기 사슬의 산수: 응답 시간은 합(550ms), 가용성은 곱(99.9%⁴≈99.6%) — 그리고 사슬 끝의 알림 장애가 주문 실패로 역류한다. '알림이 안 가서 주문이 안 되는' 결합이 동기 호출의 정체다.
이벤트로 바꾸면 주문 서비스는 검증 후 '주문됨'을 발행하고 즉시(120ms) 응답한다. 재고·결제·알림은 각자 구독해 자기 속도로 처리하고, 알림이 죽어도 이벤트는 브로커에 남아 복구 후 이어진다 — 장애가 유실이 아니라 지연으로 강등된다. 마지막 장면: 분석팀이 새 소비자를 붙여도 주문 서비스는 코드 한 줄 안 바뀐다.
정직한 대가
EDA가 새로 사는 문제들 — 설계 숙제가 된다.
- 최종 일관성: '주문됨' 응답이 '결제 완료'를 뜻하지 않는다. UI·업무 흐름이 중간 상태를 다뤄야 한다.
- 중복 배달: 브로커는 대개 at-least-once — 소비자는 멱등해야 한다(이벤트 ID 기록, 자연 멱등 연산).
- 순서: 전역 순서는 없다. 필요한 단위(주문 ID)로 파티션 키를 잡는다.
- 관측: 요청 하나의 흐름이 여러 서비스·시간대에 흩어진다 — 상관 ID와 분산 추적이 필수품이 된다.
- 이중 쓰기 함정: 'DB 갱신 + 이벤트 발행'이 둘 다 성공해야 한다면 아웃박스 패턴(한 트랜잭션으로 outbox에 쓰고 릴레이가 발행)이 표준 처방이다.
언제 동기, 언제 이벤트인가
가르는 질문은 '지금 답이 필요한가'다. 결제 승인·재고 확인처럼 응답이 다음 행동을 결정하면 동기가 맞다. '주문됨·가입됨·결제됨'처럼 일어난 사실의 통지라면 이벤트가 맞다. 실전 시스템은 명령엔 동기, 사실엔 이벤트를 섞어 쓴다.
기억할 것
- 명령('해 줘')과 사실('일어났다')를 구분하라 — EDA는 후자다.
- 동기 사슬: 지연은 합, 가용성은 곱, 장애는 역류한다.
- 이벤트 보존 덕에 장애가 유실이 아니라 지연이 된다.
- 대가: 최종 일관성·멱등 소비자·아웃박스 — 공짜가 아니다.
- 즉시 답이 필요하면 동기, 사실의 공표면 이벤트 — 섞어 쓰는 게 정상이다.