표준 메세징 프로토콜 정리 (AMQP, STOMP, MQTT)

Dragony·2023년 8월 14일
2

Kafka

목록 보기
6/7

AMQP (Advanced Message Queue Protocol)

등장 배경

AMQP는 메세지 지향 미들웨어 (MOM) 을 위한 표준 응용 계층 프로토콜입니다. 간단히 말하면, 메세지 통신을 위한 규약 스펙 입니다.
플랫폼 종속적인 제품들 사이에서 서로 다른 이기종간에 메세지를 교환하기 위해서는 메세지 포맷 변환을 위해 속도가 느린 메세지 Bridge를 이용하거나, 시스템 자체를 통일 시켜야 하는 불편함과 비효율성이 있었습니다.

그래서, 서로 다른 시스템들 간의 최대한 효율적인 방법으로 메세지를 교환하기 위해 AMQP 프로토콜이 등장하게 되었습니다.

AMQP는 금융계의 이기종 플랫폼간의 메세지 상호 정보 교환을 위해서 JPMorgand의 John O'Hara에 의해 개발되었으며 2006년도에 최초로 사용되었다고 합니다.


구현체

  • RabbitMQ
  • OpenAMQ
  • StormMQ
  • Apache Qpid

특징

AMQP의 주요 기능으로는 메세지 기반, Queuing, 라우팅, 신뢰성 및 보안 등으로 정의할 수 있습니다.

과거의 미들웨어 표준들은 API 레벨(ex: JMS)에서 등장하였습니다. 이러한 방식은 여러 구현체 간 상호 운용성을 제공하기 보다는, 다른 미들웨어 구현체들과 프로그래머의 상호작용을 표준화에 중점을 두었습니다.

API 및 메세지 구현체들이 제공해야 하는 일련의 행동 양식을 정의하는 JMS와 다르게 AMQP는 와이어 레벨 프로토콜입니다. 와이어 레벨 프로토콜은 네트워크를 통해 바이트 스트림으로 전송되는 데이터 형식에 대한 설명입니다.

결과적으로 이 데이터 형식을 준수하는 메세지를 만들고 해석할 수 있는 모든 도구는 구현 언어에 관계없이 다른 호환 도구와 상호 운용이 가능합니다.


단점

  • 성능 오버헤드
    • 유연성과 안정성을 보장하지만, 매우 낮은 대기시간이 필요하거나 매우 높은 메세지를 처리할때는 약간의 성능 오버헤드가 있음
    • 풍부한 기능 집합과 정교한 라우팅 메커니즘은 오버헤드를 증가시키면서 고급 기능을 제공합니다.
    • 사용 사례에 따라 MQTT와 같은 다른 메세징 프로토콜이나 특정 사용 사례에 최적화된 프로토콜이 더 나은 성능을 제공할 수 있음
  • MQTT 보다 더 높은 대역폭을 필요로 함
  • 버전 호환성 문제
    • 이전 버전과 호환되지 않음 (버전 문제를 고려해야 함)
  • 상호 운용성 문제
    • AMQP는 서로 다른 시스템 간의 상호 운용성을 제공하는 것을 목표로 하지만 일부 메시징 브로커 또는 클라이언트는 AMQP 사양을 완전히 준수하지 않아 호환성 문제가 발생할 수 있습니다.
    • AMQP와 호환 가능한 프로토콜들
      • SOTMP
      • XMPP
      • MQPP
      • OpenWire

사용 사례

AMQP는 다목적이며 다양한 시스템과 장치 간의 안정적이고 안전하며 효율적인 통신이 필요한 시나리오에 가장 적합합니다.

즉, AMQP는 손실이나 중복 없이 메시지를 전달해야 하는 사용 사례에서 탁월합니다. 또한 복잡한 라우팅이 필요하고 다양한 애플리케이션과 플랫폼이 원활하게 정보를 교환해야 하는 시나리오에서 탁월합니다.


구조

AMQP는 메세지 큐 구조에 Exchage 라는 라우터 역할이 존재합니다. ExchangePublisher에게 메세지를 수신 받으면 그것을 Queue에 분배해주는 역할을 합니다(큐에 직접 메세지를 전달하지 않음). 이렇게 Queue에 저장된 메세지를 Consumer가 소비하게 됩니다.

