생산자와 소비자 사이에 버퍼를 두어 둘을 떼어 놓는 통신 수단. 동기 호출이 "전화"라면 메시지 큐는 "우편함"이다.
동기 호출과 무엇이 다른가
동기 호출
주문서비스 ──HTTP──► 재고서비스
│ │
└─ 재고가 죽으면 주문도 실패
└─ 재고가 느리면 주문도 느림
└─ 재고 응답을 기다리는 동안 스레드 점유
메시지 큐
주문서비스 ──► [ 큐 ] ──► 재고서비스
│ │
└─ 큐에 넣으면 끝. 재고가 죽어 있어도 메시지는 쌓인다
└─ 재고가 살아나면 밀린 것부터 처리
무엇을 얻는가
| 이득 | 설명 |
|---|---|
| 시간 분리 | 소비자가 죽어 있어도 생산자는 계속 보낸다 |
| 부하 평탄화 | 초당 1만 건이 몰려도 큐가 받아 두고 소비자는 초당 1천 건씩 처리 |
| 결합도 감소 | 생산자는 누가 몇 개나 처리하는지 몰라도 된다 |
| 확장 용이 | 밀리면 소비자를 늘리면 된다 |
무엇을 잃는가 — 공짜가 아니다
- 즉시 응답이 사라진다. "결제 완료됐습니다"를 바로 보여줘야 하면 큐는 안 맞는다.
- 순서와 중복 문제가 새로 생긴다. 대부분 at-least-once라 소비자가 멱등해야 한다.
- 추적이 어렵다. 어디까지 처리됐는지 보려면 상관관계 ID·분산 추적이 필요하다.
- 최종 일관성을 받아들여야 한다. 주문 직후 재고에 아직 반영 안 됐을 수 있다.
언제 쓰나 — 판단 기준
응답을 기다릴 필요가 없는 일이면 후보다.
주문 생성 (동기 — 사용자가 결과를 봐야 함)
├─ 재고 차감 (동기 — 실패하면 주문도 취소해야 함)
├─ 알림 발송 (비동기 ✅ — 늦어도 됨)
├─ 통계 집계 (비동기 ✅)
└─ 추천 학습 (비동기 ✅)
면접 답변 골격
"동기 호출로 묶으면 한쪽 장애가 전파되고 피크를 못 견디는 지점에 큐를 넣습니다. 대신 소비자를 멱등하게 만들고, 실패는 재시도와 DLQ로 다룹니다. 사용자가 즉시 결과를 봐야 하는 흐름은 동기로 남깁니다."