본문 바로가기
Tech Notes

큐라고 다 같은 큐가 아니다 — Kafka · SQS · RabbitMQ · Cloudflare Queues 지형도

by miracle-tech 2026. 5. 31.
728x90
반응형
큐라고 다 같은 큐가 아니다 — Kafka · SQS · RabbitMQ · Cloudflare Queues 지형도
아키텍처 · 1인 개발자 메모

큐라고 다 같은 큐가 아니다
— Kafka · SQS · RabbitMQ · Cloudflare Queues 지형도

지난 글에서 "큐 패턴"으로 백엔드를 다시 짰다. 그런데 그 '큐'는 한 종류가 아니다. "왜 Kafka 안 썼어요?"라는 질문에서 시작한, 메시지 시스템 지형도 정리.

2026-05-31 · 약 10분 소요 · 이전 글: 큐 패턴 도입기

들어가며: "왜 Kafka 안 썼어요?"

지난 글에서 3분 걸리는 AI 호출을 백그라운드로 빼면서 큐 패턴을 도입한 이야기를 썼어요. Cloudflare Queues를 썼다고 했더니 돌아온 질문이 이거였습니다. "큐면 Kafka 아니에요? 왜 Kafka 안 썼어요?"

이 질문에는 흔한 오해가 하나 숨어 있어요. "큐 = Kafka"라는 등식. 사실 Kafka는 엄밀히 말하면 큐가 아니고, 시중의 메시지 시스템들은 생긴 건 비슷해 보여도 동작 모델이 꽤 다릅니다. 그래서 이번 글에서는 대표적인 네 가지 — Kafka, AWS SQS, RabbitMQ, Cloudflare Queues — 를 한 지도 위에 놓고 비교해보려 해요.

이 글의 결론을 먼저: 큐 시스템 선택은 "뭐가 제일 좋냐"가 아니라 "내 문제가 작업 분배이벤트 재생이냐"에서 갈립니다. 그리고 1인 개발자에겐 운영 부담이 성능보다 중요한 변수예요.

가장 중요한 한 갈래: 큐 vs 로그

다른 건 다 잊어도 이것만 기억하면 절반은 끝나요. 메시지 시스템은 크게 두 갈래입니다.

메시지 큐 (Queue)

메시지가 줄 서 있고, 소비자가 하나 꺼내서(ack) 처리하면 그 메시지는 사라집니다. 여러 소비자가 붙으면 일을 나눠 가져가요. 핵심 용도는 작업 분배(work distribution). "이 일 누가 하나 처리해줘"에 어울립니다. SQS · RabbitMQ · Cloudflare Queues가 여기 속해요.

이벤트 로그 (Log)

메시지가 append-only 로그에 차곡차곡 쌓이고, 읽어도 사라지지 않습니다. 각 소비자(그룹)는 자기 오프셋(offset)을 들고 "내가 어디까지 읽었나"를 기억하며 읽어요. 그래서 같은 데이터를 여러 소비자가 각자 독립적으로 읽을 수 있고, 과거 시점부터 재생(replay)도 됩니다. Kafka가 대표주자예요.

큐(꺼내면 사라짐) vs 로그(남고 오프셋으로 재생)
메시지 큐 — 꺼내면 사라진다 M3 M2 M1 (소비됨·삭제) Consumer A Consumer B 일을 나눠 가져감 이벤트 로그 — 남고, 각자 오프셋으로 읽는다 0 1 2 3 4 append-only · 읽어도 삭제 안 됨 그룹 A offset=2 그룹 B offset=4 같은 로그를 여러 그룹이 각자 읽고, 되감아 재생도 가능
한 줄 요약: "일을 한 번만 처리하면 끝"이면 . "같은 사건을 여러 곳이 듣고, 나중에 다시 돌려봐야 함"이면 로그.

4개 시스템, 한 장 요약

Apache Kafka

분산 이벤트 로그

append-only 로그를 파티션으로 쪼개 초고처리량을 낸다. 오프셋 기반이라 재생·이벤트소싱·스트림 처리에 강하다. 대신 클러스터(브로커·코디네이션)를 운영해야 한다.

강점: 처리량 · 재생 · 다중 소비

AWS SQS

완전 관리형 메시지 큐

AWS가 다 굴려주는 큐. 서버가 없다. Standard(순서 미보장·초고처리량)와 FIFO(순서·정확히 한 번) 두 종류. AWS 생태계 안이면 가장 손이 덜 간다.

강점: 무운영 · AWS 통합

RabbitMQ

메시지 브로커 (AMQP)

익스체인지·라우팅 키로 복잡한 분배(fanout·topic·우선순위)를 정교하게 짠다. 라우팅 유연성이 최고. 대신 인스턴스를 직접(또는 매니지드로) 운영한다.

강점: 라우팅 유연성

Cloudflare Queues

서버리스 메시지 큐

Workers에 바인딩 한 줄로 붙는 서버리스 큐. 토큰·엔드포인트 없이 env.JOBS.send()로 끝. 처리량 상한은 위 셋보다 낮지만 작은 트래픽엔 압도적으로 간편하다.

강점: 제로 운영 · Workers 통합

비교 표

같은 축으로 나란히 놓으면 성격 차이가 분명해져요. (숫자는 대략적 체감 — 버전·설정·플랜에 따라 달라집니다.)

