티스토리 뷰
메시지 큐(MQ) 개념부터 Kafka와 RabbitMQ 아키텍처 및 내부 원리 완벽 정리
1. 분산 아키텍처에서 메시지 지향 미들웨어(MOM)의 필요성
동기식 HTTP REST API 기반의 마이크로서비스 아키텍처(MSA)에서는 서비스 간의 강한 결합도(Tight Coupling)로 인해 하나의 서비스가 장애를 일으키면 연쇄적으로 전체 시스템이 마비되는 장애 전파 현상이 발생합니다. 메시지 지향 미들웨어(Message-Oriented Middleware, MOM)는 비동기 프로토콜을 사용하여 데이터 송신자와 수신자를 완전히 분리(Decoupling)함으로써 시스템의 확장성과 결합도를 최적화합니다.
데이터를 생성하는 생산자(Producer)는 수신자의 상태와 상관없이 메시지 큐(Message Queue)에 데이터를 던진 후 자신의 비즈니스 로직을 즉시 마칩니다. 데이터를 소비하는 소비자(Consumer)는 자신의 처리 역량에 맞춰 큐에서 메시지를 가져와 처리합니다. 이러한 구조는 대규모 트래픽 쇄도 시 완충 장치(Buffer) 역할을 수행하여 백엔드 시스템 전체의 가용성을 유지하는 기반이 됩니다.
2. 메시지 브로커(Message Broker)와 이벤트 브로커(Event Broker)의 차이
대다수 아키텍처 문서에서 혼용되지만, 하부 저장소 매커니즘과 메시지 소비 방식에 따라 메시지 브로커와 이벤트 브로커는 완전히 다르게 동작합니다. 글로벌 CSS의 table-layout 유실에 대비하여 고정 가로폭 스타일을 적용한 상세 비교 구조입니다.
| 비교 항목 | 메시지 브로커 (RabbitMQ, ActiveMQ) | 이벤트 브로커 (Apache Kafka, AWS Kinesis) |
|---|---|---|
| 메시지 보존성 | 소비자가 메시지를 수신하여 처리 완료(Ack)하면 큐에서 즉시 삭제됩니다. | 소비자가 데이터를 읽어가도 삭제되지 않고, 정해진 보존 기간 동안 디스크에 유지됩니다. |
| 데이터 흐름 방식 | 브로커가 소비자의 상태를 관리하며 메시지를 밀어주는 Push 방식 위주입니다. | 소비자가 자신이 읽을 위치(Offset)를 관리하며 직접 당겨오는 Pull 방식을 씁니다. |
| 재사용 가능 여부 | 한 번 소비된 메시지는 소멸하므로 과거 데이터 재처리가 불가능합니다. | 오프셋 조정을 통해 과거에 처리했던 이벤트를 다시 처음부터 재생(Replay)할 수 있습니다. |
3. RabbitMQ의 AMQP 모델 작동 원리와 라우팅 코드 예제
RabbitMQ는 표준화된 메시지 인터페이스 규격인 **AMQP 0-9-1(Advanced Message Queuing Protocol)**을 충실하게 구현했습니다. 생산자가 큐로 메시지를 직접 던지지 않고, 중간 매개체인 **익스체인지(Exchange)**로 발송하면 라우팅 키(Routing Key) 규칙에 기반하여 물리적인 큐(Queue)들로 메시지를 복사 배분합니다.
가장 유연하게 사용되는 Topic Exchange 매커니즘 기반의 구조 설정 자바 선언 예제입니다.
@Configuration
public class RabbitConfig {
private static final String EXCHANGE_NAME = "app.topic.exchange";
private static final String QUEUE_NAME = "order.service.queue";
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(EXCHANGE_NAME);
}
@Bean
public Queue orderQueue() {
return new Queue(QUEUE_NAME, true); // Durable 설정으로 브로커 재부팅 시에도 큐 보존
}
@Bean
public Binding binding(Queue orderQueue, TopicExchange topicExchange) {
// 와일드카드(*)를 이용한 패턴 매칭 바인딩 선언
return BindingBuilder.bind(orderQueue).to(topicExchange).with("order.*.domestic");
}
}
위와 같이 바인딩이 정의되면, 생산자가 order.book.domestic 이라는 라우팅 키로 발송한 데이터는 유효하게 해당 큐에 쌓이지만, order.book.foreign 이나 payment.card.domestic 키를 가진 데이터는 필터링되어 유입되지 않습니다. 이 메커니즘을 통해 정교한 라우팅 토폴로지를 유연하게 구축할 수 있습니다.
4. Apache Kafka의 분산 분할(Partition) 구조와 확장 메커니즘
Apache Kafka는 고성능 이벤트 스트리밍 처리를 목표로 설계되었기 때문에 일반적인 인메모리 큐 아키텍처를 버리고, 파일 시스템에 순차적으로 기록하는 **Append-only Commit Log** 형태의 분산 저장 방식을 취합니다. 카프카 논리적 데이터 단위를 **토픽(Topic)**이라 부르며, 이 토픽은 물리적으로 여러 서버에 쪼개져 저장되는 단위인 **파티션(Partition)**들의 집합으로 구성됩니다.
하나의 토픽을 다수의 파티션으로 개방하면 여러 소비자가 각 파티션에 1:1 매핑되어 데이터를 동시에 병렬로 풀링할 수 있어 대량의 쓰기/읽기 처리가 가능해집니다. 아래 코드는 하이레벨 Java Kafka 클라이언트 엔진을 이용한 데이터 발행(Publish) 로직입니다.
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka-broker-1:9092,kafka-broker-2:9092");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
// 파티션 분산 정합성을 보장하기 위한 Shard Key 설정 (예: user_id_777)
String messageKey = "user_id_777";
String messageValue = "{\"order_id\": 23091, \"item\": \"Laptop\"}";
ProducerRecord<String, String> record = new ProducerRecord<>("user-order-topic", messageKey, messageValue);
// 비동기 전송 및 내부 해시 분산 처리
producer.send(record, (metadata, exception) -> {
if (exception == null) {
System.out.println("이벤트 저장 파티션 위치: " + metadata.partition());
} else {
exception.printStackTrace();
}
});
동일한 messageKey를 가진 이벤트들은 무조건 카프카 내부 파티셔너(Partitioner) 알고리즘에 의해 항상 같은 파티션 번호로 할당됩니다. 카프카는 파티션 내부에서만큼은 이벤트 저장 순서를 유일하게 완벽 보장하기 때문에, 금융 주문 처리나 상태 머신 변화 추적 등 순차 정합성이 보장되어야 하는 파이프라인에서 뛰어난 방어력을 제공합니다.
📚 공식 기술 레퍼런스 (References)
- Apache Kafka Core Documentation: "Design Section 4.3 - File System Persistence & Message Efficiency" 구조 설계 공식 스펙 명세 인용
- RabbitMQ & Pivotal AMQP Spec Guide: "AMQP 0-9-1 Model Explained - Channels, Exchanges and Queues Architecture" 사양 준수
- Enterprise Integration Patterns (Gregor Hohpe): "Chapter 3 - Messaging Channels Systems" 설계 사상 적용
#메시지큐원리 #ApacheKafka구조 #RabbitMQAMQP #MOM미들웨어 #이벤트브로커차이 #TopicExchange라우팅 #카프카파티션정합성 #분산시스템디자인
'Program Development' 카테고리의 다른 글
| 웹 스트리밍(토큰) 데이터 송수신(SSE) (0) | 2026.06.17 |
|---|---|
| React DOM 최적화 (0) | 2026.06.13 |
| VSCode 설치 방법(Windows, MacOS) (0) | 2026.06.11 |
| 컴파일 vs 인터프리터 (1) | 2026.06.10 |
| 트랜잭션 격리 수준(Isolation Level) 종류와 이상 현상 (0) | 2026.06.06 |
| 프로그래밍 언어별 주석 처리 방법 총정리 (0) | 2026.06.02 |
| HTTP 상태 코드(HTTP Status Codes) (0) | 2026.05.16 |
| C# 소켓 프로그래밍 - 비동기 채팅 프로그램 만들기 (1:n 통신) (13) | 2018.08.31 |
- Total
- Today
- Yesterday
- String
- c#
- 데이터베이스
- 안드로이드
- 아두이노
- C++ 클래스
- C
- 블루투스
- 자료구조
- 알고리즘
- Android
- OpenCV
- 배열
- MySQL
- 파일처리
- 벡터
- DB연동
- 클래스
- html
- 상속
- C언어
- 문자열
- 정보처리기사
- Class
- C++
- Java
- 자바
- 리스트
- 문제풀이
- 파이썬
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
