Files
2nd/10_Wiki/Topic_Programming/Coding/Messaging_NATS_RabbitMQ_Comparison.md
T
Antigravity Agent 9148c358d0 docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
2026-07-05 00:33:48 +09:00

4.7 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
messaging-nats-rabbitmq-comparison NATS / RabbitMQ / SQS — 큐 비교 Coding draft B conceptual 2026-05-09 2026-05-09
messaging
nats
rabbitmq
sqs
vibe-coding
language applicable_to
TS / NATS / AMQP
Backend
NATS JetStream
RabbitMQ
AMQP
SQS
message broker

NATS / RabbitMQ / SQS

Kafka 만이 답이 아니다. NATS = 가볍고 빠름, RabbitMQ = AMQP routing, SQS = AWS managed. 처리량 / ordering / 영속성 / 운영 부담 4축으로 선택.

📖 핵심 개념

  • NATS Core: pub/sub fire-and-forget.
  • NATS JetStream: 영속, replay, exactly-once.
  • RabbitMQ: AMQP, exchange + routing key + queue.
  • SQS: AWS managed FIFO 또는 standard.

💻 코드 패턴

NATS JetStream

import { connect } from 'nats';

const nc = await connect({ servers: 'nats://nats:4222' });
const js = nc.jetstream();
const jsm = await nc.jetstreamManager();

// Stream 생성
await jsm.streams.add({ name: 'ORDERS', subjects: ['orders.*'], storage: 'file', max_age: 7 * 24 * 3600 * 1e9 });

// Publish
await js.publish('orders.created', JSON.stringify({ id, userId }));

// Consumer
const sub = await js.consumers.get('ORDERS', 'order-projector');
const iter = await sub.consume();
for await (const m of iter) {
  await handle(JSON.parse(m.string()));
  m.ack();
}

RabbitMQ (AMQP)

import amqp from 'amqplib';

const conn = await amqp.connect('amqp://rabbit:5672');
const ch = await conn.createChannel();

await ch.assertExchange('orders', 'topic', { durable: true });
await ch.assertQueue('orders.created.projector', { durable: true });
await ch.bindQueue('orders.created.projector', 'orders', 'orders.created');

// Publish
ch.publish('orders', 'orders.created', Buffer.from(JSON.stringify(order)), {
  persistent: true,
  messageId: eventId,
});

// Consume
await ch.prefetch(10);
ch.consume('orders.created.projector', async (msg) => {
  if (!msg) return;
  try {
    await handle(JSON.parse(msg.content.toString()));
    ch.ack(msg);
  } catch {
    ch.nack(msg, false, false); // DLX 로
  }
});

RabbitMQ DLX (dead-letter exchange)

await ch.assertQueue('orders.created.projector', {
  durable: true,
  arguments: {
    'x-dead-letter-exchange': 'orders.dlx',
    'x-message-ttl': 60_000,
    'x-max-retries': 5,
  },
});

AWS SQS (standard)

import { SQSClient, SendMessageCommand, ReceiveMessageCommand, DeleteMessageCommand } from '@aws-sdk/client-sqs';

const sqs = new SQSClient({});

await sqs.send(new SendMessageCommand({
  QueueUrl: queueUrl,
  MessageBody: JSON.stringify(order),
  MessageAttributes: { eventId: { DataType: 'String', StringValue: id } },
}));

// Long-poll
const r = await sqs.send(new ReceiveMessageCommand({
  QueueUrl: queueUrl,
  WaitTimeSeconds: 20,
  MaxNumberOfMessages: 10,
}));
for (const msg of r.Messages ?? []) {
  await handle(JSON.parse(msg.Body!));
  await sqs.send(new DeleteMessageCommand({ QueueUrl: queueUrl, ReceiptHandle: msg.ReceiptHandle! }));
}

SQS FIFO (ordering)

await sqs.send(new SendMessageCommand({
  QueueUrl: fifoUrl, // .fifo 끝
  MessageBody: ...,
  MessageGroupId: order.userId,        // 같은 group 안 ordering
  MessageDeduplicationId: eventId,    // 5분 dedupe
}));

NATS Core (fire-and-forget, 빠름)

nc.subscribe('telemetry.*', { callback: (err, msg) => handle(msg.data) });
nc.publish('telemetry.cpu', JSON.stringify({ host, cpu }));

영속 X — 받지 못하면 잃음. 모니터링 / IoT 같은 use case.

🤔 의사결정 기준

요구 추천
큰 처리량 + 영속 + replay Kafka
가벼운 + Quick start NATS JetStream
Routing 복잡 (topic + header) RabbitMQ
AWS only SQS (+ EventBridge / SNS)
매우 작은 (1대) Redis Streams
Realtime fire-and-forget NATS Core / Redis pub/sub
Lambda trigger SQS / EventBridge

안티패턴

  • 모든 곳 Kafka: 운영 부담 큼. 단순 큐 = SQS / RabbitMQ.
  • NATS Core 영속 가정: subscribe 안 됐으면 잃음.
  • Prefetch 무제한 (RabbitMQ): 한 consumer 가 모두 가져감.
  • Visibility timeout 짧음 (SQS): 처리 중 다시 visible → 중복.
  • Manual ack 없음: 처리 실패해도 ack — 메시지 잃음.
  • DLQ 없음: 실패 메시지 영원 재시도 또는 잃음.
  • FIFO 가정 standard SQS: ordering 보장 X.

🤖 LLM 활용 힌트

  • 상황별 다름: 영속/replay = Kafka, 가벼움 = NATS, AWS = SQS, 복잡 routing = RabbitMQ.
  • DLQ + idempotency 항상.
  • prefetch / visibility 적정.

🔗 관련 문서