Request/response vs event-driven

judgment
상황

주문 결제가 끝나면 알림 발송, 포인트 적립, 재고 차감 같은 후속 작업을 해야 한다. 후속 서비스들을 그냥 REST로 직접 호출할지, 이벤트 하나 발행하고 각자 알아서 구독하게 할지 정해야 한다.

😴 Boring — 동기 REST 호출 (request/response)

언제: 후속 작업이 한두 개뿐이고, 호출한 쪽이 결과를 바로 알아야 할 때. 호출 하나면 로그 따라가기도 쉽고, 실패하면 그 자리에서 에러를 돌려주면 끝이다.

비용: 상대 서비스가 느려지면 내 응답도 같이 느려지고, 상대가 죽으면 나도 같이 실패한다. 후속 작업이 하나 늘 때마다 내 코드에 호출을 또 붙여야 해서, 남의 기능 때문에 내 서비스를 배포하게 된다.

✨ Novel — 이벤트 발행 (Kafka/SQS 같은 메시지 큐)

언제: 구독자가 3개 이상으로 늘고 각각 다른 팀 소유일 때, 보내는 쪽이 결과를 기다릴 필요가 없을 때, 트래픽 스파이크를 큐가 흡수해줘야 할 때.

비용: 결과가 바로 안 보여서 "지금 처리됐나?"에 즉답을 못 한다. 중복 소비 대비 멱등 처리, DLQ, 컨슈머 랙 모니터링, 분산 추적까지 운영 부담이 통째로 따라온다. 발행과 DB 저장을 맞추려면 outbox 같은 장치도 추가로 필요하다.

⚖️ 기본 판단

기본은 동기 REST로 시작한다. 호출이 한두 개일 땐 그게 제일 단순하고 장애 추적도 쉽다. 컨슈머가 3개를 넘거나, 다운스트림 지연 때문에 내 p99가 끌려 올라가거나, 후속 기능 추가 때마다 두 팀이 한 배포에 묶이기 시작하면 그때 이벤트로 전환한다.

🚨 트립와이어 — 이 신호가 오면 바꾼다
  • 내 API p99가 다운스트림 호출 때문에 500ms를 넘기 시작한다
  • 다운스트림 한 곳 장애에 내 5xx 비율이 1% 이상으로 같이 튄다 — 장애가 전파되고 있다는 신호
  • 요청 하나에 동기 호출이 3개 이상 줄줄이 붙어 타임아웃이 곱으로 쌓인다
  • 후속 기능 하나 추가할 때마다 두 팀이 같은 배포에 묶여 일정이 밀린다

🔧Kafka / SQStransactional outboxDLQ + 재처리consumer-lag 알람OpenTelemetry 분산 추적

🗣 영어 한 줄 평결

I default to plain request/response; once a third consumer appears or downstream latency drags my p99, I switch to events.

checking microphone…

⚔️ Defend it — AI 시니어가 반박한다. 영어로 버텨라.

첫 메시지로 네 입장을 영어로 선언해라 — 예: “I'd start with 동기 REST 호출 here, and only switch when …” 그러면 상대가 반박을 시작한다. 근거·숫자·트립와이어로 받아쳐라.

두어 번은 치고받은 뒤에 채점