1. MQTT란?
MQTT는 Message Queuing Telemetry Transport의 약자로 임베디드 장치들 간의 통신을 위한 가벼운 메시징 프로토콜입니다. 이름대로 초기에는 원격측정을 목적으로 만들어졌으며, 저전력 배터리나 네트워크 상태가 좋지 않은 환경에서 사용가능하여 IOT 기기에서 많이 쓰이고 있습니다. 전송 계층 위에 해당하는 프로토콜이며, 기본적으로 TCP/IP를 기반으로 통신하지만 MQTT-SN(MQTT for Sensor Networks) 프로토콜을 통해 지그비같은 No TCP/IP 환경에서도 통신가능합니다.
2. MQTT 구조
MQTT는 발행자(Publisher), 구독자(Subscriber), 브로커(Broker)로 구성됩니다. HTTP가 요청(Request)-응답(Response)을 기반으로 클라이언트의 요청이 있을때만 서버와 통신이 가능한 단방향 통신인 것에 반하여 MQTT는 발행(Publish)-구독(Subscriber)을 기반으로 브로커를 통해 발행자와 구독자 사이의 양방향 통신이 가능합니다.
발행자가 브로커에게 토픽과 데이터를 발행하면 브로커는 토픽을 구독하는 구독자에게 데이터를 전달합니다. 브로커는 발행자와 구독자 사이의 중계자 역할만 하고 발행자와 구독자 사이에 통신이 되는 구조입니다. 하나의 토픽에 여러 구독자가 구독할 수 있으므로 1:N으로 통신이 가능합니다.
3. 토픽(Topic)
메시지 버스에는 여러 메시지가 흐르는데 이를 구분하기위해 토픽이라는 채널을 만듭니다, 하나의 토픽은 하나의 채널을 구성하며, 슬래쉬(/)를 사용하여 채널의 계층 구분이 가능합니다. 또한 와일드카드를 지원하는데 +와 # 2가지가 있습니다.
+는 자식노드가 같은 모든 노드를 구독합니다. #은 부모노드가 같은 모든 노드를 구독합니다.
예를 들겠습니다.
서울특별시가 최상위 노드이며 자식노드로 강남구, 서초구, 송파구가 있습니다. 그 아래 자식노드로 CGV, 롯데시네마가 있습니다. 서울특별시/강남구/CGV 토픽을 구독한다면 오직 서울특별시/강남구/CGV 토픽에 발행된 데이터만 받을 수 있습니다.
하지만 서울특별시/+/CGV 토픽을 구독한다면 서울특별시/강남구/CGV 토픽뿐만 아니라 서울특별시/서초구/CGV 토픽의 데이터도 받을 수 있습니다. 마찬가지로 서울특별시/강남구/# 토픽을 구독한다면 서울특별시/강남구/CGV 토픽과 서울특별시/강남구/롯데시네마 토픽의 데이터도 받을 수 있습니다.
4. QoS(Quality of Service)
QoS는 서비스 질을 보장해주는 레벨입니다. 와이파이나 No TCP/IP 환경에서는 통신이 불안정할 수 있기때문에 QoS를 적절하게 조절해주는 것이 좋습니다. 발행자와 구독자 모두 QoS 설정이 가능하지만 발행자의 QoS가 우선합니다.
1) QoS 0 (At most once)
QoS 0의 경우 브로커가 구독자에게 메시지를 1번만 발행합니다. 가장 빠른 전송방법으로 구독자에게 데이터가 전달되었는지 확인하지 않습니다. 즉, QoS를 보장하지 않습니다.
2) QoS 1 (At least once)
QoS 1의 경우 브로커가 구독자에게 메시지를 1번 이상 발행합니다. 발행자는 메시지를 발행하고 PUBACK(Publish Acknowledge)을 기다립니다. PUBBACK이 오지않으면 DUP flag와 함께 메시지를 다시 발행하는데 브로커는 이미 메시지를 삭제한 상태이기때문에 구독자에게 다시 메시지를 발행합니다. 즉, 구독자는 중복해서 메시지를 받을 수 있습니다.
3) QoS 2 (Exactly once)
QoS 2의 경우 가장 느린 전송방법이지만 "3 way handshaking"을 통해 브로커는 구독자에게 정확히 1번만 메시지를 발행합니다.
발행자는 메시지를 발행하고 PUBREC(Publish Received)을 기다립니다. PUBREC이 오지 않으면 메시지를 다시 발행하지만 브로커는 메시지를 저장한 상태이기때문에 다시 구독자에게 메시지를 발행하지 않습니다. PUBBEC이 오면 브로커에게 PUBREL(Publish Relese)를 보냅니다. PUBREL을 받은 브로커는 메시지를 삭제하고 발행자에게 PUBCOMP(Publish Complete)을 보냅니다. PUBCOMP을 받은 발행자는 메시지를 삭제합니다.
4) QoS -1 MQTT-SN 프로토콜에서 사용하며 QoS 0 ~ 2는 클라이언트(발행자, 구독자)의 접속을 확인후에 메시지를 발행하지만 -1은 접속 확인 없이 메시지를 발행합니다. 위에 QoS 0 ~ 2를 와이어샤크로 분석한 패킷을 보면 PUBLISH 메시지가 오기전에 CONNACK 메시지가 먼저 온 것을 확인할 수 있습니다.
5. MQTT 패킷 구조
bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
메시지 타입(Message Type) |
중복flag (DUP flag) |
QoS Level |
RETAIN |
byte 2 |
Remaining Length |
byte 3
... byte n |
Option: Variable header |
byte n+1
... |
Option: Payload |
MQTT는 고정헤더(Fixed Header), 가변헤더(Variable Header), 페이로드(Payload)로 구성됩니다. 고정헤더가 2byte로 매우 작아 IOT 통신에 적합합니다.
고정헤더의 1byte는 메시지타입, 중복 플래그(DUP flag), QoS, RETAIN으로 이루어지고 나머지 1byte는 가변헤더와 페이로드의 크기를 나타냅니다.
1) 메시지타입(4bit)
명칭 | 10진수 | 설명 | Reserved | 0 | 사용하지 않음 | CONNECT | 1 | 연결됨 | CONNACK | 2 | 연결 확인(Connect Acknowledgment) | PUBLISH | 3 | 발행 메시지(Publish message) | PUBACK | 4 | 발행 확인(Publish Acknowledgment) | PUBREC | 5 | 발행 수신(Publish Received) | PUBREL | 6 | 발행 해제(Publish Release) | PUBCOMP | 7 | 발행 완료(Publish Complete) | SUBSCRIBE | 8 | 구독 요청(Client Subscribe request) | SUBACK | 9 | 구독 확인(Subscribe Acknowledgment) | UNSUBSCRIBE | 10 | 구독취소 요청(Client Unsubscribe request) | UNSUBACK | 11 | 구독취소 확인(Unsubscribe Acknowledgment) | PINGREQ | 12 | PING 요청(PING Request) | PINGRESP | 13 | PING 응답(PING Response) | DISCONNECT | 14 | 연결 해제 | Reserved | 15 | 사용하지 않음 |
2) 중복 플래그(1bit) : 중복 발행 횟수를 나타내는 플래그입니다. QoS에서 메시지를 다시 발행할때 하나씩 오릅니다.
3) QoS(2bit) : 서비스 질을 나타내는 레벨입니다.
4) RETAIN(1bit) : Retain이 설정되면 브로커가 메시지를 계속 보유하고 있으면서 토픽에 새로운 구독자가 들어올때마다 해당 메시지를 발행합니다.
retain을 설정하면
신규 구독자에게도 메시지가 발행됩니다.
5) 남은 길이(Remaing Length) : 가변 헤더와 페이로드를 포함하여 현재 메시지에 남아있는 byte 크기를 나타냅니다. 최대 4byte까지 사용가능한데 1byte마다 마지막 1bit는 다음 byte가 remaing Length 값으로 사용되는지 결정하기때문에 7bit씩 사용하여 최대 ((2^7)^4-1) = 268435455byte (256 MB)의 값이 올 수 있습니다. 인코딩 알고리즘은 복잡하므로 생략합니다.
패킷을 분석해보면 단지 1byte에 필수 정보가 들어있습니다 ㅇ_ㅇ
|