CS + 인프라/Messaging

[Messaging] MQTT 이해하기 - 2탄 : Pub/Sub 구조

공대키메라 2026. 4. 14. 23:30

이번 글에서는 지난 MQTT이해하기 - 1탄 : MQTT란 무엇인가?에 이어서 Pub/Sub에 대해 설명하는 MQTT Essentials: Part 2를 읽어서 정리할 것이다.

 

MQTT Essentials: Part 3 를 한 번에 넣고 보려 했는데 너무 길어지는 관계로... 분리하는게 맞다는 판단이다.

 

또, 글을 읽다보면 이게 MQTT에 대한 내용만이 아니라, 말 그대로 MQTT를 이해하기 위한 선행 지식을 알려주는 섹션으로 

2장에서 pub/sub에 대해 먼저 설명하고, 이를 MQTT에서 적용함으로 생기는 문제와 해결점에 대해 말해준다. 

 

오히려 MQTT: 뭐시기 뭐시기 하는 설명에 글을 읽는 사람을 헷갈리게 하는게 아닌가... 하는 생각도 들었다.


목표

1. pub/sub구조에 대해 이해한다.


1. MQTT: Publish / Subscribe (Pub/Sub) Architecture

Publisher (발행자) : 메시지를 생성하는 측

Subscriber (구독자) : 메시지를 받는 측

 

publish-subscribe는 다양한 프로토콜이나 기술을 사용하여 구현할 수 있는 더 광범위한 개념이다.

 

즉, MQTT는 pub/sub 아키텍처를 따르는 하나의 특정 메시지 프로토콜이다. 

 

2. MQTT: Pub/Sub Decoupling Feature

Pub/Sub 모델은 전통적인 Client-Server모델에게 유일한 대안을 제공한다.

 

요청-응답 접근에서 클라이언가 서버에 직접 요청해서 성능을 늦추는 병목을 만드는것과 달리 pub/sub 모델은 publisher와 subscriber의 연관관계를 끊는다. 서로는 서로가 존재하는지 모른다. 세 번째 구성인 broker가 이를 연결한다!

 

이렇게 직접적인 요청을 끊어냄으로 (IP 주소와 포트의 교환)양쪽 구성 요소의 통신이 중단없이 지속될 수 있게 하는 결합 해제(decouping)기능을 제공한다.

 

공간 결합 해제(Space decoupling) : 발행자와 구독자는 서로를 알 필요가 없다.

시간 결합 해제(Time Decoupling) : 발행자와 구독자가 동시 실행할 필요가 없다.  

동기화 결합 해체(Synchronization Decoupling) : 두 구성요소에 작업들이 발행하고 받는 동안 방해가 없다. 

 

즉, 발행자와 구독자 서로 broker의 hostname/IP만 알고 있으면 된다는 것이다. 

 

Pub/Sub의 가장 중요한 이점은 들어오는 모든 메시지를 필터링하고 구독자에게 정확하게 분배하는 능력이다. 

 

3. MQTT: Pub/Sub Message Filtering Feature

메시지 필터링는 pub/sub 구조에서 구독자(subscribers)가 오직 관심있는 메시지만 받게 하는 중요한 사항이다.

 

이를 위해 pub/sub 브로커는 몇 개의 필터링 옵션을 제공한다. subject-based 필터링, content-based 필터링 그리고 type-based filtering이다.

 

각각 해석을 해 보자면 주제기반(subject-based), 내용기반(content-based), 종류 혹은 타입기반(type-based) 필터링인데 뭔지 알아봐야겠다. 다른 곳에서는 어떻게 번역하는지 모르겠다. 그래서 영어 기반으로 단어들을 기억하고 있는게 아무래도 좋은 것 같다. 

 

3.1) Subject-Based Filtering of Pub/Sub architecture

broker가 MQTT 토픽(topic)혹은 주제(subject)에 따라 메시지를 필터링하는 가장 기본적인 필터링 옵션.

지난 글에서 토픽은 메시지가 게시되고 구독되는 문자열이라고 말했다.

 

