Q린이의 MQTT 도입기!

몇 달 전, 저희가 고객사에 LoRa OSS 시스템을 구축하던 때였습니다.

OSS는 저전력 장거리 통신에 특화된 LoRaWAN 프로토콜을 이용하여 산업 현장 내 근로자의 안전을 지켜주고 작업의 효율을 높여주는 솔루션입니다. (깨알홍보!)

로라

필드에 있는 수천여 대의 GPS Tracker로부터 위치 정보를 수집하여 서버에 저장하고, 원격지에서 그를 모니터링 할 수 있도록 지원해주는 시스템인데, 고객사 PM님으로부터…

나PM : 측위 데이터 저희 서버까지 보내주셔야 되잖아요?
Q린이 : 네, REST로 짜고 있었는데 POST로 넣어드리면 될까요?
나PM : 저희 서버는 서버 역할은 못 하고, 클라이언트 역할만 수행할 수 있어요. 😭
Q린이 : ?!!

서버가 서버 역할을 못 한다니… 이 무슨, 서버인 듯 서버 아닌 서버 같은 서버란 말인가…
나중에 알고 보니 고객사 서버 앞단에 덧댄 미들웨어의 특수성 때문이긴 했지만, 아무튼.


Polling

최초에 제가 꺼내든 카드는 폴링이었습니다. 고객사 서버가 서버로는 동작을 못 한다니, 그럼 클라이언트로서 무스마 서버를 바라보게 하고, 특정 주기마다 조회할 데이터의 유무를 체크하게끔 구성하면…!

나PM : 아, 저희 쪽에서 데이터를 이렇게 가져가라고요?
Q린이 : 네, 이 정도 주기로 요청하는 건 부담스럽지도 않고요.
나PM : 부담스러운데요..
Q린이 : 간격을 여유 있게 조금 늘여볼까요?
나PM : 그러면 데이터의 정시성 보장이 안 되잖아요. 실시간 모니터링이어야 하는데. 😭
Q린이 : ?!!

음…
한참을 고민 고민하던 끝에, 그제야 Message Queue 생각이 들었습니다. Topic을 중심으로 Message 발행 및 구독을 통해 데이터를 공유하는 EDA(Event-Driven Architecture)에 답이 있겠구나!

방법

네, 그렇습니다! 😭

MQTT ?

MQTT는 Message Queuing Telemetry Transport의 약자로 TCP/IP 프로토콜 베이스로 설계된 가벼운 pub/sub 모델의 메시징 프로토콜입니다. 여러 장점 때문에 IoT 쪽에서는 대표적인 프로토콜로 자주 쓰입니다.

MQTT broker가 존재하고, 다수의 클라이언트들은 broker를 통해 publish 또는 subscribe 함으로써 데이터를 송수신할 수 있습니다.

왜 많고 많은 Message Queues 가운데 MQTT를 택했나 물으시면, MQTT의 대표성, 연동성을 들 수 있을 것 같습니다. ISO 표준 프로토콜이고, 마이너한 다른 많은 MQ보다는 상대적으로 고객사를 설득하는 데 힘을 실어줄 수 있으리라 확신했습니다.


시작하기

MQTT broker에는 많은 종류가 있습니다만, 저는 Mosquitto와 고민하다가 결국 Mosca를 택했습니다. 모기보다는 단연, 고양이죠! 대체 왜?

mosca

귀여우면 도큐먼트도 잘 읽힌다는 게 학계의 정설

나중에야 알았지만 Mosca의 author이신 Matteo Collina님이 최근 Aedes라는 library를 새로 작업중이셨습니다. 이런 말씀을 남기셨네요!

This library is born after a lot of discussion with all Mosca users and how that was deployed in production. This addresses your concerns about performance and stability. (https://github.com/mcollina/aedes#acknowledgements)

Aedes는 나중에 또 한 번 살펴보기로 하고, 다시 Mosca로 돌아가서

  • 설치 (standalone service)

      $ npm install mosca bunyan -g
    
  • 사용법

      $ mosca -v | bunyan
    

broker는 준비 끝났습니다. :)

  • Client #1 - Publisher

      const mqtt = require('mqtt')
      const client = mqtt.connect('mqtt://localhost')
    
      client.on('connect', () => {
          client.publish('presence', 'Hello mqtt')
      })
    
  • Client #2 - Subscriber

      const mqtt = require('mqtt')
      const client = mqtt.connect('mqtt://localhost')
    
      client.on('connect', () => {
          client.subscribe('presence', err => {
              if(err) console.error(err)
          })
      })
        
      client.on('message', (topic, message) => {
          console.log(`${topic} : ${message.toString()}`)
      })
    

간단한 테스트 코드는 이 정도면 충분합니다. 너~무 간단하죠! 😍
다음 포스트에서는 MQTT에 대해 보다 심도 있게 알아보도록 하겠습니다.

사이먼