📚FOS Study
홈카테고리
홈카테고리

카테고리

  • AI 페이지로 이동
    • RAG 페이지로 이동
    • agents 페이지로 이동
    • langgraph 페이지로 이동
    • BMAD Method — AI 에이전트로 애자일 개발하는 방법론
    • Claude Code의 Skill 시스템 - 개발자를 위한 AI 자동화의 새로운 차원
    • Claude Code를 11일 동안 쓴 결과 — 데이터로 본 나의 사용 패턴
    • Claude Code 멀티 에이전트 — Teams
    • 하네스 엔지니어링 실전 — 4인 에이전트 팀으로 코딩 파이프라인 구축하기
    • 하네스 엔지니어링 — 오래 실행되는 AI 에이전트를 위한 설계
    • 멀티모달 LLM (Multimodal Large Language Model)
    • AI 에이전트와 함께 MVP 만들기 — dooray-cli 사례
  • algorithm 페이지로 이동
    • live-coding 페이지로 이동
    • 분산 계산을 위한 알고리즘
  • architecture 페이지로 이동
    • [초안] 시니어 백엔드를 위한 API 설계 실전 스터디 팩 — REST · 멱등성 · 페이지네이션 · 버전 전략
    • 캐시 설계 전략 총정리
    • [초안] DDD와 도메인 모델링: 시니어 백엔드 관점의 전술/전략 패턴 실전 가이드
    • [초안] Decorator & Chain of Responsibility — 행동을 체인으로 조립하는 두 가지 방식
    • 디자인 패턴
    • [초안] 분산 아키텍처 완전 정복: Java 백엔드 시니어 인터뷰 대비 실전 가이드
    • [초안] 분산 트랜잭션과 Outbox 패턴 — 왜 2PC를 피하고 어떻게 대신할 것인가
    • 분산 트랜잭션
    • [초안] 대규모 커머스 트래픽 처리 패턴 — 1,600만 고객과 올영세일을 버티는 설계
    • [초안] MSA 서비스 간 통신: Redis Cache-Aside × Kafka 이벤트 하이브리드 설계
    • [초안] Observability 입문: 시니어 백엔드가 장애를 탐지하고 대응하는 방식
    • [초안] 시니어 백엔드를 위한 Resilience 패턴 실전 가이드 — Timeout, Retry, Circuit Breaker, Bulkhead, Backpressure
    • [초안] Strategy Pattern — 분기문을 없애는 설계, 시니어 백엔드 인터뷰 핵심 패턴
    • [초안] 시니어 백엔드를 위한 시스템 설계 입문 스터디 팩
    • [초안] 템플릿 메서드 패턴 - 백엔드 처리 골격을 강제하는 가장 오래되고 가장 위험한 패턴
    • [초안] 대규모 트래픽 중 무중단 마이그레이션 — Feature Flag + Shadow Mode 실전
  • css 페이지로 이동
    • FlexBox 페이지로 이동
  • database 페이지로 이동
    • mysql 페이지로 이동
    • opensearch 페이지로 이동
    • redis 페이지로 이동
    • 김영한의-실전-데이터베이스-설계 페이지로 이동
    • 커넥션 풀 크기는 얼마나 조정해야할까?
    • 인덱스 - DB 성능 최적화의 핵심
    • 역정규화 (Denormalization)
    • 데이터 베이스 정규화
  • devops 페이지로 이동
    • docker 페이지로 이동
    • k8s 페이지로 이동
    • k8s-in-action 페이지로 이동
    • monitoring 페이지로 이동
    • Envoy Proxy
    • Graceful Shutdown
  • go 페이지로 이동
    • Go 언어 기본 학습
  • http 페이지로 이동
    • HTTP Connection Pool
  • interview 페이지로 이동
    • 210812 페이지로 이동
    • company-analysis 페이지로 이동
    • experience-based 페이지로 이동
    • master 페이지로 이동
    • 뱅크샐러드 AI Native Server Engineer
    • CJ 올리브영 커머스플랫폼유닛 Back-End 개발 지원 자료
    • 마이리얼트립 - Platform Solutions실 회원주문개발 Product Engineer
    • NHN 서비스개발센터 AI서비스개발팀
    • nhn gameenvil console backend 직무 인터뷰 준비
    • 면접을 대비해봅시다
    • 토스증권 Server Developer (Platform) 지원 자료
    • 토스증권 Server Developer (Product) 지원 자료
    • 토스뱅크 Server Developer (Product) 지원 자료
    • Tossplace Node.js Developer
    • 토스플레이스 Node.js 백엔드 컬처핏
  • java 페이지로 이동
    • concurrency 페이지로 이동
    • jdbc 페이지로 이동
    • opentelemetry 페이지로 이동
    • spring 페이지로 이동
    • spring-batch 페이지로 이동
    • 더_자바_코드를_조작하는_다양한_방법 페이지로 이동
    • [초안] JVM 튜닝 실전: 메모리 구조부터 Virtual Threads, GC 튜닝, 프로파일링까지
    • Java의 로깅 환경
    • MDC (Mapped Diagnostic Context)
    • OpenTelemetry 란 무엇인가?
    • Java StampedLock — 읽기 폭주에도 쓰기가 밀리지 않는 락
    • Virtual Thread와 Project Loom
  • javascript 페이지로 이동
    • Data_Structures_and_Algorithms 페이지로 이동
    • Heap 페이지로 이동
    • typescript 페이지로 이동
    • AbortController
    • Async Iterator와 제너레이터
    • CommonJS와 ECMAScript Modules
    • 제너레이터(Generator)
    • Http Client
    • Node.js
    • npm vs pnpm 선택기준은 무엇인가요?
    • `setImmediate()`
  • kafka 페이지로 이동
    • Kafka 기본
    • Kafka를 사용하여 **데이터 정합성**은 어떻게 유지해야 할까?
    • [초안] Kafka 실전 설계: 파티션 전략, 컨슈머 그룹, 전달 보장, 재시도, 순서 보장 트레이드오프
    • 메시지 전송 신뢰성
  • linux 페이지로 이동
    • fsync — 리눅스 파일 동기화 시스템 콜
    • tmux — Terminal Multiplexer
  • network 페이지로 이동
    • L2(스위치)와 L3(라우터)의 역할 차이
    • L4와 VIP(Virtual IP Address)
    • IP Subnet
  • observability 페이지로 이동
    • [초안] Datadog APM 실전 투입 가이드: Java/Spring 서비스 관측성 스택 구축하기
  • rabbitmq 페이지로 이동
    • [초안] RabbitMQ Basics — 실전 백엔드 관점에서 정리하는 메시지 브로커 기본기
    • [초안] RabbitMQ vs Kafka — 백엔드 메시징 선택 기준과 실전 운영 관점
  • react 페이지로 이동
    • JSX 페이지로 이동
    • VirtualDOM 페이지로 이동
    • v16 페이지로 이동
  • resume 페이지로 이동
    • 지원 문항
  • security 페이지로 이동
    • [초안] 시니어 백엔드를 위한 보안 / 인증 스터디 팩 — Spring Security, JWT, OAuth2, OWASP Top 10
  • task 페이지로 이동
    • ai-service-team 페이지로 이동
    • nsc-slot 페이지로 이동
    • sb-dev-team 페이지로 이동
    • the-future-company 페이지로 이동
  • testing 페이지로 이동
    • [초안] 시니어 Java 백엔드를 위한 테스트 전략 완전 정리 — 피라미드부터 TestContainers, JMH, Contract까지
