MQTT(Message Queueing Telemetry Transport)
https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
MQTT Version 5.0
docs.oasis-open.org
MQTT는 주로 IoT 통신에 사용되는 OASIS 표준 pub-sub 기반 메시징 프로토콜이다. TCP/IP 위에서 동작하며, 헤더 크기가 작기 때문에 효율적인 통신이 가능하다.
배경
1999년 위성을 통해 정유 파이프라인을 모니터링하기 위한 목적으로,최소한의 배터리 손실 및 대역폭으로 통신할 수 있는 프로토콜로 개발되었다. 이후 IBM은 2010년 MQTT 3.1을 개방형 프로토콜로 오픈했고, 2013년 유지 관리를 위해 OASIS( Organization for the Advancement of Structured Information Standards ) 에 제출되어 표준 프로토콜이 되었다.
구조
MQTT는 pub - sub 기반으로 동작한다. 각 IoT 장치(클라이언트)는 메시지를 발행하거나 구독할 수 있으며, 클라이언트 사이의 pub - sub 통신을 중간에서 처리하는 브로커(서버)가 존재한다. 일반적인 pub - sub 모델을 생각하면 된다. 공식 명세에서는 broker 대신 server라는 표현을 사용하고 있다.
- Client: MQTT 프로토콜을 이용하는 프로그램 또는 장치. 메시지를 게시하거나 구독할 수 있다.
- Server: 게시자 / 구독자 역할을 하는 클라이언트들 사이에서 중개자 역할을 하는 프로그램 또는 장치
- 클라이언트의 구독 / 구독 취소 요청을 처리
- 클라이언트가 게시한 메시지 수락
- 메시지가 들어왔을 때, 해당 메시지를 구독한 클라이언트에게 메시지 전달
QoS
MQTT는 3가지 수준의 서비스 품질을 지원한다.
- QoS 0: 메시지를 최대 한번 전달. 메시지가 손실될 수 있다.
- QoS 1: 메시지를 최소 한번 전달 . 메시지는 손실되지 않지만, 중복될 수 있다.
- Q0S 2: 메시지를 정확히 한번 전달. 메시지가 손실되지도, 중복되지도 않지만 리소스가 많이 든다.
패킷 구조
https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901019
크게 3개 부분으로 나뉜다.
- Fixed Header:모든 패킷 타입 공통 헤더
- Variable Header: 일부 패킷 타입이 가지는 헤더
- Payload: 일부 패킷 타입이 가지는 헤더
Fixed Header
모든 MQTT 패킷이 공통으로 가지는 Fixed Header은 2byte의 크기를 가진다.
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1 | MQTT Control Packet type | Flags specific to each MQTT Control Packet type | ||||||
byte 2… | Remaining Length |
- Control Packet Type[7-4]: 패킷의 타입. 현재 15개의 패킷 타입이 존재한다.
- Flag[3-0]: 패킷 타입에 따라 추가적인 정보를 포함하는 영역. 메시지를 발행하는 PUBLISH는 QoS 지정을 위해 [2-1] 비트를 이용한다.
- Remain Length: Variable Header + Payload의 byte 길이
Name | Value | Direction of flow | Description |
Reserved | 0 | Forbidden | Reserved |
CONNECT | 1 | Client to Server | Connection request |
CONNACK | 2 | Server to Client | Connect acknowledgment |
PUBLISH | 3 | Client to Server or Server to Client |
Publish message |
PUBACK | 4 | Client to Server or Server to Client |
Publish acknowledgment (QoS 1) |
PUBREC | 5 | Client to Server or Server to Client |
Publish received (QoS 2 delivery part 1) |
PUBREL | 6 | Client to Server or Server to Client |
Publish release (QoS 2 delivery part 2) |
PUBCOMP | 7 | Client to Server or Server to Client |
Publish complete (QoS 2 delivery part 3) |
SUBSCRIBE | 8 | Client to Server | Subscribe request |
SUBACK | 9 | Server to Client | Subscribe acknowledgment |
UNSUBSCRIBE | 10 | Client to Server | Unsubscribe request |
UNSUBACK | 11 | Server to Client | Unsubscribe acknowledgment |
PINGREQ | 12 | Client to Server | PING request |
PINGRESP | 13 | Server to Client | PING response |
DISCONNECT | 14 | Client to Server or Server to Client |
Disconnect notification |
AUTH | 15 | Client to Server or Server to Client | Authentication exchange |
Variable Header
패킷 유형에 따라 다르게 가지는 헤더 정보. PUBLISH의 경우 토픽 이름이 여기에 포함된다.
Payload
패킷과 함께 전달되는 데이터. PUBLISH의 경우 클라이언트에서 전달하는 메시지가 여기에 포함된다.
Topic Name / Filter
MQTT에서는 특정 토픽에 대해 메시지를 구독하거나 게시하게 된다. 토픽의 이름은 / (슬래시) 를 기준으로 여러 레벨로 나뉘며, 와일드카드를 필터에 사용하여 매칭되는 여러 토픽을 동시에 구독할 수도 있다.
hello/world 라는 토픽 이름은 hello, world라는 2개의 레벨로 구성된다.
- Topic Name: 특정 메시지를 게시(publish)할 때 사용하는 토픽의 이름
- Topic Filter: 특정 메시지를 구독(subscribe)할 때 사용하는 토픽 이름에 대한 필터
와일드카드
와일드카드는 특정 문자가 아닌 "레벨"을 대체한다.
- #(다중 레벨 와일드카드): 다중 레벨을 대체
- test/# 은 test, test/hello, test/hello/world 등 test 이하 모든 레벨과 매칭된다.
- +(단일 레벨 와일드카드): 한 레벨을 대체
- test/+/hello는 test/1/hello, test/world/hello와는 매칭되지만, test/tt/hello/world와는 매칭되지 않는다.
$로 시작하는 토픽
$로 시작하는 토픽은 MQTT 프로토콜에서 메시지 교환 이외의 다른 목적으로 서버가 이용할 수 있도록 예약되어 있다. 일반적으로 서버 정보를 제공할 때 $SYS/ 를 널리 사용하고 있으며, 클라이언트는 $로 시작하는 토픽을 게시할 수 없다.
$ 토픽의 첫번째 레벨은 와일드카드(#, +)에 매칭되지 않는다. 즉, $SYS는 #, +에 매칭되지 않는다. 이때 #, +는 레벨을 대체하는 와일드카드이기 때문에, $로 시작하는 모든 토픽을 한번에 구독하는 방법은 존재하지 않는다.
더 자세한 설명이 필요한 경우 MQTT 공식 명세를 살펴보자.