최근에 비동기 처리를 추가할 일이 생겼는데, 막상 시작하려니
“그래서 나는 어떤 큐를 써야 하지?”라는 고민이 제일 먼저 들었습니다.
Kafka도 흔히 큐처럼 사용되고, RabbitMQ는 이름부터 Message Queue이고, Redis로도 큐를 만들어 쓸 수 있다 보니 더 헷갈리더라고요.
정리해 보니 결국 중요한 건 이름이 아니라, 내가 원하는 동작이었습니다.
메시지를 다시 처리해야 하는지, 작업을 어떻게 나눌 건지, 유실을 어디까지 허용할 수 있는지, 운영 복잡도는 감당 가능한지 같은 부분이 중요했습니다.
그래서 이 글에서는 먼저 선택해 보고(선택표) → 기준을 세운 뒤(질문) → 각 큐를 이해하는(설명) 순서로 정리해보려 합니다.
먼저 선택표부터
| 상황/요구 | 추천 |
| 이벤트 로그, CDC, 재처리·재생 가능해야 함 | Kafka |
| 작업 큐, 라우팅/재시도/DLQ가 필요함 | RabbitMQ (혹은 SQS/ActiveMQ) |
| 초경량 비동기, 매우 낮은 지연, 이미 Redis 보유 | Redis Queue/Streams |
| 기록용 + 즉시 처리 병행 | Kafka로 기록, Redis로 즉시 작업 |
여기서 끝내도 되고, “왜?”가 궁금하면 아래 “4가지 질문”으로 한 번 더 체크해 보면 좋습니다.
선택을 결정짓는 4가지 질문
표가 애매하게 느껴지는 경우에는 이 질문 4개만 답해보면 방향이 잡힙니다.
- 메시지를 다시 읽어야 하나? (과거 재생, 리플레이)
- 여러 Consumer가 각각 처리해야 하나? 아니면 하나만 처리하면 되나?
- 장애 시 유실을 허용할 수 있는가?
- 운영 복잡도(클러스터, 모니터링, 튜닝)를 감당할 수 있는가?
용어만 정리..!
• Producer: 메시지를 생성해 큐/토픽으로 보내는 주체.
• Consumer: 메시지를 받아 실제 작업을 수행하는 주체.
• Queue/Topic: 메시지가 소비되기 전까지 머무는 논리적 단위.
Kafka는 Topic이라는 로그 구조를 사용하고, RabbitMQ와 Redis는 Queue나 Stream/List 같은 구조로 메시지를 분배한다.
• Offset/Ack: 메시지 처리 진행 상황을 표시하는 방식.
Kafka는 Offset으로 읽은 위치를 기록하고, RabbitMQ/Redis Streams는 Ack를 통해 처리 완료를 확정한다.
큐별로 뭐가 다를까?
이제부터는 Kafka/RabbitMQ/Redis가 각각 어떤 상황에 강한지, “쓰임새 기준”으로 정리해 보겠습니다.
Kafka (이벤트 스트리밍)
- 한마디로: 이벤트를 길게 쌓아두고, 필요하면 과거까지 되감아 보는 로그 창고.
- 디스크 기반 로그, Offset으로 재처리·재생 가능.
- 매우 높은 처리량, 다수 Consumer가 각자 읽어감.
- 운영 난이도 높음(클러스터/모니터링/스키마 관리 필요).
- 주 용도: 도메인 이벤트, CDC, 로그 파이프라인.
Kafka 아키텍처 개요

- Producer가 메시지를 Topic/Partition에 push(실제로는 브로커에 append)합니다.
- 다수의 Broker가 Topic을 Partition 단위로 분산 저장해 확장성과 내결함성을 확보합니다.
- Consumer가 pull 방식으로 읽으며, Consumer Group을 사용해 스케일아웃합니다.
Topic/Partition/Consumer Group 동작

- 하나의 Topic은 여러 Partition으로 나뉘어 병렬 처리·저장이 가능합니다.
- Producer는 특정 Partition에 레코드를 보냅니다(키 기반 파티셔닝 등).
- Consumer Group은 Partition을 나눠 맡아 읽고, 그룹 내에서 메시지가 중복 처리되지 않도록 조정합니다.
Offset으로 재생·재처리

- 각 Partition은 순차적인 Offset을 갖습니다. Consumer Group은 자신이 어디까지 읽었는지 Offset으로 기록합니다.
- Offset을 되돌리면 과거 메시지를 다시 읽어 재처리·재생이 가능합니다.
- 로그가 디스크에 일정 기간 보관되므로, 재처리/분석/장애 복구 시 유용합니다.
RabbitMQ (메시지 브로커)
- 한마디로: 작업 분배기. 들어온 일을 큐에 넣고 여러 작업자가 나눠 처리.
- 메시지를 큐에 넣고 한 Consumer가 처리(워크 큐 모델).
- Exchange/Binding으로 라우팅 유연, Ack/Retry/DLQ 기본 제공.
- 처리량·운영 복잡도 중간, 작업 큐에 최적.
- 주 용도: 주문 처리, 백그라운드 잡, 워크플로 분기.
RabbitMQ 라우팅 개요