📚FOS Study

개발 학습 기록을 정리하는 블로그입니다.

바로가기

  • 홈
  • 카테고리

소셜

  • GitHub
  • Source Repository

© 2025 FOS Study. Built with Next.js & Tailwind CSS

목록으로 돌아가기
📁rabbitmq

[초안] RabbitMQ Basics — 실전 백엔드 관점에서 정리하는 메시지 브로커 기본기

약 9분
2026년 4월 21일
GitHub에서 보기

왜 RabbitMQ를 다시 공부하는가

실무에서 메시지 브로커를 써본 경험이 있더라도, 면접에서 "왜 Kafka가 아니라 RabbitMQ를 썼나요?", "Exchange와 Queue의 차이는 뭔가요?", "메시지 유실을 어떻게 막았나요?" 같은 질문이 들어오면 의외로 말이 막힌다. 평소에는 라이브러리가 알아서 처리해주는 부분 — Exchange 타입, Binding, Ack 모드, Prefetch, DLQ, Publisher Confirm — 이 모두 질문의 단골 소재다.

RabbitMQ는 AMQP 0-9-1 프로토콜을 기반으로 한 "범용 메시지 브로커"다. Kafka가 로그 기반 스트리밍에 최적화되어 있다면, RabbitMQ는 작업 분배(task queue), 요청/응답, 비동기 이벤트 팬아웃 같은 전통적인 엔터프라이즈 메시징 패턴에 강점이 있다. 백엔드 엔지니어가 "비동기로 돌려야 하는데 트래픽이 아주 크진 않고, 메시지 단위의 라우팅이 필요하다"는 상황에서 가장 먼저 떠올리게 되는 후보다.

