글 / MQTT 메시징

MQTT Retained 메시지

retain으로 발행한 마지막 값은 브로커가 토픽마다 하나씩 보관하고 새 구독자에게 즉시 전송한다.

작성일 · 읽는 시간 2분 · MQTT 5.0 기준

Retained 메시지의 필요성

브로커는 메시지가 발행된 시점에 구독 중이던 클라이언트에게만 메시지를 전송한다. 이후에 구독한 클라이언트는 다음 발행이 있을 때까지 아무것도 수신하지 못한다. 값이 드물게 변경되는 토픽이라면 오랫동안 현재 값을 알 수 없다.

retain 플래그

PUBLISH 패킷의 retain 플래그를 설정하면 브로커는 그 메시지를 토픽의 retained 메시지(보관 메시지)로 저장한다. 브로커는 보관 메시지를 토픽마다 하나만 유지하며, retain을 설정한 새 메시지가 도착하면 기존 메시지를 새 메시지로 대체한다. 새 구독이 생성되면 브로커는 필터와 일치하는 토픽의 보관 메시지를 즉시 전송한다.

bash
# 상태를 retain으로 발행한다
mosquitto_pub -t plant/line1/robot3/status -m '{"state":"IDLE"}' -q 1 -r

# 나중에 구독해도 마지막 값을 바로 받는다
mosquitto_sub -v -t 'plant/line1/+/status'

구독 직후에 수신하는 보관 메시지는 retain 플래그가 1로 전달된다. 구독한 뒤에 발행되어 전달된 메시지는 기본 설정에서 0으로 전달되므로, 수신 측은 보관된 값과 새로 발행된 값을 구분할 수 있다.

보관 메시지가 새 구독자에게 전달되는 순서와 retain 플래그 값

보관 메시지 삭제

같은 토픽에 retain 플래그를 설정한 상태로 길이 0인 페이로드를 발행하면 보관 메시지가 삭제된다.

bash
# -n은 길이 0인 메시지를 보낸다
mosquitto_pub -t plant/line1/robot3/status -n -r

보관 메시지가 저장, 대체, 삭제되는 조건과 전이

참고

보관 메시지는 세션에 속하지 않으므로, 발행한 클라이언트의 세션이 종료되어도 유지된다.

상태와 이벤트의 적용 기준

  • 상태: 현재 모드, 연결 여부, 설정값처럼 마지막 값이 곧 현재 값인 정보. retain이 적합하다.
  • 이벤트: 버튼 눌림, 알람 발생, 명령처럼 한 번 발생한 사건. retain을 사용하지 않는다.

이벤트를 보관하면 새 구독자는 과거의 이벤트를 방금 발생한 이벤트로 수신한다. 명령 토픽이라면 재시작한 장비가 이전 명령을 한 번 더 실행하게 된다.