pub/sub에서 Subject-based 필터링의 장점 (Benefits)

1. 사용이 간단하고 쉬움

2. 유연함. 계층적 토픽 구조가 가능

3. 효율적임. 특정 토픽에 관심있는 구독자들에게만 메시지를 전송.

 

pub/sub에서 Subject-based 필터링의 단점 (Drawbacks)

1. 발행자와 구독자가 토익 계층을 사전에 동의해야함.

2. 토픽 계층에 기반하면 메시징을 필터링하는데 제한이 있음

 

여기서 왜 제한이 있다는지 이해가 안돼서 Gemini에게 이를 물어보았다.

 

"메시지의 '봉투'에 적힌 주소만 보고 판단해야 하기 때문" 이라고 알려주는데,

subject를 번역하면 아하! 주제... 그런 의미의 주제라는 생각이 든다. 

 

내용물은 정확히 확인하지 못하고 겉으로만 확인을 하니 정밀한 필터링이 되지 않는 것이다. 

 

그래서 이 Subject-Based filtering은 언제 쓰여야 하는가? 

 

Pub/Sub에서 Subject-based 필터링의 사용 사례:

메시지가 주제별로 구성되어 있고 구독자가 해당 주제 중 특정 하위 집합에 관심이 있는 사용 사례에 가장 적합하다. 

이게 무슨 말인지 이해가 안될걸 알기에, 예시를 들어준다.

 

예를 들어, 스마트 홈 시스템에서 특정 방의 온도를 알려고 하면 subscriber는 "smart-home/living-room/temperature"같은 토픽을 구독하고 브로커는 이 subscriber에게 이 토픽을 맞춘 메시지를 보낸다.

 

3.2) Content-based filtering of Pub/Sub architecture

브로커는 필터 표현식(filter expression) 을 사용하여 지정된 메시지 내용을 기반으로 메시지를 필터링한다.

 

독자는 특정 필터 표현식을 구독함으로써 관심을 표시하고, 브로커는 메시지 내용을 기반으로 적절한 구독자에게 메시지를 라우팅한다.

 

보나마나 순서대로 장단점은 기존의 subject에 비해서 상세하게 가능할 거 같고 손이 많이간다일거 같은데 너무 당연하다.

 

pub/sub에서 Content-based 필터링의 장점 (Benefits)

1. 메시지 수신을 더욱 세밀하게 제어 가능
2. 토픽 계층 구조뿐 아니라 메시지 내용에 기반한 필터링 가능
3. 복잡한 필터 표현식을 지원하는 유연한 기능을 제공

 

pub/sub에서 Content-based 필터링의 단점 (Drawbacks)

1. 주제 기반 필터링보다 사용 및 설정이 더 복잡할 수 있음
2. 필터링을 활성화하려면 게시자가 메시지에 추가 메타데이터를 포함해야 함
3. 필터 표현식이 많을 경우 성능 저하 발생 가능

 

Use Case of Content-based filtering in Pub/Sub:

콘텐츠 기반 필터링은 메시지가 토픽별로 정리되어 있지 않고, 구독자가 콘텐츠에 따라 특정 메시지 하위 집합에만 관심이 있는 경우에 가장 적합하다.

예를 들어, 물류 애플리케이션에서 구독자는 특정 운송장 번호를 가진 패키지에 대한 메시지만 수신하고 싶어할 수 있다. 이 경우 구독자는 "운송장 번호 = '123456'"과 같은 필터 표현식을 구독하고, 브로커는 이 표현식과 일치하는 메시지만 구독자에게 전송한다.

 

늘 이렇게... trade-off가 있으니 상황에 맞게 사용해야 함을 인지하자.

 

3.3) Type-based filtering of Pub/Sub architecture

유형 기반(type-based) 필터링에서, 브로커는 type이나 class에 따라 메시지를 필터링한다.

 

이 경우는 메시지가 객체로 표현되는 객체지향 언어와 작업할 때 유용하다. 

 