이 문서는 RabbitMQ를 "개념 + 실전 예제 + 흔한 실수 + 면접 답변"의 구조로 한 번에 정리하는 것이 목표다. Kafka와의 비교, Spring AMQP 기준의 Producer/Consumer 구현, 메시지 유실 방지 설정, 그리고 면접에서 바로 꺼낼 수 있는 대답 프레이밍까지 포함한다.

핵심 개념: Exchange, Queue, Binding, Routing Key

RabbitMQ의 메시지 흐름을 이해하려면 네 가지 요소가 어떻게 맞물리는지부터 잡아야 한다.

  • Producer: 메시지를 보내는 쪽. 주의할 점은 Producer는 Queue에 직접 메시지를 넣지 않는다는 것이다. 항상 Exchange로 보낸다.
  • Exchange: 메시지를 받아서, 자신에게 바인딩된 Queue 중 어디로 보낼지 라우팅하는 "분배기".
  • Queue: 실제로 메시지가 쌓이는 FIFO 버퍼.
  • Binding: Exchange ↔ Queue 사이의 연결 규칙. Routing Key 패턴이 함께 정의된다.
  • Consumer: Queue에서 메시지를 꺼내 처리하는 쪽.

Producer → Exchange → (Binding 규칙에 따라) Queue → Consumer 의 흐름이다. 이 구조 덕에 RabbitMQ는 Kafka와 달리 "한 메시지가 여러 컨슈머에게 다르게 라우팅되는" 패턴을 자연스럽게 표현한다.

Exchange 타입 네 가지

면접 단골 주제다. 각 타입의 "언제 쓰는가"를 같이 외워두는 게 좋다.

1. Direct Exchange Routing Key가 Binding Key와 정확히 일치하는 Queue로만 메시지를 보낸다. 작업 분배(work queue)처럼 "특정 타입의 작업은 특정 워커 그룹으로"라는 요구에 맞는다. 예: order.created 키는 주문 처리 큐로, order.cancelled 키는 환불 처리 큐로.

2. Fanout Exchange Routing Key를 무시하고 자신에게 바인딩된 모든 Queue로 메시지를 복제한다. 이벤트 브로드캐스트에 쓴다. 예: 사용자 회원가입 이벤트를 "이메일 발송 서비스, 추천 시스템 초기화, 분석 파이프라인"이 각각 받아야 할 때.

3. Topic Exchange Routing Key를 . 으로 구분된 패턴으로 해석한다. *는 한 단어, #는 0개 이상의 단어를 매칭한다. 가장 유연해서 실무에서 가장 많이 쓴다. 예: order.kr.* 바인딩은 order.kr.created, order.kr.paid는 받지만 order.us.created는 받지 않는다.

