STOMP에서 사용하는 Simple Broker와 MQTT Broker는 둘 다 메시지 브로커 역할을 하지만, 사용하는 방식과 기능에서 차이가 있습니다. 이 둘을 비교하면 다음과 같습니다:
1. Simple Broker (STOMP Broker)
- 사용 방식: Simple Broker는 주로 웹 애플리케이션에서 STOMP 프로토콜을 통해 메시징 기능을 지원하는 브로커입니다. Spring에서 제공하는 기본적인 Simple Broker는 애플리케이션 내에서 빠르고 간단하게 Pub/Sub 모델을 구현하기 위해 사용됩니다.
- 구성: Simple Broker는 메시지를 메모리에서 처리하고 전달하므로 별도의 외부 메시징 시스템이 필요하지 않습니다. 따라서 클라이언트 간의 간단한 메시징을 처리하기 위한 내부 브로커로 많이 사용됩니다.
- 특징:
- 내장된 경량 브로커: 별도의 메시징 서버를 구성하지 않고도 동작하므로 빠르게 설정하고 사용할 수 있습니다.
- 한계: 메모리 기반 처리로 확장성에 한계가 있고, 메시지 저장 및 재처리 기능이 부족합니다. 따라서 규모가 크거나 지속적인 메시지 보관이 필요한 경우에는 적합하지 않습니다.
2. MQTT Broker
- 사용 방식: MQTT는 메시징에 특화된 경량 프로토콜로, 주로 사물인터넷(IoT)이나 모바일 환경에서 많이 사용됩니다. MQTT Broker는 MQTT 프로토콜을 기반으로 동작하며, Pub/Sub 모델을 사용하여 여러 클라이언트가 메시지를 주고받을 수 있습니다.
- 구성: MQTT Broker는 외부에 독립적으로 실행되는 메시지 브로커(예: Mosquitto, HiveMQ 등)로, 클라이언트가 연결을 통해 메시지를 주고받습니다.
- 특징:
- 경량 프로토콜: 제한된 리소스를 가진 환경에서도 효율적으로 메시지를 처리할 수 있도록 설계되었습니다.
- 지속성: MQTT Broker는 메시지의 영속성을 지원하며, 클라이언트가 오프라인 상태에서도 메시지를 보존하고, 다시 연결될 때 전달할 수 있습니다.
- 확장성: 수많은 클라이언트를 처리할 수 있는 확장성을 가지고 있으며, 클러스터링과 같은 고가용성 기능도 지원합니다.
- QoS(Quality of Service): 메시지 전달 품질을 설정할 수 있어, 중요한 메시지의 전달 보장을 강화할 수 있습니다.
비교
항목 Simple Broker MQTT Broker
사용 프로토콜 | STOMP | MQTT |
구성 방식 | 애플리케이션 내장형 (메모리 기반) | 외부 브로커 (Mosquitto, HiveMQ 등) |
확장성 | 제한적 (소규모 애플리케이션) | 매우 높음 (대규모 IoT 및 모바일 환경) |
지속성 | 없음 | 메시지 영속성 지원 |
QoS | 제공하지 않음 | QoS 0, 1, 2 지원 |
따라서 Simple Broker는 소규모 애플리케이션에서 간단한 메시징 기능을 원할 때 적합하고, MQTT Broker는 대규모 시스템이나 IoT 환경에서 높은 확장성과 안정성을 요구하는 경우에 적합합니다.
클라이언트가 메시지를 주고받는다는 것은 항상 큐에 저장된다는 의미는 아닙니다. 이는 메시지 브로커의 설정과 사용하는 프로토콜의 동작 방식에 따라 달라집니다.
큐(Queue)와 메시지 저장에 대한 개념
- *큐(Queue)**는 메시지를 특정 순서대로 저장하고, 이를 하나씩 소비하는 메시지 처리 방식입니다. 메시지가 한 번 소비되면 큐에서 사라집니다. 일반적으로, 점대점(Point-to-Point) 모델에서 사용됩니다. 하지만 MQTT와 STOMP의 Pub/Sub(Publish/Subscribe) 모델에서는 모든 메시지가 큐에 저장되지는 않습니다.
STOMP 또는 Simple Broker에서의 메시지 흐름
- STOMP(Simple Text Oriented Messaging Protocol)는 주로 Pub/Sub 모델을 사용합니다. 여기서 브로커는 메시지를 구독한 여러 클라이언트에게 메시지를 전달하는 역할을 합니다.
- Spring의 Simple Broker는 기본적으로 메모리 내에서만 메시지를 일시적으로 유지하며, 메시지를 구독 중인 클라이언트에게 실시간으로 전달합니다. 큐에 저장되지 않고, 메시지가 곧바로 전송됩니다.
- 따라서 클라이언트가 연결되어 있지 않으면 그 동안 보낸 메시지는 손실됩니다. 큐처럼 저장하고 다시 전송하지 않습니다.
MQTT Broker에서의 메시지 흐름
- MQTT는 메시지를 큐에 저장할 수 있는 옵션을 가지고 있습니다. 특히, QoS(Quality of Service) 설정에 따라 메시지가 다르게 처리됩니다:
- QoS 0: "At most once" – 메시지가 브로커에 저장되지 않고, 한 번 전송되면 끝입니다.
- QoS 1: "At least once" – 메시지를 적어도 한 번은 전달해야 하므로, 브로커가 메시지를 저장하고, 클라이언트가 메시지를 받을 때까지 재시도합니다.
- QoS 2: "Exactly once" – 메시지가 정확히 한 번만 전달되도록 보장하는데, 이 경우 메시지가 브로커에 저장되었다가 클라이언트에게 전달됩니다.
또한, MQTT는 Persistent Session을 제공하여 클라이언트가 오프라인 상태일 때도 메시지를 보관하고, 재연결 시 전달할 수 있습니다. 이 때 큐 또는 특정 저장소에 메시지를 유지할 수 있습니다.
정리하자면:
- STOMP(Simple Broker): 메시지는 실시간으로 전달되며, 클라이언트가 구독 중일 때만 수신할 수 있습니다. 메시지가 브로커 내에 큐에 저장되지 않고, 구독자에게 바로 전송됩니다.
- MQTT Broker: QoS와 설정에 따라 메시지를 큐에 저장하거나 브로커가 메시지를 보관할 수 있습니다. 필요시 클라이언트가 재연결하면, 이전에 받은 적 없는 메시지를 큐에서 가져올 수 있습니다.
따라서, MQTT 브로커는 메시지를 큐에 저장하는 구조를 가질 수 있지만, STOMP의 Simple Broker는 메시지를 즉시 전달하는 방식이라 메시지를 큐에 저장하지는 않습니다.
MQTT에서 QoS 2를 사용하면 브로커는 메시지를 클라이언트에게 정확히 한 번(Exactly once) 전달하기 위해 메시지를 일시적으로 저장합니다. 이 과정에서 발생할 수 있는 메시지 저장 용량과 메시지 순서 보장 문제에 대해 설명하겠습니다.
1. 메시지 저장 (메모리 크기 제한)
MQTT 브로커는 QoS 2 메시지를 정확히 한 번 전달하기 위해 메시지의 임시 저장소에 메시지를 보관합니다. 이 메시지 저장이 반드시 메모리에서만 이루어지는 것은 아니며, 디스크와 같은 외부 스토리지를 사용할 수도 있습니다. 각 브로커의 설정에 따라 다르지만, 주요 사항은 다음과 같습니다.
- 메모리 사용 제한: 대부분의 MQTT 브로커는 메모리 사용량을 제한할 수 있는 설정을 제공합니다. 예를 들어, 메시지 수나 총 메모리 크기를 제한해 메모리가 초과될 경우, 메시지가 손실되거나 오래된 메시지부터 삭제되는 방식으로 동작할 수 있습니다.
- 메모리 설정 예시 (Mosquitto MQTT 브로커):
- max_queued_messages: 최대 대기 메시지 수를 설정할 수 있습니다.
- message_size_limit: 메시지의 최대 크기를 설정할 수 있습니다.
- 메모리 설정 예시 (Mosquitto MQTT 브로커):
- 메시지 저장 위치: 메모리 대신 디스크에 저장하여 메시지를 지속적으로 유지할 수 있습니다. 예를 들어, 브로커는 QoS 1, 2의 메시지를 영구 저장소에 기록하여 클라이언트가 재연결할 때 해당 메시지를 다시 전송할 수 있습니다.
따라서 브로커의 메모리 및 스토리지 제한은 브로커 설정에 따라 결정되며, 무한정으로 메시지가 쌓이는 것을 방지하기 위해 용량을 설정할 수 있습니다.
2. 메시지 순서의 정합성 (QoS 2에서 순서 보장)
MQTT에서 QoS 2는 메시지가 정확히 한 번만 전달됨을 보장하는 동시에, 순서 정합성을 보장하기 위해 다음과 같은 절차를 사용합니다:
- 4단계 핸드셰이크: QoS 2 메시지가 전송될 때, 클라이언트와 브로커는 4단계 메시지 교환을 통해 전달 상태를 확인합니다. 이 핸드셰이크 절차는 순서가 정확하게 유지되도록 설계되어 있습니다. 4단계는 다음과 같습니다:
- PUBLISH: 클라이언트가 메시지를 전송합니다.
- PUBREC: 브로커가 메시지를 수신했음을 확인하고 응답합니다.
- PUBREL: 클라이언트가 메시지 전달을 확인하고 "릴리스" 요청을 보냅니다.
- PUBCOMP: 브로커가 메시지를 처리 완료했음을 알리고 통신이 종료됩니다.
- 메시지 순서 처리: 브로커는 각 메시지에 **Packet Identifier(패킷 식별자)**를 부여하고, 메시지가 중복되거나 순서가 어긋나는 것을 방지합니다. 클라이언트가 패킷을 잘못 처리하거나 누락한 경우, 다시 요청하여 정확한 순서로 메시지를 재전송받을 수 있습니다.
- 클라이언트 재연결 시 처리: QoS 2에서는 클라이언트가 연결이 끊겼다가 다시 연결되더라도 순서가 보장된 상태에서 메시지를 받도록 브로커가 재조정합니다. 클라이언트가 이전에 수신했던 메시지를 브로커가 기억하고, 재전송할 필요가 없음을 인식합니다.
메시지 순서 관련 도전 과제
- 멀티 클라이언트 환경: 여러 클라이언트가 같은 주제를 구독할 경우, 메시지가 여러 클라이언트에게 동시에 전송될 때 각 클라이언트에 대한 순서 보장은 개별적으로 이루어집니다. 클라이언트 간에 동기화된 메시지 순서는 MQTT 프로토콜 자체에서 보장하지 않으므로 클라이언트 단에서 처리해야 합니다.
- 대기열에서의 처리 순서: 메시지가 브로커 내부의 큐에 저장되는 경우, 큐에서 처리되는 순서에 따라 메시지가 전송됩니다. 하지만 각 메시지는 독립적으로 처리되기 때문에, QoS 2를 사용할 때에도 메시지 순서가 반드시 동일한 순서로 배달된다는 보장은 없을 수 있습니다. 이를 해결하기 위해 각 메시지에 타임스탬프 또는 ID를 포함해 클라이언트 측에서 순서를 보장할 수 있습니다.
요약:
- 메모리 사용: MQTT 브로커는 QoS 2 메시지를 임시 저장하고 전송하는데, 메모리 및 디스크 사용 제한을 통해 무한히 메시지가 쌓이는 문제를 방지할 수 있습니다. 메모리 제한은 브로커 설정에 따라 조정 가능합니다.
- 메시지 순서 보장: QoS 2는 4단계 핸드셰이크와 Packet Identifier를 통해 메시지 순서와 중복 없는 전송을 보장하며, 클라이언트의 재연결 시에도 정확한 순서로 메시지를 수신할 수 있게 처리합니다.
'Computer Science' 카테고리의 다른 글
[CS] MariaDB는 뭘까? (2) | 2024.12.20 |
---|