구독자는 특정 타입의 메시지 혹은 크랠스를 구독해서 관심을 나타내고 프로커는 그 메시지 타입에 기반해서 적절한 구독자에게 메시지를 보낸다.(route)

 

pub/sub에서 Type-based 필터링의 장점 (Benefits)

1. 토픽과 내용에 상관없이 메시지 타입 기반으로 필터링 가능

2. 객체지향 언어와 작업시 사용이 간단함

3. 높은 유연성과 확장성을 제공

 

pub/sub에서 Type-based 필터링의 단점 (Drawbacks)

메시지 타입으로 필터링시 제한이 있음

미리 메시지 타입 계층의 메시지 사용에 발행자와 구동자의 동의가 필요

 

여기서 메시지 타입으로 필터링시 제한이 있다는게 이해가 안돼서 Gemini에게 물어보았고 요약하면 다음과 같다.

 

결론적으로 타입 기반 필터링의 제한은 **"브로커가 이벤트의 비즈니스적 의미(페이로드)를 이해하지 못하고, 오직 식별자(타입)로만 맹목적인 라우팅을 수행하기 때문에 발생하는 구조적 한계"**라고 이해하시면 됩니다

 

3.4) Use Case of Type-based filtering in Pub/Sub:

필터링 옵션을 통해 어떤 메시지를 어떤 구독자에게 보낼지 유연하고 세밀하게 결정할 수 있다.

사용 사례에 따라 이러한 필터링 옵션 중 하나 이상을 사용하여 구독자가 관심 있는 메시지만 수신하도록 할 수 있다.

 

하지만 발행/구독 모델이 모든 사용 사례에 적합한 것은 아니며, 발행자와 구독자 모두 주제 기반 필터링에 사용할 토픽을 알고 있어야 한다는 점, 그리고 구독자 중 누구도 특정 메시지를 읽지 않는 경우를 처리해야 한다는 점 등 고려해야 할 과제가 있습니다. 발행되는 데이터의 구조를 사전에 파악하는 것도 중요하다.

 

4. MQTT Pub/Sub’s Scalability Feature

확장성은 pub/sub 구조를 사용하는 중요한 장점 중 하나다. 전통적인 client-sever모델은 특히 많은 수의 client를 처리할 때 확장성에 제한을 줄 수 있다. 하지만, pub/sub 모델을 사용하면 broker가 이벤트 주도(event-driven)방식으로 메시지를 처리할 수 있는데, 높은 병렬처리 작업을 가능하게 한다. 

 

또한 메시지 캐싱과 똑똑한 메시지 라우팅이 pub/sub구조에서 확장성을 개선하는데 기여한다. 

 

5. What Are the Key Benefits of MQTT Pub/Sub Architecture in IoT and IIoT?

발행/구독(pub/sub) 모델은 여러 가지 이점을 제공하여 다양한 애플리케이션에서 널리 사용되고 있다.

 

다음은 발행/구독 아키텍처 사용의 주요 이점이다.

 

확장성 향상(Imroved scalability): 발행/구독(pub/sub) 아키텍처는 확장성이 뛰어나 클라이언트와 메시지가 많은 애플리케이션에 적합. 브로커는 모든 메시지의 중앙 허브 역할을 하므로 성능 저하 없이 많은 클라이언트를 처리할 수 있다.

 

내결함성 향상(Increaed Fault Tolerance): 발행/구독 아키텍처의 분리된 구조는 내결함성 향상. 기존 클라이언트-서버 모델에서는 서버에 장애가 발생하면 연결된 모든 클라이언트의 연결이 끊어진다. 하지만 발행/구독 방식에서는 브로커가 클라이언트가 다시 연결될 때까지 메시지를 저장하므로 메시지 손실이 발생하지 않는다.

 

유연성(Flexibility): 발행/구독 아키텍처는 유연성이 뛰어나 저대역폭, 고지연 네트워크부터 고속, 저지연 네트워크까지 다양한 환경에서 사용할 수 있. 발행/구독 아키텍처 기반의 MQTT 프로토콜은 다양한 서비스 품질(QoS) 수준을 지원하므로 애플리케이션에 적합한 QoS 수준을 선택할 수 있다.

 