- Publisher가 메시지를 Exchange에 발행하면, Binding 규칙에 따라 하나 혹은 여러 Queue로 복사·분기됩니다(Direct/Topic/Fanout/Headers).
- 각 Queue는 소비자에게 분배되며, 소비자는 Ack로 처리 완료를 알립니다. Ack가 없으면 재전송되거나 DLQ로 보낼 수 있습니다.
- “한 메시지 = 한 작업” 모델에 강해 주문·티켓 처리 같은 워크 큐, 라우팅이 많은 워크플로에 적합합니다.
Redis Queue/Streams (인메모리 큐)
- 한마디로: 가벼운 전달자. 메모리에 잠깐 올려두고 바로 소비.
- In-memory라 매우 빠름, 설정·운영이 단순.
- 기본 List/PubSub/Streams로 큐 구현. Streams는 Consumer Group/Offset 지원.
- 내구성·장기 보관은 약함, 재처리·Retry 로직은 직접 설계 필요.
- 주 용도: 알림 트리거, 캐시 갱신, 단기·경량 백그라운드 작업.
Redis Streams: Consumer Group 처리

- Producer가
XADD로 스트림에 메시지를 append합니다(시간순 로그). - Consumer Group이
XREADGROUP으로 메시지를 가져가고, 처리 후XACK으로 완료를 알립니다. - 각 메시지는 그룹 내에서 한 번만 할당되며, Ack 되지 않은 메시지는 Pending List에 남아 재전달이 가능합니다.
- 여러 Consumer 인스턴스가 병렬로 처리하되, 같은 메시지가 중복 소비되지 않게 조정되는 점이 핵심입니다.
Redis Pub/Sub: 실시간 브로드캐스트

- Publisher가 채널에 메시지를 Publish 하면, 구독 중인 Subscriber가 곧바로 수신합니다.
- 메시지가 Redis에 남지 않으므로 Subscriber가 없거나 잠시 끊겨 있으면 유실됩니다.
- “실시간 알림”처럼 즉시 전달이 중요하고 유실이 치명적이지 않은 경우에 적합합니다.
Redis List Queue: 단순 FIFO

LPUSH로 넣고RPOP또는BLPOP으로 빼는 단순 FIFO 큐입니다.- 별도 Ack 개념이 없어 소비자가 실패하면 재처리를 직접 구현해야 합니다.
- 간단한 백그라운드 작업이나 일시적 큐잉에 적합하지만, 안정적 재처리나 DLQ가 필요하면 Streams나 별도 로직이 필요합니다.
큐별 동작 원리 요약
위 내용을 “동작 방식” 기준으로 한 번에 요약하면 이렇게 정리됩니다.
- Kafka: Producer가 Topic/Partition에 로그를 append(디스크). Consumer Group이 Offset을 기준으로 읽고 commit 합니다. 메시지는 보관 기간 동안 남아 여러 Consumer가 각자 읽을 수 있고, 과거 재생도 가능합니다.
- RabbitMQ: Producer → Exchange → Binding 규칙으로 Queue에 라우팅. Consumer가 메시지를 받아 Ack 하며, Ack가 없으면 재전송(DLQ로 이동 가능)됩니다. 1개 큐의 메시지를 여러 Consumer가 “나눠 처리”하는 워크 큐에 강점이 있습니다.
- Redis Queue/Streams: List는 LPUSH/RPOP의 단순 FIFO(ack 없음). Pub/Sub은 저장 없이 즉시 전달(수신자가 없으면 유실). Streams는 append-only 로그 + Consumer Group/Offset으로 기본 ack/재전송을 지원해 Redis 내에서 가장 브로커스러운 모델입니다.
패턴별 추천
- 로그/이벤트 파이프라인: Kafka (재생·다중 소비 필요).
- 업무/배치 작업 큐: RabbitMQ/SQS (Ack/Retry/DLQ, 라우팅 필요).
- 알림/캐시/짧은 잡: Redis Queue/Streams (지연 최소, 단순 운영).
- 기록 + 즉시 처리 분리: Kafka로 기록, Redis로 알림·캐시 등 즉시 처리.
메시지 큐를 고를 때 성능 지표부터 보기보다는, 이 메시지가 다시 처리되어야 하는지, 여러 소비자가 각각 처리해야 하는지, 유실을 어디까지 허용할 수 있는지를 먼저 정하는 게 더 중요하다고 느꼈습니다.
그 기준으로 보면 Kafka, RabbitMQ, Redis는 경쟁 관계라기보다 각자 잘 맞는 자리가 분명한 도구들입니다.
저는 이 기준을 세운 뒤로 “어떤 큐를 써야 하지?”라는 고민이 많이 줄었습니다.