메시지 큐 기초
보내는 쪽과 받는 쪽을 비동기로 떼어놓아 결합도를 낮춥니다. 상대가 느리거나 잠시 죽어도 요청이 큐에 남습니다.
메시지 큐 기초
왜 메시지 큐가 필요한가?
- 비동기 처리: 이메일 발송, 알림 등 즉시 응답 불필요한 작업
- 디커플링: 서비스 간 직접 의존 제거
- 버퍼링: 트래픽 급증 시 요청을 큐에 저장 후 처리
주요 메시지 브로커
| 브로커 | 특징 | 적합 사례 |
|---|---|---|
| Kafka | 고처리량, 로그 기반 | 이벤트 스트리밍, 로그 수집 |
| RabbitMQ | 유연한 라우팅, AMQP | 작업 큐, RPC |
| SQS | AWS 관리형 | 간단한 비동기 처리 |
큐를 넣으면 새로 생기는 것
받는 쪽과 보내는 쪽을 떼어 놓는 대신 네 가지를 감수합니다.
같은 메시지를 두 번 받을 수 있습니다. 대부분의 큐는 적어도 한 번 전달을 약속하고 정확히 한 번은 약속하지 않습니다. 넘긴 뒤 확인이 유실되면 다시 보냅니다. 그래서 받는 쪽이 두 번 처리해도 결과가 같도록 만들어야 합니다.
순서가 보장되지 않습니다. 나눠서 처리하는 순간 도착 순서가 보낸 순서와 달라집니다. 순서가 필요하면 같은 대상의 메시지를 한 줄로 모아야 하고, 그러면 그 줄만큼만 병렬이 됩니다.
실패한 메시지가 갈 곳이 필요합니다. 계속 실패하는 하나가 줄 앞을 막으면 뒤가 전부 멈춥니다. 정해진 횟수를 넘기면 따로 빼 두고, 그 자리를 사람이 봐야 합니다.
큐 자체가 장애 지점이 됩니다. 큐가 죽으면 보내는 쪽이 무엇을 해야 하는지 정해 두어야 합니다. 요청을 거절할지, 일단 받아 두고 나중에 넣을지의 선택입니다.
언제 넣지 않는가
| 상황 | 왜 |
|---|---|
| 결과를 바로 돌려줘야 한다 | 큐는 언제 처리될지 약속하지 않는다 |
| 처리량이 부족하다 | 큐는 몰림을 흡수하고 처리량을 늘리지 않는다 |
| 흐름이 단순하고 그대로일 것이다 | 직접 부르는 것이 읽기 쉽다 |
두 번째가 가장 흔한 오해입니다. 평균 유입이 처리 속도를 넘으면 큐 길이는 무한히 자랍니다. 큐를 크게 잡는 것은 시간을 버는 것이고 문제를 없애는 것이 아닙니다.
실무 포인트
- At-least-once vs Exactly-once: 대부분 At-least-once → 멱등성 보장 필요
- 메시지 순서 보장이 필요한가? → Kafka 파티션 키 활용
- DLQ(Dead Letter Queue)로 실패 메시지 관리
- Q.메시지 큐를 왜 쓰나요?
- Q.메시지 큐를 쓰면 안 되는 경우는 언제인가요?
- Q.메시지 유실을 어떻게 방지하나요?