--- id: messaging-nats-rabbitmq-comparison title: NATS / RabbitMQ / SQS — 큐 비교 category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [messaging, nats, rabbitmq, sqs, vibe-coding] tech_stack: { language: "TS / NATS / AMQP", applicable_to: ["Backend"] } applied_in: [] aliases: [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 ```ts 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) ```ts 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) ```ts 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) ```ts 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) ```ts await sqs.send(new SendMessageCommand({ QueueUrl: fifoUrl, // .fifo 끝 MessageBody: ..., MessageGroupId: order.userId, // 같은 group 안 ordering MessageDeduplicationId: eventId, // 5분 dedupe })); ``` ### NATS Core (fire-and-forget, 빠름) ```ts 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 적정. ## 🔗 관련 문서 - [[Messaging_Kafka_Patterns]] - [[Backend_Job_Queue_Patterns]] - [[Messaging_Exactly_Once]]