6. Common Challenges in Pub/Sub Architecture and How to Overcome Them While Using MQTT

pub/sub구조가 확상성과 유연성 그리고 구성간의 디커플링같은 여러 이점을 제공하지만, 성공적인 구현을 위한 몇가지 도전(challenge)이 있다. 정리하면 다음과 같다.

 

 

  • 메시지 전달 (Delivery): 구독자가 없어 발생하는 메시지 유실 위험을 QoS 레벨을 통한 전달 보장 메커니즘으로 해결
  • 메시지 필터링 (Filtering): 불필요한 메시지 수신으로 인한 낭비를 토픽(Topic)을 활용한 주제 기반 라우팅으로 제한
  • 보안 (Security): 무단 접근 및 데이터 탈취 취약점을 사용자 인증, 접근 제어(ACL), 암호화를 강제하여 방어
  • 확장성 (Scalability): 트래픽 증가 시 발생하는 브로커 병목 현상을 다중 브로커, 클러스터링, 로드 밸런싱 인프라 구성으로 극복
  • 메시지 순서 (Ordering): 비동기 네트워크 특성상 순서가 꼬이는 문제를 QoS 레벨과 선택적인 동기식(Synchronous) API를 병행하여 제어
  • 실시간성 제약 (Real-time): 브로커 경유로 인해 추가되는 네트워크 지연(Latency) 한계는 초저지연 필수 환경일 경우 Request/Response 구조로 대체하여 우회

 

너무 장황해서 이를 축약했다. 자세한 내용은 해당 사이트의 글을 읽으면 좋다.

 

다만 메시지 순서와 실시간성 제약에 대해 잘 이해가 안돼서 이에 대해 무엇인지 질문햇고 궁금하면 다음을 열어 보길 바란다.

 

더보기

키메라:

메시지 순서 (Ordering): 비동기 네트워크 특성상 순서가 꼬이는 문제를 QoS 레벨과 선택적인 동기식(Synchronous) API를 병행하여 제어

실시간성 제약 (Real-time): 브로커 경유로 인해 추가되는 네트워크 지연(Latency) 한계는 초저지연 필수 환경일 경우 Request/Response 구조로 대체하여 우회

이게 무슨 말이야? 꼬임을 방지하는 기능도 잇어?

그리고 실시간성 제약은 뭐야? 이걸 request./response구조로 대체해서 우회한다는게 무슨말인지 이해가 안돼

 

Gemini:

1. 메시지 순서 (Ordering): "순서가 꼬인다"는 것과 방지 기능
왜 순서가 꼬일까요? (비동기의 함정) A가 B에게 "1번 메시지"를 보내고, 0.1초 뒤에 "2번 메시지"를 보냈다고 가정해 보겠습니다. 동기식(Synchronous)이라면 1번이 도착한 걸 확인하고 2번을 보내겠지만, 비동기(Asynchronous) 환경에서는 그냥 1번 쏘고 바로 2번을 쏩니다.

이때 네트워크 라우팅 경로가 다르거나, 1번 메시지가 일시적인 네트워크 병목에 걸리면 구독자 측에서는 2번 메시지를 1번보다 먼저 받게 되는 현상이 발생합니다. (예: '결제 완료' 이벤트보다 '배송 시작' 이벤트가 먼저 도착)

순서 꼬임을 방지하는 원리 (해결책) MQTT 같은 프로토콜이나 메시지 큐 시스템은 이를 방지하기 위한 구조를 가지고 있습니다.

QoS (Quality of Service) 레벨 제어:
MQTT에서 QoS 1이나 2를 설정하면, 내부적으로 각 메시지에 '패킷 식별자(ID)'를 부여합니다. 브로커는 클라이언트로부터 "N번 메시지 잘 받았다(ACK)"는 신호를 받아야만 통신이 완료된 것으로 봅니다.