Kafka SQS RabbitMQ CF Queues
모델 이벤트 로그 메시지 큐 메시지 브로커 메시지 큐
운영 방식 self-host / 매니지드(MSK·Confluent) 완전 관리형 self-host / 매니지드(CloudAMQP) 완전 관리형(서버리스)
처리량 매우 높음 (수십만~수백만/s) 높음 (사실상 무제한, Standard) 중~높음 (수만~십만/s) 중 (작은~중간 트래픽 대상)
순서 보장 파티션 내 보장 Standard 미보장 / FIFO 보장 큐 내 대체로 보장 대체로 보장(배치 단위)
재시도 / DLQ 소비자가 오프셋 직접 관리 visibility timeout + DLQ ack/nack + DLX retry() + DLQ 내장
메시지 보존 기간/크기 기준 유지 (재생 O) 소비 시 삭제 (최대 14일) 소비 시 삭제 소비 시 삭제
지연 낮음 (ms) 낮음~중 매우 낮음 낮음~중
비용 성격 인프라 + 운영비 큼 요청 수 기준 과금 인스턴스 비용 operation 기준, 저렴
러닝 커브 가파름 완만 중간 완만
표를 한 문장으로: Kafka는 로그라서 다른 셋과 근본 카테고리가 다르고, 나머지 셋의 차이는 주로 "누가 운영하느냐""라우팅을 얼마나 정교하게 하느냐"에서 갈립니다.

언제 뭘 쓰나

질문 몇 개만 따라가면 대부분 답이 나와요.

선택 흐름
같은 사건을 여러 곳이 각자 듣거나, 과거부터 재생해야 하나? Kafka 이벤트 로그 · 재생 · 스트림 · 초고처리량 아니오 (작업 분배면 큐) 토픽 fanout·우선순위 같은 복잡한 라우팅이 필요한가? RabbitMQ 정교한 라우팅 · 온프레미스 가능 아니오 (단순 작업 큐) 주력 스택이 어디에 있나? (운영 부담은 최소가 목표) AWS SQS AWS 생태계 · 완전 관리형 큐 Cloudflare Queues Workers 위 · 서버리스 · 소규모에 제로 운영 AWS 중심 Cloudflare 중심 / 1인·소규모
  • 여러 시스템이 같은 이벤트를 각자 소비 / 재생 / 이벤트 소싱 / 초고처리량 스트림 → Kafka
  • 복잡한 라우팅(fanout·topic·우선순위) 또는 온프레미스 → RabbitMQ
  • 단순 작업 큐 + AWS 생태계 → SQS
  • 단순 작업 큐 + Cloudflare/서버리스 + 작은 트래픽 → Cloudflare Queues

그래서 나는 왜 Cloudflare Queues였나

지난 글의 요구사항을 이 지도 위에 올려보면 답이 거의 자동으로 나와요.

  • 작업은 "한 번 처리하면 끝". AI 호출 결과를 만들고 저장하면 그 잡은 종료돼요. 같은 이벤트를 여러 소비자가 듣거나, 과거를 재생할 일이 없습니다. → 로그(Kafka)가 필요 없음.
  • 라우팅은 단순. 잡 하나가 들어오면 컨슈머 하나가 처리. fanout·우선순위·토픽 라우팅이 없어요. → RabbitMQ의 강점이 안 쓰임.
  • 나는 1인 개발자. 브로커 클러스터를 굴리거나 인스턴스를 운영할 여력이 없어요. 운영 부담 = 그대로 내 시간.
  • 이미 Cloudflare에 다 모아뒀음. D1·R2·Workers가 한 곳에 있고, 큐도 env.JOBS.send() 한 줄로 붙어요. 외부 토큰·엔드포인트·인증이 없습니다.
  • 트래픽이 작음. 출시 검증 단계라 처리량 상한이 병목이 될 일이 없어요. Kafka의 초고처리량은 지금 나에게 오버킬.
결론: "내 문제는 작업 분배다 + 운영은 0이어야 한다 + 스택이 Cloudflare다" — 이 세 조건이 겹치는 칸이 정확히 Cloudflare Queues였어요. Kafka를 안 쓴 게 아니라, 내 문제가 로그를 요구하지 않았던 겁니다.

물론 조건이 바뀌면 답도 바뀌어요. 나중에 "분석 파이프라인이 같은 이벤트를 따로 소비"하거나 "사용자 행동 로그를 재생해 다시 처리"할 일이 생기면, 그때는 로그 계열을 진지하게 볼 거예요. 도구는 문제를 따라가는 거니까.


마무리: 큐는 도구지 목표가 아니다

"왜 Kafka 안 썼어요?"에 대한 가장 정직한 답은 "내 문제가 Kafka를 필요로 하지 않아서"예요. 메시지 시스템 선택에서 제일 흔한 실수는, 제일 강력해 보이는 걸 먼저 고르고 거기에 문제를 끼워 맞추는 거더라고요.

순서는 반대여야 합니다. 먼저 묻기 — 내 문제가 작업 분배인가 이벤트 재생인가? 그다음 — 운영을 누가 감당하나? 이 두 질문이면 네 후보 중 어디로 갈지 거의 정해져요. 화려한 스펙표는 그다음입니다.

다음 글 예고: placeholder PNG 자리에 실제 AI 호출을 끼워넣고, 결과를 푸시 알림으로 사용자에게 다시 부르는 단계 — "대기를 없애는" 마지막 조각을 다룰 예정이에요.
728x90