4. Headers Exchange Routing Key 대신 메시지 헤더(key-value 쌍)를 기준으로 라우팅한다. 실무에서는 거의 쓰지 않고, 면접에서 "네 가지가 있다" 정도로 언급할 수 있으면 충분하다.

Queue 속성에서 꼭 알아야 할 것들

  • durable: 브로커 재시작 후에도 Queue 정의가 살아남는가. 보통 true.
  • exclusive: 선언한 커넥션에서만 쓰고, 연결이 끊기면 자동 삭제. RPC 응답 큐 같은 임시 용도.
  • auto-delete: 마지막 컨슈머가 끊기면 자동 삭제.
  • arguments: x-message-ttl, x-max-length, x-dead-letter-exchange 같은 고급 옵션.

Queue가 durable이어도 메시지가 persistent로 발행되지 않으면 재시작 시 유실된다. durable Queue + persistent Message + Publisher Confirm + Consumer Ack — 이 네 가지가 메시지 유실 방지의 기본 세트다.

Kafka와의 차이, 그리고 언제 RabbitMQ를 선택하는가

면접에서 거의 확정적으로 나오는 질문이다. 핵심은 "브로커가 어디에 상태를 두느냐"와 "메시지가 어떻게 소비되느냐"의 차이다.

관점RabbitMQKafka
모델푸시 기반(실제로는 prefetch 기반 pull) 큐로그 기반, 컨슈머가 offset으로 pull
메시지 처리 후Ack 받으면 큐에서 제거제거 안 함, 보관 기간 동안 유지
재처리같은 메시지를 재소비하려면 별도 메커니즘 필요offset만 되감으면 됨
라우팅Exchange 타입으로 복잡한 라우팅 가능Topic → Partition 단순
순서 보장단일 Queue 내에서 보장Partition 내에서 보장
처리량초당 수만~수십만초당 수십만~수백만
주용도작업 분배, RPC, 이벤트 팬아웃로그 수집, 이벤트 소싱, 스트리밍

면접 답변 프레이밍의 기본은 이렇게 잡는다.

"RabbitMQ는 큐에서 소비되면 메시지가 사라지는 전통적인 메시지 브로커고, Kafka는 소비 후에도 메시지가 로그로 남아 여러 컨슈머 그룹이 각자 offset으로 재처리할 수 있다는 점이 가장 큰 차이입니다. 그래서 작업 분배처럼 '한 번 처리되고 끝'인 워크로드에는 RabbitMQ를, 이벤트 소싱이나 여러 시스템이 같은 이벤트를 재처리해야 하는 경우에는 Kafka를 선호합니다."

실전 백엔드 활용 패턴

1. Work Queue (작업 분배)

대표적인 RabbitMQ 사용 패턴이다. API 서버가 무거운 작업(이미지 처리, 이메일 발송, PDF 생성)을 Queue에 밀어 넣고, 워커 프로세스 여러 개가 병렬로 꺼내 처리한다. Direct Exchange + 단일 Queue + N개의 Consumer 구성이 기본이다.

2. 이벤트 팬아웃

주문 생성 이벤트 하나를 "결제 서비스, 알림 서비스, 통계 서비스"가 각자 받아야 할 때. Fanout 또는 Topic Exchange로 라우팅한 뒤, 서비스별로 자기 Queue를 바인딩한다. 각 Queue는 독립적이므로 한 서비스가 느려도 다른 서비스에 영향이 없다.

3. RPC (요청/응답)

잘 쓰이진 않지만 가능하다. 요청 메시지에 reply_to(응답을 받을 임시 Queue 이름)와 correlation_id를 넣어 보내고, 서버가 해당 Queue로 응답을 보낸다. 동기 통신을 굳이 메시지 브로커로 할 이유는 많지 않아서, 실무에서는 gRPC/HTTP가 더 흔하다.

4. Delayed / Retry 패턴