한개의 Queue만 있다면 일반적인 메세지 큐와 다를 것 없지만, 여러 개의 ConsumerQueue가 존재할 때 높은 효율을 보여줍니다.

  • Exchange : Publisher(Producer)로 부터 수신한 메세지를 큐에 분배하는 라우터 역할
  • Queue : 메세지를 메모리나 디스크에 저장했다가 Consumer에게 메세지를 전달하는 역할. 스스로가 관심있는 메세지 타입을 지정한 Binding을 통해 Exchange에 말 그대로 Bind 된다.
  • Binding : Exchange에 전달된 메세지가 어떤 Queue에 저장되어야 하는지 정의

Exchange의 종류

  • Direct Exchange

    • 메세지의 라우팅 키를 큐에 1:1로 매칭 시키는 방법
    • Direct Exchange는 Exchange로 수신된 메시지의 routing key와 Queue의 Binding key가 정확히 매칭되는 Queue로 전달됩니다.
  • Fanout Exchange

    • 모든 메세지를 모든 큐로 라우팅하는 유형
    • Fanout Exchange는 Exchange와 매칭된(바인딩 된) 모든 Queue에 메시지를 전달합니다. 이때 라우팅 키는 무시가 됩니다.
    • 1:N 관계로 메시지를 브로드캐스트하는 용도로 사용합니다.
  • Topic Exchange

    • Direct Exchange와 유사한 방식이지만 고정된 routing key를 사용하는 것 대신 와일드카드(Wildcard)를 사용합니다. 메시지는 하나 또는 여러개의 routing pattern이 맞는 Queue에 보내집니다.
    • 라우팅 키는 ","으로 구분된 0개 이상의 단어의 집합으로 간주 되고 와일드카드 문자들을 이용해 특정 큐에 바인딩합니다.
    • '*' : 하나의 단어
    • '#' : 0개 이상의 단어
  • Headers Exchange

    • 마지막으로 Headers Exchange는 routing key 대신에 헤더 속성을 통해 라우팅됩니다.
    • key-value로 정의된 헤더에 의해 라우팅을 결정합니다.
    • 큐를 바인딩 할 때 x-match라는 특별한 argument로 헤더를 어떤식으로 해석하고 바인딩 할지를 결정합니다.
      • all : 모두 충족 시켜야함 (and)
      • any : 하나만 충족시키면 됨 (or)


STOMP (Simple/Stream Text Oriented Message Protocol)

특징

  • STOMP는 웹소켓 위에서 동작하는 텍스트 기반 메세징 프로토콜로써 클라이언트와 서버가 전송할 메세지의 유형, 형식, 내용들을 정의하는 매커니즘입니다.
  • TCP 또는 웹소켓과 같은 신뢰할 수 있는 양방향 스트리밍 네트워크 프로토콜에서 사용할 수 있습니다.
  • 기본적으로 pub/sub 구조로 되어있어 메세지를 전송하고 받아 처리하는 부분이 확실히 정해져있습니다.
  • http와 마찬가지로 frame을 사용해 전송하는 프로토콜입니다.
  • 헤더 값을 기반으로 통신 시 인증 처리를 구현할 수 있습니다.

구현체

  • ActiveMQ
  • Fuse Message Broker
  • HOpenMQ
  • RabbitMQ

단점

  • 제한된 기능
    • STOMP는 단순하고 가벼운 프로토콜로 설계되었으므로 고급 기능이 부족할 수 있습니다.
    • 이러한 단순성은 일부 시나리오에서 이점이 될 수 있지만, 구현할 수 있는 메세징 패턴 및 상호 작용 유형을 제한할 수도 있습니다.
  • 전달 보장 없음
    • AMQP와 같은 프로토콜과 달리 STOMP는 기본 제공 보장 전달 또는 메세지 확인 메커니즘을 제공하지 않습니다. 일부 STOMP 서버는 유사한 동작 달성을 위해 확장 기능을 제공할 수는 있지만, 추가 구현에 노력이 들 수 있습니다.
  • 서비스 품질 (QoS) 수준 없음
    • 최대 한번, 적어도 한번, 정확히 한번과 같이 메세지 전달에 대해 서로 다른 수준의 서비스 품질을 정의하지 않습니다.
    • 필요한 경우 고유한 메커니즘을 구현해야 합니다.
  • 텍스트 기반 프로토콜
    • MQTT와 같은 바이너리 프로토콜에 비해 메세지 크기가 더 클 수 있습니다.
    • 대량의 데이터를 처리할 때 네트워크 대역폭과 성능에 영향을 미칠 수 있습니다.
  • 지속성 문제
    • STOMP 자체는 메시지 지속성 또는 저장을 위한 내장 메커니즘을 제공하지 않습니다. 즉, 기본 메시지 브로커 또는 미들웨어에서 제공하는 기능에 의존해야 합니다.
    • 이 때문에 장애 시 메세지 유실 가능성이 있습니다.
  • 복잡한 시나리오에 적합하지 않음