이 과정에서 프로토콜 스펙에 따라 클라이언트와 브로커 간의 전송 순서를 강제할 수 있습니다.

 

동기식(Synchronous) API 병행:

본래 Pub/Sub은 던지고 잊어버리는(Fire-and-forget) 논블로킹(Non-blocking) 방식입니다.

하지만 절대 순서가 꼬이면 안 되는 핵심 비즈니스 로직(예: 계좌 잔액 차감)에서는 강제로 '동기식 API'를 씁니다.

즉, 1번 메시지를 발행한 후 브로커로부터 "정상 수신됨" 응답이 올 때까지 애플리케이션 스레드를 대기(Blocking) 시켰다가 2번을 보내는 것입니다. 성능(처리량)은 떨어지지만 완벽한 순서를 보장하는 트레이드오프(Trade-off) 전략입니다.

💡 클라우드 인프라 관점:
AWS 백엔드 환경에서는 일반적인 SNS나 SQS를 쓰면 순서 보장이 안 됩니다. 그래서 순서가 생명인 도메인에서는 철저하게 SQS FIFO(First-In-First-Out) 큐를 사용하거나, Amazon Kinesis나 Kafka처럼 파티션 키를 기준으로 순서를 꽉 잡아주는 스트리밍 아키텍처를 설계해야 합니다.

2. 실시간성 제약 (Real-time): Request/Response로 우회한다는 의미
왜 실시간성에 제약이 생길까요? (구조적 한계) 시스템의 성능을 극한으로 끌어올릴 때 '네트워크 홉(Hop, 거쳐 가는 단계)'의 개수는 생명입니다.

일반 API (Request/Response): 클라이언트 ➡️ 서버 (1 Hop)
Pub/Sub 모델: 클라이언트(발행) ➡️ 브로커(Kafka, RabbitMQ, MQTT 등) ➡️ 서버(구독) (2 Hops)

Pub/Sub은 브로커라는 중간 상인을 거쳐야 합니다. 브로커가 메시지를 받아서, 저장하고, 누구한테 줄지 필터링(라우팅)하고, 다시 밀어냅니다. 이 구조적 특성 때문에 아무리 시스템을 최적화해도 수 밀리초(ms) 수준의 네트워크 지연(Latency) 이 무조건 추가됩니다.

Request/Response 구조로 대체하여 우회한다는 뜻 만약 만들고 계신 시스템이 '초 단위'가 아니라 '밀리초 단위'의 즉각적인 반응이 필요한 빡빡한 실시간 시스템(예: 고주파 주식 거래 서버, 실시간 멀티플레이어 게임의 캐릭터 이동 처리)이라면 어떻게 해야 할까요?

Pub/Sub이 주는 장점(시스템 간 결합도를 낮추고 확장이 편해짐)을 과감히 포기해야 합니다. 대신, 중간 브로커를 걷어내고 서비스가 서비스에게 직접 1:1로 찔러버리는(Point-to-Point) 전통적인 Request/Response 아키텍처(예: REST API, gRPC 호출)로 되돌아가는 것을 의미합니다.

💡 구조적 요약: "느슨한 결합과 확장성(Pub/Sub)" vs "극한의 짧은 응답 속도(Request/Response)". 실시간성이 너무나도 중요한 특정 구간에서는 억지로 Pub/Sub을 고집하지 말고, 브로커를 빼고 직접 통신하는 방식으로 아키텍처를 우회(변경)하라는 뜻입니다.

 

키메라: 

그러면 굳이 request/response구조로 우회해야 하는 경우에는 pub/sub을 쓰는게 잘못된게 아니야?

 

아키텍처 설계에서 아주 핵심적인 의문을 품으셨습니다. 결론부터 말씀드리면, Pub/Sub을 도입한 것이 잘못된 것이 아니라 하나의 거대한 시스템 안에서도 비즈니스 목적에 따라 통신 방식을 섞어 쓰는(하이브리드) 것이 현대 백엔드 아키텍처의 정석이기 때문입니다.