RabbitMQ 자체에는 "지연 발행" 기능이 기본으로는 없다. 두 가지 방법이 있다.

  • rabbitmq-delayed-message-exchange 플러그인: 지연 시간을 헤더로 지정.
  • DLX + TTL 조합: TTL이 걸린 Queue에 메시지를 넣고, 만료되면 Dead Letter Exchange로 빠지게 해서 실제 처리 큐로 전달.

재시도 패턴도 같다. 처리 실패 → 짧은 TTL이 걸린 retry queue → TTL 만료 → 원래 큐로 되돌아와 재소비.

Bad vs Improved: 흔한 실수와 개선

실수 1. auto-ack 로 개발 시작

Bad

@RabbitListener(queues = "order.queue")
public void handle(OrderMessage msg) {
    paymentService.charge(msg);
}

기본 ack 모드가 무엇인지 모른 채 쓰는 경우. Spring AMQP는 기본이 AUTO지만, AUTO는 "예외가 나면 nack"을 의미할 뿐, 메시지가 꺼내지는 순간 바로 제거되는 것이 아니다. 하지만 만약 acknowledgeMode=NONE으로 설정되어 있으면, Consumer가 메시지를 받자마자 브로커는 지웠다고 간주하므로 처리 중 프로세스가 죽으면 메시지가 유실된다.

Improved

@Bean
public SimpleRabbitListenerContainerFactory factory(ConnectionFactory cf) {
    SimpleRabbitListenerContainerFactory f = new SimpleRabbitListenerContainerFactory();
    f.setConnectionFactory(cf);
    f.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    f.setPrefetchCount(20);
    return f;
}

@RabbitListener(queues = "order.queue", containerFactory = "factory")
public void handle(OrderMessage msg, Channel channel,
                   @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
    try {
        paymentService.charge(msg);
        channel.basicAck(tag, false);
    } catch (BusinessRetryableException e) {
        channel.basicNack(tag, false, true);  // requeue
    } catch (Exception e) {
        channel.basicNack(tag, false, false); // DLX로
    }
}

수동 ack로 바꾸고, 재처리 가능한 예외와 치명적 예외를 구분해 nack의 requeue 플래그를 다르게 준다.

실수 2. Prefetch 무제한

Bad: 설정을 건드리지 않으면 Consumer가 Queue에 있는 메시지를 무한정 가져가려 한다. 한 Consumer가 수천 건을 메모리에 안고 있다가 GC 폭주나 OOM이 난다.

Improved: prefetchCount를 1050 사이에서 시작해서 처리 시간에 맞춰 조정한다. 처리 시간이 긴 작업은 낮게(15), 짧으면 높게.

실수 3. Publisher Confirm 미설정

Bad: rabbitTemplate.convertAndSend(...)를 호출했다고 브로커에 도달했다는 보장은 없다. TCP 레이어에서 끊기면 메시지는 사라진다.

Improved: publisher-confirm-type: correlated를 켜고 ConfirmCallback에서 ack/nack을 확인한다. 실패 시 Outbox 테이블에 기록하거나 재발행한다.

spring:
  rabbitmq:
    publisher-confirm-type: correlated
    publisher-returns: true
    template:
      mandatory: true

실수 4. DLQ 없이 운영

처리 실패한 메시지를 계속 requeue 하면 poison message가 큐에 남아 같은 메시지를 무한 재시도하게 된다. 반드시 재시도 횟수를 제한하고, 한도를 넘으면 DLX로 보내 DLQ에 쌓아두고 알람을 띄운다.

로컬 실습 환경

Docker 한 줄이면 충분하다.

docker run -d --name rabbit \
  -p 5672:5672 -p 15672:15672 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=admin \
  rabbitmq:3.13-management

http://localhost:15672 로 접속하면 관리 UI가 뜬다. Exchange, Queue, Binding, 메시지 레이트를 눈으로 확인할 수 있어서 학습용으로 가장 빠른 피드백 루프가 나온다.

Spring Boot 프로젝트의 build.gradle.

implementation 'org.springframework.boot:spring-boot-starter-amqp'