사용사례

단순성과 사용 편의성이 우선시되는 시나리오에서 사용될 수 있습니다.

  • 웹 애플리케이션
    • 브라우저와 백엔드 서버 간의 실시간 통신
  • 실시간 업데이트
    • 실시간 업데이트 및 알림을 클라이언트에 푸시하여 사용자가 자주 폴링할 필요 없이 즉시 업데이트를 받을 수 있습니다.
  • 채팅 애플리케이션
  • 프로토타이핑, 데모, 디버깅, PoC 등 쉽고 빠르게 개발해야 할 경우

Command

STOMP 프로토콜은 대체로 HTTP와 유사하며 다음 명령을 사용하여 TCP를 통해 작동합니다.

클라이언트와 서버 간의 통신은 여러 줄로 구성된 Frame을 통해 이루어집니다.
요청 Frame에는 메세지는 무엇이고, 누가 받아서 처리할지에 대한 Header 정보가 포함되어 있습니다.

Command 들은 'destination' 헤더를 요구하는데, 어디에 메세지를 전송할 지, 혹은 어디에서 메세지를 구독할 것인지를 나타냅니다. 이러한 과정을 통해 STOMP는 pub-sub 메커니즘을 제공합니다.

즉, Borker를 통해 타 사용자들에게 메세지를 보내거나 서버가 특정 작업을 수행하도록 메세지를 보낼 수 있게 됩니다.

CONNECT
SEND
SUBSCRIBE
UNSUBSCRIBE
BEGIN
COMMIT
ABORT
ACK
NACK
DISCONNECT

Frame

Frame 은 명령(command)과 추가적인 헤더(header)와 추가적인 바디(body)로 구성됩니다.

Frame은 몇 개의 텍스트 라인으로 지정된 구조인데, 첫번째 줄에는 Command이고, 이후 <key>:<value> 형식의 헤더 정보를 나타내고(한 줄에 하나씩), header 이후에 공백 줄 (빈 줄)을 하나 추가하는 것으로 헤더의 끝을 설정할 수 있습니다.

헤더 이후에는 payload(Body) 가 존재합니다. 이는 실제 전송되는 데이터 입니다. Body의 끝은 NULL 문자로 설정합니다.

COMMAND
key(header):value
key(header):value
...

BODY^@
  • Example
SEND
destination:/queue/a
content-type:text/plain

hello queue a
^@


MQTT

  • 사물 통신 (M2M: Machine to Machine), 사물 인터넷(IoT: Internet of Things)과 같이 대역폭이 제한된 통신 환경에 최적화하여 개발된 푸시 기술(Push Technology) 기반의 경량 메세지 전송 프로토콜입니다.
  • 즉, IoT와 같은 제한된 환경에서 대규모 트래픽 전송을 위해 만들어진 프로토콜이고, TCP/IC 프로토콜 위에서 동작하지만 동시에 굉장히 가벼오며, 많은 통신 제약들을 해결해줍니다.
  • 단방향 통신이 아니라, Device와 Cloud 간 송수신을 하는 양방향 통신을 지원합니다.

특징

  • 가볍고 효율적임
    • 가장 작은 MQTT 제어 메세지는 2바이트 정도로 작고, 메세지 헤더도 작기 때문에 네트워크 대역폭을 최적화 할 수 있고, 작은 마이크로 컨트롤러에도 사용 가능합니다.
  • 확장성
    • MQTT 구현에는 최소량의 코드만 필요하며, 아주 작은 전력만 소비됩니다.
    • 또한 많은 수의 IoT 디바이스와의 통신을 지원하기 때문에, MQTT 프로토콜을 구현하여 수백만개의 디바이스에 연결할 수 있습니다.
  • 신뢰성
    • 많은 IoT 디바이스는 대역폭은 낮고 지연 시간은 긴 신뢰할 수 없는 셀룰러 네트워크를 통해 연결합니다.
    • MQTT에는 IoT 디바이스에서 클라우드에 다시 연결하는 데 소요되는 시간을 줄여주는 기능이 기본적으로 탑재되어 있습니다.
    • 또한 최대 1회(0), 최소 1회(1) 및 정확히 1회(2) 라는 3가지 서비스 품질 수준 (QoS)를 정의하여 IoT 사용 사례에 필요한 신뢰성을 보장합니다.
  • 보안
    • MQTT를 사용하면 메세지를 손쉽게 암호화하고 OAuth, TLS1.3, 고객 관리형 인증서 및 기타 최신 인증 프로토콜을 사용하여 디바이스와 사용자를 인증할 수 있습니다.
  • 우수한 지원
    • Python과 같은 다수의 언어가 MQTT 프로토콜 구현을 광범위하게 지원합니다.