모든 시스템에는 '은탄환(Silver Bullet)'이 존재하지 않습니다. 서비스 전체를 100% Request/Response로만 구성하면 시스템 간 결합도가 너무 높아져서 트래픽 스파이크 시 연쇄 장애(Cascading Failure)가 발생하고, 반대로 100% Pub/Sub으로만 구성하면 방금 우려하신 것처럼 실시간 트랜잭션 처리가 불가능해집니다.

이를 구조적으로 이해하기 위해 숙박 관리 시스템(PMS)의 객실 예약 프로세스를 예로 들어 두 아키텍처가 어떻게 공존하는지 설명해 드리겠습니다.

1. Request/Response가 반드시 필요한 구간 (Core Domain)
고객이 앱에서 특정 날짜의 객실을 예약하고 결제를 요청하는 순간입니다. 
이때는 잔여 객실 수(블록 차트)를 차감하고 결제 모듈을 통해 승인을 받아야 합니다. 만약 이 과정을 Pub/Sub 브로커를 태워 비동기로 처리한다면, 브로커 지연 시간 동안 다른 고객이 동일한 객실을 예약해버리는 '오버부킹(초과 예약)' 문제가 발생할 수 있습니다. 

또한 사용자는 화면에서 "예약 완료"라는 즉각적인 피드백을 기다리고 있습니다. 따라서 이 구간은 트래픽이 몰리더라도 DB 락(Lock)을 걸고 REST API나 gRPC를 통한 강한 결합의 Request/Response 동기 통신으로 즉각적인 응답을 보장해야 합니다.

 

2. Pub/Sub이 빛을 발하는 구간 (Sub Domain)
하지만 객실 예약이 확정되고 DB에 정상적으로 커밋된 이후의 파생 작업들은 어떨까요?
* 고객에게 카카오톡 알림톡 전송
* 요금 관리(Fee Management) 및 정산 시스템으로 매출 데이터 전송
* 마케팅 통계 서버로 예약 데이터 동기화

이 작업들은 예약 확정 화면을 띄워주는 데 1밀리초도 방해를 주어서는 안 됩니다. 카카오톡 발송 서버가 일시적으로 다운되었다고 해서 고객의 객실 예약 자체가 실패 처리(Rollback)되면 안 되기 때문입니다. 

따라서 예약 서비스는 예약 완료 직후 "객실 예약됨(RoomBookedEvent)"이라는 메시지만 메시지 브로커(Kafka, RabbitMQ, MQTT 등)에 던져두고(Publish) 자신의 할 일을 끝냅니다.

 

그러면 알림, 정산, 통계 서비스들이 각자 알아서 해당 메시지를 구독(Subscribe)하여 본인들의 속도에 맞춰 비동기적으로 처리합니다.

AWS 인프라 관점에서의 아키텍처 구성

실제 고가용성 클라우드 환경에서는 이 두 가지를 명확히 분리하여 인프라를 라우팅합니다.

* 동기식 실시간 트래픽 (프론트엔드 ↔ 백엔드 핵심 서비스):
 AWS API Gateway나 ALB(Application Load Balancer)를 거쳐 대상 컨테이너(Spring Boot)로 직접 트래픽을 꽂아 넣습니다. 지연 시간을 최소화합니다.

 

* 비동기식 파생 트래픽 (백엔드 서비스 ↔ 백엔드 서비스): 핵심 서비스가 이벤트를 발생시키면, AWS EventBridge나 SNS를 통해 주제별로 라우팅하고, SQS 큐에 쌓아두어 다른 마이크로서비스들이 안전하게 꺼내 가도록 설계합니다.

결론적으로, "실시간성이 필요한 핵심 트랜잭션 구간에 Pub/Sub을 억지로 끼워 넣는 것"은 잘못된 아키텍처 설계가 맞습니다. 

 

하지만 도메인 주도 설계(DDD) 관점에서 볼 때, 데이터의 강한 일관성과 즉각적인 응답이 필요한 '핵심 도메인'은 Request/Response로 타이트하게 묶고, 최종적인 일관성(Eventual Consistency)만 보장되어도 충분한 '파생 도메인'은 Pub/Sub으로 느슨하게 풀어주는 것이 대규모 트래픽을 감당하는 올바른 구조입니다.