application.yml.

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: admin
    publisher-confirm-type: correlated
    publisher-returns: true
    listener:
      simple:
        acknowledge-mode: manual
        prefetch: 20

실행 가능한 예제: 주문 이벤트 팬아웃 + DLQ

Exchange와 Queue 선언.

@Configuration
public class RabbitConfig {

    public static final String ORDER_EXCHANGE = "order.exchange";
    public static final String ORDER_DLX      = "order.dlx";
    public static final String EMAIL_QUEUE    = "order.email.queue";
    public static final String EMAIL_DLQ      = "order.email.dlq";

    @Bean
    TopicExchange orderExchange() {
        return ExchangeBuilder.topicExchange(ORDER_EXCHANGE).durable(true).build();
    }

    @Bean
    DirectExchange orderDlx() {
        return ExchangeBuilder.directExchange(ORDER_DLX).durable(true).build();
    }

    @Bean
    Queue emailQueue() {
        return QueueBuilder.durable(EMAIL_QUEUE)
                .withArgument("x-dead-letter-exchange", ORDER_DLX)
                .withArgument("x-dead-letter-routing-key", "email.failed")
                .build();
    }

    @Bean
    Queue emailDlq() {
        return QueueBuilder.durable(EMAIL_DLQ).build();
    }

    @Bean
    Binding emailBinding() {
        return BindingBuilder.bind(emailQueue()).to(orderExchange()).with("order.created");
    }

    @Bean
    Binding emailDlqBinding() {
        return BindingBuilder.bind(emailDlq()).to(orderDlx()).with("email.failed");
    }
}

Producer.

@Service
@RequiredArgsConstructor
public class OrderPublisher {
    private final RabbitTemplate rabbitTemplate;

    public void publishOrderCreated(OrderCreatedEvent event) {
        CorrelationData cd = new CorrelationData(event.orderId());
        rabbitTemplate.convertAndSend(
            RabbitConfig.ORDER_EXCHANGE,
            "order.created",
            event,
            message -> {
                message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                return message;
            },
            cd
        );
    }
}

Consumer (재시도 한도 포함).

@Component
public class EmailConsumer {

    @RabbitListener(queues = RabbitConfig.EMAIL_QUEUE)
    public void onMessage(OrderCreatedEvent event,
                          Channel channel,
                          @Header(AmqpHeaders.DELIVERY_TAG) long tag,
                          @Header(name = "x-death", required = false) List<Map<String,?>> xDeath) throws IOException {
        int retry = xDeath == null ? 0 : ((Long) xDeath.get(0).get("count")).intValue();
        try {
            if (retry >= 3) {
                channel.basicNack(tag, false, false); // DLQ로
                return;
            }
            emailService.sendOrderEmail(event);
            channel.basicAck(tag, false);
        } catch (Exception e) {
            channel.basicNack(tag, false, false); // DLX 경유 후 retry → DLQ
        }
    }
}

x-death 헤더는 DLX를 거쳐 재큐잉될 때 브로커가 자동으로 채워주는 재시도 이력이다. 이걸 이용해 "재시도 3회 초과면 DLQ로 고정" 같은 정책을 간단하게 쓸 수 있다.

면접 답변 프레이밍

Q. RabbitMQ와 Kafka의 차이를 설명해 달라.

가장 큰 차이는 메시지가 소비된 이후의 보관 모델입니다. RabbitMQ는 Ack가 돌아오면 메시지를 큐에서 지우는 전통적인 브로커고, Kafka는 소비 후에도 로그로 보관해 offset 기반으로 재소비할 수 있습니다. 그래서 작업 분배나 이벤트 팬아웃처럼 "한 번 처리되면 끝"인 경우 RabbitMQ, 이벤트 소싱이나 스트리밍 분석처럼 같은 이벤트를 여러 번 재처리해야 하는 경우 Kafka를 선택했습니다.

Q. RabbitMQ에서 메시지 유실을 막기 위해 어떤 설정을 켭니까?