단점

  • 제한된 메세지 브로커 기능
    • Streaming Processing이나 Data Integration, 복잡한 메세지 라우팅 등 제공하지 않음
  • 메세지 전달 보장 부족
    • 세가지 서비스 품질 수준 (QoS)를 제공하지만, 가장 높은 QoS 수준도 메세지가 정확히 한번만 전달된다는 보장은 없음.
    • 네트워크 중단 또는 브로커 오류로 인해 중복 메세지가 전달될 가능성이 있음
  • 텍스트 기반 프로토콜
    • 페이로드는 바이너리 일 수 있지만, 프로토콜 자체에는 텍스트 헤더로 인해 약간의 오버헤드가 있을 수 있음
  • 복잡한 워크플로우에 적합하지 않음
    • 단순한 실시간 통신 패턴에 적합하고, 복잡한 워크플로우, 변환 및 처리에 경우 AMQP 와 같이 기능이 풍부한 프로토콜이 더 적합할 수 있음

사용사례

  • 제한된 장치와 신뢰할 수 없는 네트워크 사용 시 (저전력 소비, 최소 대역폭) => IoT 디바이스
  • 가벼운 Push-based messaging solution이 필요할때

QoS (Quality of Service)

  • 0 : 최대 1회 전송. Topic을 통해 메세지를 전송할 뿐 보장은 하지 않습니다. (보낸 다음 잊어버림)
  • 1 : 최소 1회 전송. 구독하는 클라이언트가 메세지를 받았는지 불확실하면 정해진 횟수만큼 재전송합니다.
    • 메세지 핸드셰이킹 과정을 엄밀하게 추적하지는 않으므로 중복의 위험성이 존재합니다. (확인 응답을 거치는 전달)
  • 2 : 구독하는 클라이언트가 요구된 메세지를 정확히 한 번 수신할 수 있도록 보장합니다. (메세지의 핸드 셰이킹 과정을 추적)
    • 높은 품질을 보장하지만 성능의 희생이 따릅니다.
  • 이 필드는 기반이 되는 TCP/IP 데이터 전송의 처리에 영향을 주지 않으며, MQTT 송신자와 수신자 간에만 사용됩니다.

-> 0~1 정도의 QoS를 사용하며, 메세지 손실의 위험은 상위 애플리케이션 차원에서 관리하는 방법이 널리 쓰입니다.


구조

MQTT 프로토콜은 클라이언트-서버 구조로 이루어지는 것이 아닌, Broker, Publisher, Subscriber 중심의 pub/sub 모델의 원칙을 기반으로 작동합니다.


구현체

MQTT 프로토콜을 구현하는 브로커들은 아래와 같은 것들이 있습니다.

  • Mosquitto
  • HiveMQ
  • mosca
  • ActiveMQ
  • RabbitMQ (Plug-in 형태로 지원)



profile
안녕하세요 :) 제 개인 공부 정리 블로그입니다. 틀린 내용 수정, 피드백 환영합니다.

1개의 댓글

comment-user-thumbnail
2024년 4월 16일

잘 읽었습니다.
글 중 MQTT 단점으로
"
메세지 전달 보장 부족
세가지 서비스 품질 수준 (QoS)를 제공하지만, 가장 높은 QoS 수준도 메세지가 정확히 한번만 전달된다는 보장은 없음.
네트워크 중단 또는 브로커 오류로 인해 중복 메세지가 전달될 가능성이 있음
"
QoS 2의 경우 정확히 한 번만 전달되어 중복 메세지 전달 가능성은 없는 것으로 알고 있습니다.

답글 달기