관련 나의 블로그 글 | |
분산 메세지 큐 1편 - 읽은 책 | https://jm-baek.tistory.com/325 |
분산 메세지 큐 2편 - 읽은 책 | https://jm-baek.tistory.com/330 |
✅ [Messaging] RabbitMQ 개념편 | https://jm-baek.tistory.com/363 |
[Messaging] RabbitMQ 도입 구상편 | https://jm-baek.tistory.com/358 |
[Messaging] RabbitMQ 도입편 |
https://jm-baek.tistory.com/392 |
혼자 고민하고 정리해서 서툴고 틀린 방향이 있을 수 있습니다.
좋은 충고와 질문은 어제든 감사드립니다.
Why Messagig System?
🙋 통신 방법으로 여러 가지가 있는데 왜 메세지 큐 기반의 통신을 사용하려고 할까?
아래는 내가 사용하려고 하는 이유
→ 유실되는 메세지 보존과 느스한 결합을 이유로 사용을 하려고 한다.
- 메시지 보존 (Durability & Reliability)
- RabbitMQ는 소비자가 메시지를 즉시 수신하지 못하더라도 메시지를 큐에 보관하여 나중에 소비자가 준비되면 처리할 수 있도록 보장함.
- 네트워크 장애, 서버 장애 등으로 인해 일시적으로 소비자가 다운되더라도 메시지 유실 없이 복구 가능.
- persistent 속성을 설정하면 메시지가 브로커가 재시작되더라도 유지됨.
- 송수신 상태 확인 (Message Acknowledgment & Delivery Guarantees)
- 메시지가 정상적으로 전송되었는지 확인하는 기능이 필요함.
- RabbitMQ는 Publisher Confirms를 통해 메시지가 브로커에 정상적으로 도착했는지 확인 가능.
- 소비자는 Acknowledgment(ACK) 를 통해 메시지를 정상적으로 처리했는지 RabbitMQ에 알릴 수 있음.
아래는 ChatGPT가 알려준 이유 중 일부분
- 비동기 처리 및 성능 향상
- 클라이언트 요청을 즉시 응답하고 백그라운드에서 작업을 수행할 수 있음.
- 무거운 작업(예: 데이터 처리, 보안 검사, 로그 기록 등)을 분산하여 수행 가능.
- 소비자가 여러 개일 경우 부하 분산(Load Balancing) 효과를 얻을 수 있음.
- 서비스 간 느슨한 결합(Loose Coupling)
- 직접적인 서비스 호출보다 메시지를 큐에 넣고 비동기적으로 처리하는 방식이 서비스 간 결합도를 낮춤.
- 마이크로서비스 아키텍처에서 중요한 요소로, 서비스 간 독립성을 유지하면서도 안정적인 통신을 가능하게 함.
- 확장성(Scalability) 및 부하 분산
- 메시지 큐를 사용하면 여러 개의 소비자가 병렬로 메시지를 처리할 수 있어 성능을 높일 수 있음.
- 필요에 따라 소비자를 동적으로 늘리거나 줄이는 방식으로 시스템 확장 가능.
RabbitMQ vs Kafaka
🙋 어떤 메세지 큐를 사용하는게 좋을까?
→ 정답은 없지만 개발하는 서비스에 맞게 정해서 사용하면 될 것 같다!!
RabbitMQ를 선택해야 하는 경우
- 요청-응답 기반의 메시징이 필요한 경우 (예: API Gateway → Backend)
- 빠른 메시지 전달과 즉시 소비가 필요한 경우 (예: 실시간 알림, 비동기 작업 처리)
- 트랜잭션이 중요한 경우 (예: 주문 처리, 결제 시스템)
- 경량 메시징이 필요한 경우 (예: 작은 메시지를 주고받는 서비스 간 통신)
Kafka를 선택해야 하는 경우
- 대량의 데이터를 스트리밍하고 처리해야 하는 경우 (예: 로그 분석, IoT 데이터 처리)
- 이벤트 소싱(Event Sourcing)이 필요한 경우 (예: 금융 거래, 주문 시스템)
- 순서 보장이 중요한 경우 (예: 로그 수집, 데이터 파이프라인)
- 수평 확장을 고려해야 하는 경우 (예: 분산 데이터 처리)
🐰 RabbitMQ
한 문장으로 RabbitMQ란?
AMQP 프로토콜을 기반으로 하는 오픈소스 메시지 브로커로, 시스템 간 비동기 메시지 통신을 지원하여 애플리케이션 간 결합도를 낮추고 안정적인 데이터 전달을 가능하게 합니다.
What is AMQP 0-9-1?
AMQP 0-9-1(Advanced Message Queuing Protocol)은 메시지 지향 미들웨어(Message-Oriented Middleware, MOM)를 위한 오픈 스탠다드 프로토콜로, 메시지를 안정적으로 송수신하는 데 필요한 기능을 제공하는 프로토콜입니다.
메시지 지향 미들웨어(MOM)는 애플리케이션 간의 통신을 메시지를 통해 비동기적으로 처리할 수 있도록 도와주는 소프트웨어 계층입니다.
RabbitMQ는 AMQP 0-9-1을 기본 프로토콜로 사용하며, 메시지 브로커와 클라이언트 간의 통신 방식을 정의하는 데 사용됩니다.
AMQP 0-9-1은 메시지 큐 시스템에서 메시지의 신뢰성(Reliability), 보안(Security), 트랜잭션(Transaction)을 지원하는 표준입니다.
AMQP 0-9-1 Model in Brief
RabbitMQ의 메시징 모델은 Producer, Exchange, Queue, Consumer로 구성됩니다.
- Producer(P): 메시지를 생성하여 Exchange로 전달
- Exchange(X): 메시지를 적절한 큐로 라우팅
- Queue(Q_n): 메시지를 저장하고 대기 중인 Consumer에게 전달
- Consumer(C_n): 큐에서 메시지를 가져와 처리
상세 흐름은 아래와 같이 RabbitMQ에서 가이드를 제공하고 있습니다.
1) Exchange
Exchange는 AMQP 0-9-1에서 메시지가 전송되는 대상입니다.
어떤 큐로 메시지가 전달될지는 익스체인지 유형(Exchange Type) 과 바인딩(Binding) 규칙에 따라 결정됩니다.
※ Exchange 타입에 대한 디테일한 설명은 RabbitMQ 공식 사이트를 확인해주세요.
(내용이 길어져서 넘어가도록 하겠습니다.)
유형 | 설명 |
Direct Exchange | Routing Key가 일치하는 Queue로 메시지 전달 |
Fanout Exchange | 모든 바인딩된 Queue로 메시지 브로드캐스트 |
Topic Exchange | Routing Key 패턴(와일드카드 포함)에 따라 메시지 전달 |
Headers Exchange | 메시지 헤더 속성을 기반으로 큐로 전달 |
익스체인지는 유형(Exchange Type) 외에도 여러 가지 속성을 가지고 있으며, 주요 속성은 다음과 같습니다.
- 이름(Name)
- 익스체인지를 식별하는 이름
- 지속성(Durability)
- 지속적인 익스체인지(Durable Exchange): 브로커가 재시작되어도 유지됨
- 일시적인 익스체인지(Transient Exchange): 브로커가 재시작되면 사라지며, 다시 선언해야 함
- 자동 삭제(Auto-delete)
- 해당 익스체인지에 바인딩된 마지막 큐가 해제되면 익스체인지가 자동으로 삭제됨
- 추가 인자(Arguments)
- 선택적 속성으로, 플러그인 및 브로커별 기능(예: 메시지 TTL, 사용자 정의 라우팅 등) 에 사용됨
2) Queue
모델에서 큐(Queue)는 다른 메시지 및 작업 큐잉 시스템의 큐와 매우 유사합니다. 큐는 애플리케이션이 소비하는 메시지를 저장하며, 익스체인지(Exchange)와 일부 속성을 공유하지만 추가적인 속성도 가지고 있습니다.
큐의 속성은 다음과 같습니다
- 이름(Name)
- 지속성(Durable): 브로커가 재시작되어도 큐가 유지됨
- 독점성(Exclusive): 하나의 연결만 사용할 수 있으며, 해당 연결이 닫히면 큐가 삭제됨
- 자동 삭제(Auto-delete): 최소한 한 명의 소비자가 사용한 후, 마지막 소비자가 구독을 해제하면 큐가 삭제됨
- 추가 인자(Arguments) (선택 사항): 메시지 TTL, 큐 길이 제한 등 플러그인 및 브로커별 기능에 사용됨
큐를 사용하기 전에 반드시 선언해야 합니다. 큐를 선언하면 존재하지 않는 경우 생성되며, 이미 존재하는 경우에는 선언된 속성과 기존 속성이 동일할 경우 아무런 영향도 미치지 않습니다. 그러나 기존 큐의 속성이 선언된 속성과 다를 경우, 채널 수준 예외 코드 406 (PRECONDITION_FAILED) 가 발생합니다.
3) Binding
바인딩은 익스체인지(Exchange)가 메시지를 큐(Queue)로 라우팅할 때 사용하는 규칙입니다.
익스체인지 E가 큐 Q로 메시지를 전달하도록 하려면, Q는 E에 바인딩(Binding)되어야 합니다.
일부 익스체인지 유형에서는 바인딩 시 라우팅 키(Routing Key) 를 설정할 수 있습니다.
라우팅 키는 익스체인지에서 특정 메시지를 선택하여 바인딩된 큐로 전달하는 필터 역할을 합니다.
라우팅 실패 시 동작
- 메시지가 어떤 큐에도 라우팅되지 못하면 (예: 익스체인지에 바인딩된 큐가 없음)
- 드롭(Drop)될 수도 있고
- 게시자(Publisher)에게 반환(Return)될 수도 있음
- 이 동작은 메시지 속성(Message Attribute)에 따라 결정됨
4) Consumer
큐(Queue)에 저장된 메시지는 애플리케이션이 소비(Consume)해야 의미가 있습니다.
AMQP 0-9-1 모델에서는 메시지를 소비하는 두 가지 방식이 있습니다.
- 구독(Subscribe)하여 메시지를 전달받는 방식 ("Push API")
- 권장되는 방식
- 애플리케이션이 특정 큐에서 메시지를 소비하고 싶다는 관심을 표시하면, 해당 큐의 메시지가 자동으로 전달됨
- 한 큐에 여러 개의 소비자(Consumer) 를 등록할 수도 있으며,
독점 소비자(Exclusive Consumer) 를 지정하여 다른 소비자가 접근하지 못하게 할 수도 있음
- 폴링(Polling) 방식으로 메시지를 요청하는 방식 ("Pull API")
- 비효율적이므로 대부분의 경우 피해야 함
- 애플리케이션이 큐에 직접 요청을 보내서 메시지를 가져오는 방식
메시지 전달 보장 (Message Guarantees)
AMQP 0-9-1은 메시지 전달 보장을 위해 다음과 같은 기능을 제공합니다.
🔹 At-most-once → 메시지가 한 번만 전달되지만 유실될 수 있음
🔹 At-least-once → 최소 한 번 이상 전달되며, 중복 발생 가능
🔹 Exactly-once → 중복 없이 메시지가 정확히 한 번만 전달됨 (트랜잭션 필요)
기능 | 설명 |
Persistent Messages | 메시지를 디스크에 저장하여 브로커 재시작 후에도 유지 |
Publisher Confirms | 메시지가 브로커에 정상적으로 도착했는지 확인 가능 |
Consumer Acknowledgment (ACK) | 메시지가 정상적으로 처리되었음을 확인 |
Dead Letter Exchange (DLX) | 소비되지 못한 메시지를 다른 Queue로 이동하여 재처리 가능 |
🙋 메세지 큐를 사용할 때 메세지를 전달 보장에 대해서 심히 고려를 해야한다.
1.1 At-Most-Once (최대 한 번 전달, 유실 가능)
- 메시지를 한 번만 전달하지만 유실될 가능성이 있음
- 메시지를 브로커에 저장하지 않고 전송 → 브로커 장애 시 메시지 손실
- 빠른 성능이 중요하고 일부 메시지 손실이 허용되는 경우 적합
- 예) 실시간 로그 스트리밍, IoT 센서 데이터
1.2 At-Least-Once (최소 한 번 이상 전달, 중복 가능)
- 메시지가 최소 한 번 이상 전달됨 (중복 발생 가능)
- 메시지가 유실되지 않도록 브로커는 메시지를 소비자가 정상적으로 처리(ACK)할 때까지 보관
- 중복 방지를 위해 애플리케이션에서 중복 제거 로직 필요
- 예) 결제 시스템, 주문 처리 시스템
1.3 Exactly-Once (중복 없이 정확히 한 번 전달)
- 메시지가 중복 없이 정확히 한 번 전달됨
- At-Least-Once 방식에 트랜잭션(Transaction) 처리를 추가하여 중복을 방지
- 성능 오버헤드가 크므로, 정확성이 중요한 금융 시스템에서 주로 사용
- 예) 은행 송금, 거래 시스템
참고 사이트
RabbitMQ와 Kafka - 메시지 대기열 시스템 간의 차이점 - AWS
RabbitMQ는 간단한 아키텍처로 복잡한 메시지 라우팅을 제공하는 반면, Kafka는 애플리케이션이 스트림 기록의 데이터를 처리할 수 있을 만큼 내구성이 우수한 메시지 브로커 시스템을 제공합니다.
aws.amazon.com
Message Converters :: Spring AMQP
Yet another option is the MarshallingMessageConverter. It delegates to the Spring OXM library’s implementations of the Marshaller and Unmarshaller strategy interfaces. You can read more about that library here. In terms of configuration, it is most commo
docs.spring.io
Getting Started | Messaging with RabbitMQ
To run the code without Spring Boot Docker Compose support, you need a version of RabbitMQ running locally to connect to. To do this, you can use Docker Compose, but you must first make two changes to the compose.yaml file. First, modify the ports entry in
spring.io
AMQP 0-9-1 Model Explained | RabbitMQ
<!--
www.rabbitmq.com
라운드 로빈 방식 이해
라운드 로빈 방식에서는 각 메시지가 한 번에 한 소비자에게만 할당됩니다. 예를 들어, 큐에 메시지가 A, B, C 순서로 들어가고, 두 소비자가 큐를 구독하고 있다면, RabbitMQ는 메시지 A를 소비자 1에게, 메시지 B를 소비자 2에게, 메시지 C를 다시 소비자 1에게 전달합니다. 이렇게 각 소비자가 순차적으로 메시지를 받게 되며, 동일한 메시지를 모든 소비자가 받지는 않습니다.
모든 소비자가 동일한 메시지를 받게 하려면?
- 별도의 큐로 메시지 복제
각각의 소비자가 동일한 메시지를 받게 하려면, 각 소비자마다 개별 큐를 만들어 메시지를 복제하거나 팬아웃(Fanout) 방식의 Exchange를 사용하여 여러 큐에 동일한 메시지를 브로드캐스트할 수 있습니다. - 팬아웃(Fanout) Exchange 사용
팬아웃 Exchange는 메시지를 수신하는 모든 큐에 메시지를 전송할 수 있는 방식입니다. 따라서 여러 소비자가 동일한 메시지를 받아야 하는 경우 팬아웃 Exchange를 사용하고 각 소비자에 대해 별도의 큐를 바인딩하는 방법이 일반적입니다.
- A producer is a user application that sends messages.
- A queue is a buffer that stores messages.
- A consumer is a user application that receives messages.
3) consumer
Message Convert
1) SimpleMessageConverter
2) SerializerMessageConverter
3) Jackson2JsonMessageConverter
4) MarshallingMessageConverter
5) Jackson2XmlMessageConverter
6) ContentTypeDelegatingMessageConverter
'프레임워크 > Kafka & RabbitMQ' 카테고리의 다른 글
[Messaging] RabbitMQ 도입편 (0) | 2025.03.18 |
---|---|
[Messaging] RabbitMQ 도입 구상편 (0) | 2025.03.18 |