Kafka와 RabbitMQ 선택 기준
근본 차이: 추가 전용 로그 vs 브로커 큐
- Kafka: 메시지를 로그에 append 한다. 소비해도 사라지지 않고 보존 기간까지 남는다. 어디까지 읽었는지는 컨슈머의 오프셋이 관리한다
- RabbitMQ: ack를 받으면 큐에서 제거한다. 브로커가 익스체인지 규칙으로 라우팅과 분배를 담당한다
비교
| 항목 | Kafka | RabbitMQ |
|---|
| 재생(replay) | 오프셋을 되감아 재소비 | 기본적으로 불가 |
| 라우팅 | 토픽과 파티션 단위, 필터는 컨슈머 몫 | direct / topic / fanout 익스체인지 |
| 순서 | 파티션 단위 보장 | 큐 단위, 경쟁 컨슈머면 깨짐 |
| 처리량 | 순차 디스크 쓰기로 매우 높음 | 상대적으로 낮고 지연은 짧음 |
| 지연 메시지 | 별도 구현 필요 | TTL, 플러그인으로 지원 |
선택 기준
- 하나의 이벤트를 여러 소비자가 각자의 속도로 다시 읽어야 한다 → Kafka
- 한 건을 한 워커가 처리하는 작업 큐이고 라우팅이 복잡하다 → RabbitMQ
- 운영 인력이 적고 트래픽이 작다 → 관리형 큐(SQS 등)에서 시작한다
다시 읽을 수 있느냐가 갈림길이다
가장 큰 차이는 처리한 뒤에 그 메시지가 남는가입니다.
| 남나 | 무엇이 가능해지나 |
|---|
| 남는다 | 버그를 고치고 지난 것을 다시 처리한다 |
| 남는다 | 새 소비자가 처음부터 다시 읽는다 |
| 안 남는다 | 다시 처리할 방법이 없다. 대신 관리할 것이 적다 |
첫째가 실무에서 큰 값입니다. 계산이 틀렸다는 것을 하루 뒤에 알았을 때, 되돌려 다시 돌릴
수 있느냐가 대응 방식을 완전히 바꿉니다.
무엇이 더 번거로운가
남기는 쪽이 공짜는 아닙니다.
파티션 수를 미리 정해야 하고 줄이기 어렵다
어디까지 읽었는지를 소비자가 관리해야 한다
저장 기간만큼 디스크가 든다
반대쪽은 메시지마다 다른 경로로 보내고 우선순위를 주는 것이 쉽습니다. 그래서 일감을
여러 일꾼에게 나눠 주는 용도라면 그쪽이 단순하고, 흘러가는 사건을 여러 소비자가 각자
읽어야 한다면 남기는 쪽이 맞습니다.
실무 포인트
- Kafka로 작업 큐를 억지로 구현하면 개별 메시지 재시도와 지연 처리가 번거로워진다
- 함께 쓰는 조합도 흔하다. 이벤트 스트림은 Kafka, 작업 분배는 RabbitMQ
- 선택 근거를 처리량 숫자보다 재생 필요 여부와 라우팅 복잡도로 설명하면 설득력이 있다
Q.Kafka와 RabbitMQ 중 무엇을 고르시겠어요? 어떤 기준으로 판단하나요?
메시지를 흐름으로 다루는지, 작업으로 다루는지로 갈립니다.
| 항목 | Kafka | RabbitMQ |
|---|
| 모델 | 로그. 읽어도 남는다 | 큐. 소비하면 사라진다 |
| 재처리 | 오프셋을 되돌려 다시 읽는다 | 기본적으로 불가 |
| 여러 구독자 | 각자 자기 위치를 가진다 | 교환기 설정으로 복제 |
| 순서 | 파티션 안에서 보장 | 큐 안에서 보장. 조건이 있다 |
| 라우팅 | 단순. 토픽과 파티션 | 유연. 조건별 분배 |
| 처리량 | 매우 높다 | 상대적으로 낮다 |
| 지연 | 묶음 처리로 약간의 지연 | 낮다 |
| 보관 | 기간이나 용량 기준으로 남긴다 | 소비되면 없어진다 |
선택 기준입니다.
| 상황 | 선택 |
|---|
| 이벤트를 여러 팀이 각자 구독 | Kafka |
| 로그와 지표 수집, 스트림 처리 | Kafka |
| 나중에 다시 읽어야 한다 | Kafka |
| 작업 분배와 우선순위 | RabbitMQ |
| 조건별 복잡한 라우팅 | RabbitMQ |
| 지연 큐, 개별 메시지 재시도 | RabbitMQ |
흔한 실수: 처리량만 보고 고르는 것. 대부분의 서비스는 어느 쪽으로도 충분합니다. 재처리가 필요한지, 라우팅이 복잡한지가 실제 판단을 가르는 지점입니다.
Q.Kafka에서 이미 소비한 메시지를 다시 읽을 수 있는 이유는?
Kafka 는 메시지를 지우지 않고 로그에 남겨 두고, 소비자는 자기가 어디까지 읽었는지를 기록만 합니다.
| 항목 | 내용 |
|---|
| 저장 | 파티션마다 순서대로 추가되는 로그 파일 |
| 소비 | 읽어도 삭제되지 않는다 |
| 위치 | 소비자 그룹별로 오프셋을 따로 관리한다 |
| 삭제 | 보관 기간이나 용량 기준으로만 |
그래서 오프셋을 되돌리면 그 지점부터 다시 읽습니다. 일반 큐는 소비 시점에 메시지를 제거하므로 이것이 불가능합니다.
| 이 성질이 쓰이는 곳 | 내용 |
|---|
| 버그 수정 후 재처리 | 잘못 처리한 구간을 다시 읽는다 |
| 새 소비자 추가 | 과거 데이터부터 처음부터 읽어 상태를 만든다 |
| 여러 팀이 각자 구독 | 서로의 진행에 영향을 주지 않는다 |
| 장애 복구 | 소비자를 잃어도 남은 로그에서 이어간다 |
두 번째가 특히 유용합니다. 새 집계 서비스를 만들 때 과거 이벤트를 처음부터 읽어 현재 상태를 구성할 수 있습니다.
흔한 실수: 재처리를 무제한으로 여기는 것. 보관 기간이 지나면 삭제되므로 그 이전 데이터는 없습니다. 재처리를 전제한다면 보관 기간을 그만큼 길게 잡아야 합니다.
Q.작업 큐 용도로 Kafka를 쓰면 어떤 점이 불편한가요?
Kafka 는 순서 있는 로그라서, 개별 작업을 따로 다루는 일이 어렵습니다.
| 불편 | 내용 |
|---|
| 개별 재시도 | 한 메시지만 나중에 다시 처리하기 어렵다. 오프셋은 순차적이다 |
| 앞이 막힌다 | 처리 못 하는 메시지가 그 파티션의 진행을 멈춘다 |
| 우선순위 | 급한 작업을 먼저 처리하는 기능이 없다 |
| 지연 실행 | 5분 뒤 처리 같은 기능이 없다 |
| 소비자 수 상한 | 파티션 수를 넘겨 늘릴 수 없다 |
| 작업 단위 확인 | 특정 작업이 처리됐는지 조회하기 어렵다 |
두 번째가 가장 아픕니다. 작업 큐에서는 하나가 실패해도 다른 작업은 계속 처리돼야 하는데, Kafka 는 순서를 지키므로 그 메시지를 넘기지 않으면 뒤가 멈춥니다.
우회 방법은 있습니다.
| 우회 | 내용 |
|---|
| 실패는 즉시 별도 토픽으로 | 앞을 막지 않게 넘긴다 |
| 지연 토픽 | 대기 시간별 토픽을 따로 둔다 |
| 우선순위별 토픽 | 급한 것과 아닌 것을 나눈다 |
우회가 많아지면 그것이 신호입니다. 작업 큐가 필요한 것이면 작업 큐를 쓰는 편이 낫습니다.
흔한 실수: 이미 Kafka 가 있으니 작업 큐도 그것으로 처리하는 것. 운영 대상을 하나로 유지하는 이점이 있지만, 위 우회들을 직접 구현하는 비용이 그것을 넘는 경우가 많습니다.
Q.RabbitMQ에서 메시지 순서가 깨지는 상황은 언제인가요?
큐 하나에 소비자가 하나이고 재시도가 없을 때만 순서가 지켜집니다. 그 조건이 깨지는 경우들입니다.
| 상황 | 왜 깨지나 |
|---|
| 소비자가 여러 대 | 각자 다른 속도로 처리해 완료 순서가 뒤바뀐다 |
| 미리 받는 개수가 1보다 크다 | 한 소비자가 여러 건을 동시에 처리한다 |
| 재입력 | 실패한 메시지를 큐에 되돌리면 뒤로 간다 |
| 우선순위 큐 | 나중에 온 높은 우선순위가 먼저 나간다 |
| 여러 큐로 라우팅 | 같은 대상의 메시지가 다른 큐로 갈 수 있다 |
| 지연 큐 | 대기 시간이 다르면 순서가 바뀐다 |
첫 번째와 두 번째가 흔합니다. 처리량을 올리려고 소비자를 늘리거나 미리 받는 개수를 키우는 것이 순서를 포기하는 선택임을 놓치기 쉽습니다.
세 번째도 실무에서 자주 봅니다. 실패한 메시지를 되돌려 넣으면 그 뒤에 온 메시지들이 이미 처리된 상태입니다.
순서를 지켜야 한다면 이렇게 합니다.
| 방법 | 내용 |
|---|
| 대상별 큐 분리 | 순서 단위마다 다른 큐. 큐가 많아진다 |
| 소비자 하나 + 미리 받기 1 | 확실하지만 처리량을 포기한다 |
| 순번을 담는다 | 소비자가 순서를 검사해 어긋나면 보류한다 |
흔한 실수: 큐가 FIFO 라서 순서가 보장된다고 답하는 것. 큐에 들어가는 순서는 지켜지지만 처리 완료 순서는 소비자 구성에 달려 있습니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
메시징 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.