7. MQTT Vs. Message Queues

해당 글에서 많은 사람들이 Message Queue와 MQTT에 대해 헷갈려하는것 같다. 

 

그래서 MQTT와 Message Queue의 특징에 대해 정리를 해줬다.

 

  • 이름의 오해: MQTT는 IBM의 MQ 시리즈에서 유래했을 뿐, 구조적으로 '메시지 큐' 원리를 사용하는 프로토콜이 아닙니다.
  • 메시지 보관 방식: 메시지 큐는 소비자가 가져갈 때까지 메시지를 저장하지만, MQTT는 구독자가 없으면 메시지를 즉시 폐기합니다.
  • 수신 대상의 수: 메시지 큐는 하나의 소비자만 메시지를 처리(부하 분산)하는 반면, MQTT는 해당 토픽을 구독한 모든 클라이언트가 메시지를 받습니다.
  • 생성 방식의 유연성: 큐는 사전에 명시적으로 이름을 지정해 생성해야 하지만, MQTT 토픽은 발행/구독 시점에 즉시 생성되는 유연성을 가집니다.

백엔드 개발자 입장에서 이 차이를 실무에 대입해 보면 훨씬 명확해집니다.

  • 메시지 큐(예: AWS SQS, RabbitMQ): 작업(Job) 처리용입니다. "이 주문 처리해!"라고 던지면 누군가 하나가 가져가서 처리할 때까지 안전하게 보관되는 게 중요할 때 씁니다.
  • MQTT (예: AWS IoT Core): 상태 업데이트나 알림용입니다. "지금 온도 25도야!"라고 뿌리면, 그 순간 듣고 있는 모든 장치나 대시보드가 동시에 정보를 받아야 할 때 씁니다.

다음은 또 필자가 글을 읽으면서 느낀점을 Gemini 에게 질문한 내용이다.

 

pub/sub구조가 MQTT만 있는게 아닐텐데 하는 생각이 들어서 질문을 했는데 각각 정리를 잘 해줬다. 궁금하면 열어보시길!

 

더보기

필자:

pub/sub이 잇지만 이를 구현하는 메시징 툴에 따라서 성격이 다른거지?

 

Gemini:

1. MQTT (IoT와 모바일의 '초경량 통신망')

  • 성격: 열악한 환경에서도 끈질기게 살아남는 초경량 무전기.
  • 구현 특징: 통신을 위한 헤더(껍데기)가 2Byte에 불과할 정도로 가벼우며, 대역폭이 좁거나 연결이 자꾸 끊기는 불안정한 네트워크 환경(모바일, IoT 기기)에 극단적으로 최적화되어 있습니다.
  • 장점: 기기의 배터리 소모와 네트워크 부하를 최소화하면서도, QoS(0, 1, 2) 레벨을 통해 "빠르게 대충 보낼지, 느리더라도 절대 유실 없이 꼼꼼하게 보낼지" 전송 보장 수준을 입맛대로 조절할 수 있습니다.
  • 용도: 스마트홈 기기 원격 제어, 커넥티드 카(차량) 통신, 모바일 푸시 알림, 공장 자동화 센서 데이터 수집 등 통신의 주체가 백엔드 서버가 아닌 '단말기(Client)'일 때 압도적인 1타 툴입니다.

2. Apache Kafka (대용량 데이터의 '기록 보관소')

  • 성격: 무식할 정도로 튼튼하고 거대한 컨베이어 벨트.
  • 구현 특징: 메시지를 메모리가 아닌 **디스크(파일)에 순서대로 차곡차곡 기록(Append-only Log)**합니다.
  • 장점: 데이터를 브로커가 굳건히 보관하므로, 구독자 서버가 잠시 죽어있거나 에러가 나더라도 나중에 **과거 데이터부터 다시 재생(Replay)**할 수 있습니다. 파티션 키를 활용해 메시지 순서를 엄격하게 제어하는 데 특화되어 있습니다.
  • 용도: 결제 트랜잭션 로그, 대용량 클릭 스트림 분석, MSA 환경에서의 핵심 데이터 동기화 등 절대 유실되면 안 되고 대용량 스트리밍 처리가 필요한 곳.