네 가지를 세트로 봅니다. Queue durable, Message persistent, Publisher Confirm, Consumer manual ack 입니다. 여기에 더해서 처리 실패 메시지를 위한 DLX + DLQ를 구성하고, Publisher 쪽에서는 Confirm nack이 왔을 때 재발행할 수 있도록 Outbox 패턴으로 묶어두는 편입니다.

Q. Prefetch는 왜 설정하나요?

Consumer가 아직 ack하지 않은 메시지를 얼마나 미리 받아올지 제한하는 값입니다. 기본값이 무제한이라 놔두면 한 Consumer가 수천 건을 메모리에 안고 있다가 OOM이 나거나, 불균등 분배가 심해집니다. 처리 시간이 긴 작업은 낮게(15), 짧은 작업은 높게(50) 잡아 분배를 평탄하게 만듭니다.

Q. 같은 메시지가 여러 번 처리되는 문제를 어떻게 다루나요?

RabbitMQ는 기본이 at-least-once이기 때문에 중복은 언제든 발생할 수 있다고 전제합니다. 그래서 Consumer 측에서 메시지 ID를 기준으로 idempotent 하게 처리하도록 만듭니다. 예를 들어 주문 이벤트 처리 전에 processed_message(message_id) 테이블을 확인하거나, 결제 호출에 idempotency_key를 실어 보내는 식입니다.

Q. Exchange 타입 중 어떤 걸 가장 많이 썼나요?

Topic Exchange를 기본으로 썼습니다. 도메인.액션.리전 같은 라우팅 키로 설계해두면, 새로운 Consumer가 특정 패턴만 구독해서 붙기가 쉽고, 초기 설계를 크게 바꾸지 않고 확장할 수 있었습니다.

학습 체크리스트

  • Exchange 네 가지 타입을 각 한 줄 예시와 함께 설명할 수 있다.
  • Producer → Exchange → Queue → Consumer 흐름을 그림 없이 말로 설명할 수 있다.
  • durable / persistent / Publisher Confirm / manual ack 의 역할을 각각 구분해 설명할 수 있다.
  • Prefetch를 설정하는 이유와 조정 기준을 말할 수 있다.
  • DLX + DLQ 구성법과 x-death 헤더를 이용한 재시도 제한 패턴을 코드로 쓸 수 있다.
  • RabbitMQ와 Kafka를 선택하는 기준을 워크로드 관점에서 구분해 말할 수 있다.
  • at-least-once 전제 하에 idempotent 소비자를 어떻게 구현하는지 설명할 수 있다.
  • 로컬 Docker로 RabbitMQ를 띄우고, 관리 UI에서 Exchange/Queue/Binding을 직접 생성해본 경험이 있다.
  • Spring AMQP로 Producer/Consumer를 작성하고, 의도적으로 예외를 던져 DLQ에 메시지가 쌓이는 것을 확인해봤다.
  • Delayed Message 플러그인과 TTL + DLX 방식의 차이를 설명할 수 있다.
rabbitmq 카테고리의 다른 글 보기수정 제안하기

댓글

댓글을 불러오는 중...
  • 왜 RabbitMQ를 다시 공부하는가
  • 핵심 개념: Exchange, Queue, Binding, Routing Key
  • Exchange 타입 네 가지
  • Queue 속성에서 꼭 알아야 할 것들
  • Kafka와의 차이, 그리고 언제 RabbitMQ를 선택하는가
  • 실전 백엔드 활용 패턴
  • 1. Work Queue (작업 분배)
  • 2. 이벤트 팬아웃
  • 3. RPC (요청/응답)
  • 4. Delayed / Retry 패턴
  • Bad vs Improved: 흔한 실수와 개선
  • 실수 1. auto-ack 로 개발 시작
  • 실수 2. Prefetch 무제한
  • 실수 3. Publisher Confirm 미설정
  • 실수 4. DLQ 없이 운영
  • 로컬 실습 환경
  • 실행 가능한 예제: 주문 이벤트 팬아웃 + DLQ
  • 면접 답변 프레이밍
  • 학습 체크리스트