🌊 들어가기에 앞서
지난 글 에서 Kafka가 왜 등장했는지, Producer/Consumer/Broker/Topic/Partition 개념이 뭔지 정리했습니다. 그런데 막상 우리 서비스에 메시지 큐를 넣자는 이야기가 나오면, Kafka보다 먼저 나오는 이름이 있습니다. 바로 RabbitMQ입니다.
둘 다 Producer와 Consumer를 분리해준다는 점에서는 비슷해 보이지만, 실제로는 태생부터 다른 도구입니다. 이번 글에서는 AWS가 정리한 비교 기준1을 따라가면서, RabbitMQ와 Kafka가 근본적으로 뭐가 다른지, 그래서 언제 뭘 골라야 하는지 정리해보겠습니다.
📮 우체국과 도서관으로 비유해보기
가장 쉬운 비유는 우체국과 도서관입니다. 제가 비유한건 아니고, AWS 공식 문서에서 이렇게 비유하긴 했습니다.
- RabbitMQ (우체국): Producer가 메시지를 보내면, Broker가 능동적으로 정해진 Consumer를 찾아 전달합니다. 편지를 보내면 우체국이 알아서 배달해주는 것과 같습니다.
- Kafka (도서관): Producer가 메시지를 보내면, Broker는 그냥 진열대(Topic)에 순서대로 꽂아둘 뿐입니다. Consumer가 필요할 때 직접 와서 원하는 위치부터 읽어갑니다.
IMPORTANT이 비유가 곧 두 시스템의 차이인 Push와 Pull입니다. RabbitMQ는 Broker가 Consumer에게 메시지를 Push하고, Kafka는 Consumer가 Broker에서 메시지를 Pull합니다. 이 차이 하나에서 거의 모든 차이가 파생됩니다.
🧱 구성 요소가 다르다
같은 메시지 큐라는 카테고리로 묶이지만, 내부 구조는 이름부터 다릅니다.
| 구분 | RabbitMQ | Kafka |
|---|---|---|
| 전달 방식 | Push | Pull |
| 핵심 구성요소 | Exchange → Binding → Queue | Broker → Topic → Partition |
| 라우팅 | Exchange가 규칙에 따라 메시지를 여러 Queue로 분배 | Producer가 지정한 Topic의 Partition에 그대로 적재 |
RabbitMQ는 Producer가 메시지를 Exchange에 보내면, Exchange가 미리 정의된 Binding 규칙에 따라 하나 또는 여러 개의 Queue로 메시지를 복사/분배합니다. 조건에 따라 메시지를 이 팀에는 보내고 저 팀에는 안 보내는 식의 세밀한 라우팅이 필요하다면 이 구조가 훨씬 유리합니다.
반면 Kafka는 지난 글에서 다뤘듯 Producer가 Topic에 메시지를 넣으면 끝입니다. 누가 얼마나 많이 구독하든, 라우팅 로직을 브로커가 대신 고민해주지 않습니다. 분배는 Consumer Group의 몫입니다.
TIP
- Exchange: 메시지를 수신하고 처리할 대상을 결정하는 요소를 의미한다.
- Queue: 메시지를 저장하는 공간이며 이벤트 생성자와 이벤트 소비자 간의 데이터를 주고받는 공간을 의미한다.
🔢 메시지 순서, 둘 다 보장은 하는데
- RabbitMQ: 기본적으로 FIFO를 보장합니다. 게다가 우선순위 큐를 지원해서, 급한 메시지를 새치기시켜서 먼저 처리할 수도 있습니다.
- Kafka: 하나의 Partition 안에서만 순서가 보장됩니다. Topic 전체로 보면 순서가 섞일 수 있고, 우선순위라는 개념 자체가 없습니다. Kafka에게 모든 메시지는 동등합니다.
TIP급한 알림은 먼저 처리하고 싶다처럼 메시지 간 우선순위가 실제로 의미 있는 도메인이라면, 그건 Kafka로 구현하기 어려운 요구사항입니다. 이럴 땐 RabbitMQ를 사용하는 쪽이 훨씬 자연스럽습니다.
⚡ 처리량과 확장성
RabbitMQ는 메시지를 큐에 적재/전달하는 과정에서 임의 메모리 접근에 가까운 방식을 쓰는 반면, Kafka는 디스크에 로그를 이어붙이는 순차 디스크 I/O를 씁니다. 순차 쓰기는 임의 메모리 접근보다 훨씬 빠르기 때문에, 이 차이가 그대로 처리량 격차로 이어지게됩니다.
| 항목 | RabbitMQ | Kafka |
|---|---|---|
| 처리량 | 초당 수천~수만 건 수준 | 초당 수백만 건까지 가능 |
| 확장 방식 | 브로커 클러스터 + 큐 미러링 | Partition을 늘려 여러 Broker에 부하 분산 |
| 큐가 밀렸을 때 | 처리 속도가 눈에 띄게 느려질 수 있음 | Partition 단위라 상대적으로 영향이 적음 |
일반적으로 RabbitMQ도 웬만한 서비스 트래픽은 충분히 감당합니다. 하지만 여기서의 차이는 초당 수만 건을 넘어 수백만 건까지 감당해야 하는가라는, 꽤 극단적인 트래픽 구간에서 어떤 도구를 사용할지 나눠지게 됩니다.
🗄️ 메시지가 사라지는 시점
여기가 지난 글에서 다룬 Replay와 직결되는 부분입니다.
- RabbitMQ: Consumer가 메시지를 읽고 ACK를 보내는 순간, 브로커는 그 메시지를 큐에서 바로 삭제합니다. 한 번 읽고 지나간 메시지는 원칙적으로 다시 읽을 방법이 없습니다.
- Kafka: 메시지를 읽어도 삭제하지 않습니다. 설정된 보존 기간 동안 로그 파일에 그대로 남아있고, Consumer는 Offset만 되돌리면 언제든 과거 데이터를 다시 처리할 수 있습니다.
WARNINGRabbitMQ에서 읽은 메시지를 나중에 다시 처리하고 싶다는 요구가 생기면, 이건 RabbitMQ의 설계 철학과 충돌합니다. 재처리가 필요한 데이터라면 애초에 RabbitMQ가 아니라 Kafka를 골랐어야 하는 신호일 수 있습니다.
🎯 그래서, 언제 뭘 써야 할까?
전체 내용을 종합하면 이렇게 정리됩니다.
| 항목 | RabbitMQ | Kafka |
|---|---|---|
| 모델 | Push (우체국) | Pull (도서관) |
| 강점 | 정확한 전달, 복잡한 라우팅, 우선순위 | 대용량 처리, 장기 보관, 재처리 |
| 메시지 보존 | ACK 즉시 삭제 | 보존 기간 동안 유지 |
| 순서 보장 | 큐 전체 FIFO | Partition 단위만 |
| 지연 시간 | 상대적으로 짧음 | 처리량 우선, 상대적으로 길 수 있음 |
| 대표 사례 | 결제/뱅킹 거래, SMS 알림처럼 정확히 한 번, 순서대로 전달이 중요한 경우 | 로그 집계, 실시간 이벤트 분석처럼 대량의 데이터를 스트림으로, 여러 번 다시 봐야 하는 경우 |
TIP질문을 하나로 압축하면 이렇습니다. 이 메시지, 소비되고 나면 버려도 되는가, 아니면 나중에 다시 봐야 하는가? 버려도 된다면 RabbitMQ, 다시 봐야 한다면 Kafka 쪽으로 가는게 훨씬 효율적인거죠.
😮💨 마무리
RabbitMQ와 Kafka는 경쟁 관계라기보다, 서로 다른 문제를 풀 수 있는 도구에 가깝습니다. RabbitMQ는 메시지 하나하나를 정확하게, 정해진 순서로 배달하는 데 강하고, Kafka는 대량의 이벤트를 오래 쌓아두고 여러 번 다시 처리하는 데 강합니다.
실제로는 두 개를 같이 쓰는 아키텍처도 흔합니다. 서비스 간 즉각적인 명령/응답에는 RabbitMQ를, 로그나 이벤트 스트림처럼 나중에도 다시 봐야 하는 데이터에는 Kafka를 두는 식입니다. 결국 선택 기준은 우리가 다루는 메시지가 소모품인지, 아니면 자산인지에 달려 있는 것 같습니다.