3. RabbitMQ (정교한 '우체국')

  • 성격: 아주 똑똑하고 복잡한 규칙을 가진 우편집중국.
  • 구현 특징: 브로커 내부에 Exchange(라우터)라는 똑똑한 구성 요소가 있어, "이 조건일 때는 A 큐로, 저 조건일 때는 B 큐로 보내라" 같은 **정교한 라우팅(필터링)**을 브로커 단에서 다 처리해 줍니다.
  • 장점: 라우팅 구조가 매우 유연합니다. 단, 메시지를 구독자가 정상적으로 가져가서 처리를 완료(ACK)하면 브로커는 해당 메시지를 큐에서 즉시 삭제해 버립니다.
  • 용도: 복잡한 비즈니스 로직에 따른 분기 처리, 전통적인 비동기 작업 큐 (예: 이메일/알림톡 발송, 비디오/이미지 인코딩 워커).

4. Redis Pub/Sub (극강의 실시간 '확성기')

  • 성격: 동네 이장님의 방송 마이크. 압도적으로 빠르지만, 뒤끝이 없습니다.
  • 구현 특징: 오직 **인메모리(RAM)**에서만 동작하며, 브로커가 메시지를 저장(Persistence)하지 않는 Fire-and-Forget(던지고 잊어버림) 구조입니다.
  • 장점: 네트워크 지연이 거의 없고 시스템 리소스를 매우 적게 먹습니다.
  • 단점: 브로드캐스팅하는 그 순간 구독자가 연결(Subscribe)되어 있지 않으면 그 메시지는 영원히 증발합니다. (메시지 유실 보장 안 됨)
  • 용도: 웹소켓 기반의 실시간 대시보드 업데이트, 서버 인스턴스 간의 가벼운 캐시 무효화(Cache Invalidation) 동기화.

5. AWS SNS + SQS (클라우드 네이티브의 정석)

  • 성격: 인프라 관리가 전혀 필요 없는 완전 관리형 택배 시스템.
  • 구현 특징: Pub/Sub 브로드캐스팅 역할을 하는 **SNS(Push 방식)**와, 메시지를 유실 없이 담아두는 버퍼 역할의 **SQS(Pull 방식)**를 묶어서 구성하는 것이 AWS 아키텍처의 국룰입니다.
  • 장점: 직접 서버를 띄우고 클러스터링을 튜닝할 필요가 없습니다. 트래픽이 폭주하면 AWS가 알아서 무한대로 큐를 늘려 감당합니다.
  • 단점: 클라우드 인프라에 종속(Lock-in)되며, 직접 구축한 Kafka나 Redis에 비해서는 네트워크 홉(Hop)이 길어져 미세한 처리 지연(Latency)이 발생할 수 있습니다.

글을 읽어보니... MQTT에 대한 지식만이 아니라 pub/sub 구조에 대한 일반적인 지식을 설명하고 있고 

이에 더해서 MQTT를 간간히 설명에 끼워넣고 있다. 

 

결국 pub/sub구조란 데이터를 생산하는 측(Publisher)과 소비하는 측(Subscriber)이 서로의 존재나 IP/포트 같은 물리적 위치를 전혀 알 필요 없이, 중간에 위치한 '브로커(Broker)'를 통해 비동기적으로 메시지를 주고받도록 설계된 '느슨한 결합(Decoupling) 기반의 메시징 아키텍처'이다!

 

공식 문서들에서 이상하게 이게 뭔지를 정리를 안해주고 어떤 특징을 가지고 있는지만 설명해서... 이를 정리해서 추가한다.

 

출처

https://www.hivemq.com/blog/mqtt-essentials-part2-publish-subscribe/