MQTT(Message Queuing Telemetry Transport) 프로토콜은 1999년, IBM의 앤디 스탠퍼드 클락(Andy Stanford-Clark)과 당시 아르컴 컨트롤 시스템즈(Arcom Control Systems, 현 시러스 링크) 소속의 알렌 니퍼(Arlen Nipper)에 의해 처음 개발되었다.1 이 프로토콜의 탄생 배경에는 매우 구체적이고 현실적인 산업 현장의 요구가 있었다. 당시 이들은 위성을 통해 광범위하게 펼쳐진 석유 및 가스 파이프라인을 원격으로 모니터링해야 하는 과제에 직면했다.2 이러한 환경은 네트워크 대역폭이 극도로 제한적이고, 통신 비용이 높으며, 연결이 불안정하고, 현장 장비는 배터리와 같은 제한된 전력으로 구동되어야 하는 극한의 조건을 내포하고 있었다. 즉, 최소한의 대역폭과 최소한의 배터리 소모를 지원하면서도 신뢰성 있는 데이터 전송이 가능한 새로운 통신 규약이 절실히 필요했던 것이다.2
이러한 배경 속에서 MQTT는 ‘작은 코드 공간(small code footprint)’과 제한된 네트워크 대역폭 환경에 최적화된 경량 메시징 프로토콜로 설계되었다.1 초기 명칭인 ‘Message Queuing Telemetry Transport’는 당시 IBM의 메시지 큐 제품군인 ‘MQSeries’(현 WebSphere MQ)에서 그 기원을 찾을 수 있다.1 이는 프로토콜의 초기 단계에서 IBM의 기술적 영향이 있었음을 시사하지만, 현재 MQTT는 더 이상 특정 제품군의 약어가 아닌, 프로토콜 자체를 지칭하는 공식적인 이름으로 통용된다.2
MQTT의 발전 과정에서 중요한 전환점은 2010년, IBM이 MQTT 버전 3.1을 모든 사용자가 자유롭게 구현할 수 있는 개방형 무료 프로토콜로 공개한 것이다.2 이 결정은 MQTT가 특정 기업의 소유물을 넘어, 전 세계 개발자 커뮤니티와 산업계가 함께 발전시키는 공개 표준으로 나아가는 발판이 되었다. 이후 프로토콜의 체계적인 유지보수와 발전을 위해 2013년, 구조화된 정보 표준의 발전을 위한 기구인 OASIS(Organization for the Advancement of Structured Information Standards)에 표준으로 제출되었고, 이는 MQTT가 공식적인 국제 표준으로 자리매김하는 계기가 되었다.1 2019년에는 현대적인 IoT 환경의 복잡한 요구사항을 반영하여 공유 구독, 세션 만료, 이유 코드 등 다양한 기능이 대폭 개선된 MQTT 버전 5.0이 발표되면서 프로토콜의 기능성과 확장성은 한 단계 더 도약하였다.2
MQTT의 가장 근본적인 설계 철학은 발행-구독(Publish-Subscribe) 모델에 있다. 이는 전통적인 클라이언트-서버(Client-Server) 구조의 요청-응답(Request-Response) 모델과는 근본적으로 다른 통신 패러다임을 제시한다.2 요청-응답 모델에서는 클라이언트가 서버의 특정 주소(Endpoint)를 명확히 알고 직접 연결하여 데이터를 요청하고 응답을 기다린다. 이는 클라이언트와 서버 간의 강한 결합(tight coupling)을 전제로 하며, 한쪽의 장애가 다른 쪽에 직접적인 영향을 미치는 구조적 한계를 지닌다.
반면, MQTT의 발행-구독 모델은 ‘메시지 브로커(Message Broker)’라는 제3의 중개자를 통신 아키텍처의 중심에 둔다.2 이 모델에서 메시지를 보내는 주체인 ‘발행자(Publisher)’와 메시지를 받는 주체인 ‘구독자(Subscriber)’는 서로의 존재를 전혀 알지 못한다. 발행자는 특정 주제(Topic)에 대한 메시지를 브로커에게 보내는 것으로 자신의 임무를 다하며, 구독자는 자신이 관심 있는 주제를 브로커에게 등록해 놓음으로써 해당 주제에 대한 메시지를 수신한다. 모든 메시지 흐름은 브로커가 전적으로 중개한다.5
이러한 중개 구조는 시스템 구성요소 간의 세 가지 핵심적인 ‘분리(Decoupling)’를 가능하게 하며, 이는 MQTT 기반 시스템의 유연성, 확장성, 그리고 회복탄력성(Resilience)의 근간을 이룬다.2
이 세 가지 분리 원칙은 단순히 기술적 특징을 넘어선다. 이는 시스템 아키텍처에 본질적인 회복탄력성을 부여하는 철학적 기반이 된다. 강하게 결합된 시스템에서는 하나의 구성요소의 장애가 연쇄적으로 다른 구성요소의 장애를 유발할 수 있다. 예를 들어, HTTP 기반 시스템에서 서버가 다운되면 클라이언트는 직접적으로 오류를 처리하고 재시도 로직을 수행해야 한다. 그러나 MQTT 기반 시스템에서는 발행자가 오프라인이 되어도 구독자는 단순히 새로운 데이터를 받지 못할 뿐 시스템 자체가 중단되지는 않는다. 반대로 구독 애플리케이션에 장애가 발생하더라도 발행자는 아무런 영향을 받지 않고 계속해서 데이터를 브로커로 전송할 수 있다. 이 구조에서 브로커는 각 구성요소의 가용성 문제나 연결 상태 변화에 대한 ‘충격 흡수 장치(shock absorber)’ 역할을 수행한다. 결과적으로, MQTT는 메시지를 전송하는 단순한 프로토콜을 넘어, 본질적으로 견고하고 확장 가능하며 장애에 유연하게 대처할 수 있는 분산 시스템을 구축하기 위한 강력한 아키텍처 패턴을 제공한다.
MQTT 프로토콜의 아키텍처는 세 가지 핵심적인 역할로 구성된다: 발행자(Publisher), 구독자(Subscriber), 그리고 브로커(Broker). 이들의 상호작용은 발행-구독 모델의 근간을 이룬다.
MQTT 클라이언트 (Client): MQTT 클라이언트는 프로토콜의 양 끝단에 위치하는 주체로, 네트워크를 통해 MQTT를 사용하여 통신하는 모든 디바이스나 애플리케이션을 포괄하는 용어다.6 클라이언트는 역할에 따라 발행자 또는 구독자가 될 수 있으며, 때로는 두 역할을 동시에 수행하기도 한다. 예를 들어, 스마트 홈의 온도 센서는 온도 데이터를 발행하는 발행자 역할을 수행하고, 동시에 원격 제어 명령을 수신하기 위해 특정 토픽을 구독하는 구독자 역할도 할 수 있다. MQTT 클라이언트는 리소스가 풍부한 서버부터 극도로 제한된 성능을 가진 소형 마이크로컨트롤러에 이르기까지 매우 광범위한 하드웨어 스펙트럼에 걸쳐 구현될 수 있다.3
MQTT 브로커 (Broker): 브로커는 MQTT 아키텍처의 심장부로서, 모든 메시지 트래픽을 중개하는 중앙 서버 시스템이다.6 브로커는 단순히 메시지를 전달하는 역할을 넘어, MQTT 시스템의 전체적인 상태와 흐름을 관리하는 복합적인 기능을 수행한다. 브로커의 핵심 책임은 다음과 같다 6:
이처럼 브로커는 발행자와 구독자 사이의 직접적인 연결을 차단하고 모든 통신을 중재하는 ‘중개인(Broker)’의 역할에 충실하기 때문에, 단순히 ‘서버’라고 부르기보다는 그 기능적 특성을 강조하여 ‘브로커’로 지칭하는 것이 일반적이다.8
메시지 흐름: MQTT 시스템에서의 데이터 흐름은 명확하고 단순한 경로를 따른다. 발행자는 특정 토픽(예: home/livingroom/temperature)에 메시지(예: 23.5)를 담아 브로커에게 발행(Publish)한다.9 브로커는 이 메시지를 수신한 뒤, home/livingroom/temperature 토픽을 구독(Subscribe)하고 있는 모든 클라이언트(예: 스마트폰 앱, 데이터베이스 로거)에게 해당 메시지를 전달한다.6 이 과정에서 발행자와 구독자는 서로를 전혀 인지하지 못하며, 오직 브로커와의 통신만을 수행한다. 이는 시스템의 각 구성요소가 독립적으로 동작하고 확장될 수 있는 기반을 제공한다.
MQTT 클라이언트와 브로커 간의 모든 상호작용은 신뢰성 있는 양방향 연결을 제공하는 TCP/IP 프로토콜 위에서 이루어진다.1 통신을 시작하기 위해 클라이언트는 먼저 브로커와의 TCP 연결을 수립한 후, MQTT 프로토콜 레벨의 연결 설정을 위한 핸드셰이크(handshake) 과정을 거친다.
CONNECT 패킷 전송: 클라이언트는 브로커에게 CONNECT 메시지를 전송하여 MQTT 세션의 시작을 요청한다.6 이 패킷은 단순한 연결 요청 이상의 의미를 가지며, 세션의 동작 방식을 결정하는 중요한 파라미터들을 포함한다.
true이면, 클라이언트는 새로운 세션을 시작하며 브로커는 이전 세션 정보를 모두 폐기한다. false이면, 브로커는 동일한 Client ID를 가진 이전 세션이 존재할 경우 이를 재개하려고 시도한다.PINGREQ 패킷을 보내고, 브로커는 PINGRESP로 응답하여 연결 상태를 확인한다.CONNACK 패킷 수신: 브로커는 클라이언트의 CONNECT 요청을 처리한 후, 그 결과를 CONNACK (Connection Acknowledgement) 메시지로 응답한다.6
CONNACK 패킷에는 클라이언트가 요청한 세션(Clean Start=false)이 브로커에 존재하여 재개되었는지 여부를 나타내는 플래그가 포함된다. 이를 통해 클라이언트는 이전 구독을 다시 할 필요가 있는지 판단할 수 있다.이 CONNECT-CONNACK 핸드셰이크 과정이 성공적으로 완료되어야만, 클라이언트는 메시지를 발행하거나 토픽을 구독하는 등의 후속 MQTT 작업을 수행할 수 있다.
MQTT에서 토픽은 메시지를 분류하고 라우팅하는 핵심적인 메커니즘이다. 이는 단순한 문자열 레이블을 넘어, 시스템 전체의 데이터 흐름을 구조화하는 역할을 수행한다. 토픽은 슬래시(/) 문자를 구분자로 사용하여 파일 시스템의 디렉터리 경로와 유사한 계층적 구조(hierarchical structure)를 가진다.5 예를 들어, 특정 건물의 특정 층에 있는 특정 방의 온도 센서 데이터는 building_A/floor_3/room_301/temperature와 같은 토픽으로 표현될 수 있다.
이러한 계층적 네임스페이스는 다음과 같은 중요한 설계상의 이점을 제공한다.
building_A/floor_3/#를 구독하면 3층의 모든 센서 데이터를 한 번에 수신할 수 있다.building_A/#)에 대한 모든 데이터에 접근 권한을 가질 수 있고, 다른 사용자는 특정 센서(building_A/floor_1/room_101/humidity)에만 접근하도록 제한할 수 있다.이처럼 MQTT의 토픽 네임스페이스는 단순한 주소 지정 체계를 넘어, 시스템 전체의 데이터 스키마(schema) 역할을 암묵적으로 수행한다. 데이터베이스 설계에서 스키마가 데이터의 구조와 관계를 정의하듯이, MQTT 시스템에서는 잘 설계된 토픽 네임스페이스가 데이터의 논리적, 물리적 계층을 정의하고 데이터의 발견 가능성(discoverability)과 관리 용이성을 결정한다. 따라서 대규모 MQTT 시스템을 설계할 때 토픽 네임스페이스를 어떻게 구조화할 것인가는 초기에 신중하게 결정해야 할 가장 중요한 아키텍처적 결정 중 하나이다. 잘 설계된 네임스페이스는 그 자체로 시스템을 설명하는 문서가 되며, 시스템의 확장성과 유지보수성을 크게 향상시킨다. 반면, 일관성 없는 토픽 구조는 구독의 모호성을 유발하고, 비효율적인 와일드카드 사용으로 인한 브로커의 성능 저하, 그리고 복잡한 접근 제어 규칙을 초래할 수 있다.
MQTT의 강력함은 와일드카드를 이용한 유연한 구독 기능에서 두드러진다. 구독자는 특정 토픽을 명시적으로 구독하는 것 외에도, 두 종류의 와일드카드 문자를 사용하여 여러 토픽을 포괄하는 패턴을 구독할 수 있다. 단, 와일드카드는 구독(SUBSCRIBE) 시에만 사용 가능하며, 발행(PUBLISH) 시 토픽 이름에는 사용할 수 없다.10
단일 레벨 와일드카드 (+): 이 와일드카드는 토픽 계층에서 정확히 하나의 레벨을 대체한다.5 이는 특정 위치에 어떤 문자열이 오든 상관없이 매칭하되, 해당 레벨이 반드시 존재해야 함을 의미한다.
usa/ca/+/temperature일 경우, 이는 usa/ca/sanjose/temperature와 usa/ca/losangeles/temperature 토픽에 발행된 메시지를 모두 수신한다.usa/ca/temperature (중간 레벨 부재) 또는 usa/ca/sanjose/downtown/temperature (레벨 개수 불일치)와는 매칭되지 않는다.12+는 토픽 레벨의 경계인 / 사이에 위치해야 하며, sport+와 같이 다른 문자와 섞여 사용될 경우 와일드카드로 인식되지 않는다.10다중 레벨 와일드카드 (#): 이 와일드카드는 자기 자신을 포함하여 하위의 모든 토픽 레벨을 대체한다. 이는 0개 이상의 레벨과 매칭될 수 있으며, 반드시 토픽 필터의 가장 마지막 문자로 사용되어야 한다.5
usa/ca/#일 경우, 이는 usa/ca/sanjose/temperature, usa/ca/losangeles/humidity/sensor1, 그리고 usa/ca 자체에 발행된 메시지까지 모두 수신한다 (#가 0개의 레벨을 대표하는 경우).10#는 토픽 필터의 중간에 위치할 수 없다. 예를 들어, usa/#/temperature는 유효하지 않은 토픽 필터이다.시스템 토픽 예외: 브로커의 내부 상태나 통계 정보를 제공하기 위해 예약된 $SYS와 같은 특수 토픽들은 일반적으로 와일드카드 구독(+ 또는 #)의 대상에서 제외된다.13 이는 사용자가 의도치 않게 대량의 시스템 메시지를 수신하여 클라이언트나 네트워크에 부하를 주는 것을 방지하기 위함이다.
$SYS 토픽을 구독하려면 $SYS/#와 같이 명시적으로 구독해야 한다.
와일드카드를 활용한 구독 전략은 시스템의 효율성과 확장성을 크게 향상시킨다. 예를 들어, 새로운 센서가 usa/ca/sandiego/temperature라는 토픽으로 데이터를 발행하기 시작했을 때, usa/ca/+/temperature를 구독하고 있는 기존의 애플리케이션은 아무런 변경 없이 새로운 센서의 데이터를 즉시 수신할 수 있다. 이는 새로운 데이터 소스를 시스템에 동적으로 추가하고 통합하는 과정을 매우 단순하게 만들어준다.
MQTT는 네트워크의 신뢰도와 메시지의 중요성에 따라 전송 품질을 선택할 수 있도록 세 단계의 서비스 품질(Quality of Service, QoS) 레벨을 정의한다. 이는 불안정한 네트워크 환경에서도 데이터의 신뢰성을 보장하기 위한 핵심적인 메커니즘이다.8
QoS 0은 “최대 한 번” 전송을 의미하며, “쏘고 잊어버리기(Fire and Forget)” 방식으로 동작한다.1
QoS 1은 “최소 한 번” 전송을 보장하며, 가장 널리 사용되는 서비스 레벨이다.17
전송 특성: 발행자는 메시지가 수신자(브로커)에게 최소 한 번은 확실히 전달되는 것을 보장받는다.1 이를 위해 2단계 핸드셰이크(2-way handshake) 과정을 거친다.
PUBLISH: 발행자는 고유한 패킷 식별자(Packet Identifier)를 포함한 PUBLISH 패킷을 브로커에게 전송한다. 이후 발행자는 PUBACK 패킷을 수신할 때까지 원본 PUBLISH 패킷을 내부에 저장한다.17PUBACK: 브로커는 PUBLISH 패킷을 성공적으로 수신하면, 동일한 패킷 식별자를 포함한 PUBACK (Publish Acknowledge) 패킷을 발행자에게 응답한다.21재전송 및 중복 가능성: 만약 발행자가 일정 시간 내에 PUBACK 패킷을 수신하지 못하면(예: PUBACK 패킷이 네트워크에서 유실된 경우), 발행자는 메시지가 전달되지 않았다고 판단하고 저장해 두었던 PUBLISH 패킷을 다시 전송한다. 이때 재전송되는 패킷에는 중복된 메시지임을 나타내는 DUP(Duplicate) 플래그가 설정된다.17 브로커는 이미 첫 번째
PUBLISH 패킷을 받고 처리했음에도 불구하고, 재전송된 PUBLISH 패킷을 새로운 메시지로 받아 다시 처리할 수 있다. 이로 인해 최종 구독자는 동일한 메시지를 여러 번 수신할 수 있는 가능성이 생긴다.16
적합한 사용 사례:
QoS 2는 “정확히 한 번” 전송을 보장하는 가장 높은 신뢰도 수준의 서비스이다.1
PUBLISH: 발행자는 패킷 ID를 포함한 PUBLISH 패킷을 브로커에게 보내고, 해당 패킷을 저장한다.PUBREC (Publish Received): 브로커는 PUBLISH 패킷을 수신하고 패킷 ID를 저장한 후, PUBREC 패킷으로 응답한다. 이 시점에서 브로커는 메시지를 수신했지만 아직 구독자에게 전달하지는 않는다.PUBREL (Publish Release): 발행자는 PUBREC 패킷을 수신하면, 저장해 두었던 원본 PUBLISH 패킷을 폐기하고, 대신 PUBREL 패킷을 저장한 후 브로커에게 전송한다. 이는 발행자가 브로커의 수신을 확인했음을 알리는 신호이다.PUBCOMP (Publish Complete): 브로커는 PUBREL 패킷을 수신하면, 저장하고 있던 메시지를 최종적으로 처리(구독자에게 전달)하고 관련 상태를 모두 삭제한다. 그리고 발행자에게 PUBCOMP 패킷을 보내 모든 과정이 완료되었음을 알린다. 발행자는 PUBCOMP를 수신하면 저장했던 PUBREL 패킷을 폐기한다.메시지가 구독자에게 최종적으로 전달될 때 적용되는 QoS 레벨은 발행자가 설정한 QoS와 구독자가 구독 시 요청한 QoS 중 더 낮은 값으로 결정된다는 점을 이해하는 것이 중요하다.17 예를 들어, 발행자가 중요한 경보를 QoS 2로 발행했더라도, 실시간 대시보드 역할을 하는 구독자가 성능을 위해 QoS 0으로 구독했다면 브로커는 해당 구독자에게 메시지를 QoS 0으로 전달한다. 반면, 모든 경보를 기록해야 하는 다른 구독자가 QoS 1로 구독했다면, 브로커는 이 구독자에게는 QoS 1로 메시지를 전달한다.
이러한 QoS 하향 조정(downgrading) 메커니즘은 MQTT의 분리(decoupling) 철학을 강화하는 강력한 기능이다. 이는 데이터 생산자의 신뢰성 요구사항과 데이터 소비자의 신뢰성 요구사항을 분리시킨다. 발행자는 데이터의 고유한 중요도에 따라 QoS를 결정하고, 각 소비자는 자신의 애플리케이션 로직과 성능 요구사항에 맞춰 최적의 신뢰도 수준을 독립적으로 선택할 수 있다. 이로 인해 단일 데이터 소스가 다양한 신뢰도 요구를 가진 여러 애플리케이션에 동시에 서비스를 제공할 수 있게 되어, 시스템 전체의 유연성과 효율성이 극대화된다.
MQTT는 단순히 메시지를 전달하는 것을 넘어, 클라이언트의 상태를 관리하고 불안정한 네트워크 환경에서도 데이터의 연속성을 보장하기 위한 정교한 메커니즘을 제공한다.
LWT(Last Will and Testament, 유언)는 클라이언트의 비정상적인 연결 종료를 감지하고 다른 시스템 구성원들에게 이를 알리는 강력한 기능이다.26
동작 원리: 클라이언트는 브로커에 처음 연결(CONNECT)할 때, ‘유언’으로 남길 메시지를 미리 등록할 수 있다. 이 유언 정보에는 메시지가 발행될 토픽(Will Topic), 메시지 내용(Will Payload), QoS 레벨, 그리고 Retain 플래그가 포함된다.27 이후 클라이언트가 정상적인
DISCONNECT 메시지를 보내지 않고 연결이 끊어지는 경우(예: 네트워크 장애, 장치 전원 차단, Keep Alive 시간 초과 등), 브로커는 해당 클라이언트를 대신하여 등록된 유언 메시지를 지정된 토픽으로 발행한다.7 클라이언트가 정상적으로 연결을 종료하면, 브로커는 등록된 유언 메시지를 폐기한다.26
활용: LWT는 주로 클라이언트의 온라인/오프라인 상태를 모니터링하는 데 사용된다. 예를 들어, 한 클라이언트는 연결 시 devices/client1/status 토픽에 "offline"이라는 유언 메시지를 등록하고, 연결 성공 직후 동일한 토픽에 "online" 메시지를 발행한다. 이렇게 하면 다른 클라이언트들은 devices/client1/status 토픽을 구독함으로써 해당 클라이언트의 상태를 실시간으로 파악할 수 있다. 갑작스러운 연결 종료 시 브로커가 "offline" 메시지를 발행해주기 때문이다.26
Retained Message(보관 메시지)는 특정 토픽의 가장 최근 상태 값을 브로커에 저장하여, 새로운 구독자가 즉시 해당 상태를 알 수 있도록 하는 기능이다.29
RETAIN 플래그를 true로 설정하면, 브로커는 해당 메시지를 해당 토픽의 ‘보관 메시지’로 저장한다. 브로커는 토픽당 오직 하나의 보관 메시지만을 유지하며, 새로운 보관 메시지가 도착하면 이전 메시지를 덮어쓴다.29 이후 어떤 클라이언트가 해당 토픽(또는 매칭되는 와일드카드 토픽)을 구독하면, 구독 요청과 거의 동시에 브로커는 저장된 보관 메시지를 즉시 전달해준다.30home/livingroom/temperature 토픽에 RETAIN 플래그를 켜고 현재 온도를 발행하면, 나중에 스마트 홈 대시보드가 켜져서 이 토픽을 구독하는 순간, 가장 최근에 측정된 온도 값을 즉시 화면에 표시할 수 있다.29 보관 메시지를 삭제하고 싶을 때는 해당 토픽에 길이가 0인(zero-byte) 페이로드를 가진 보관 메시지를 발행하면 된다.29LWT와 Retained Message를 함께 사용하면 매우 효율적이고 견고한 상태 관리 패턴을 구축할 수 있다. 앞선 LWT 예시에서 유언 메시지("offline")와 정상 상태 메시지("online")를 모두 RETAIN 플래그를 켜서 발행하도록 구성하는 것이 핵심이다.26 장치가 연결될 때
devices/123/status 토픽에 "online"이라는 보관 메시지를 남기고, 비정상 종료 시 브로커가 "offline"이라는 보관 메시지를 남기도록 LWT를 설정한다. 이렇게 하면 언제 어떤 애플리케이션이 devices/123/status 토픽을 구독하더라도, 항상 해당 장치의 가장 최신 온라인/오프라인 상태를 즉시 전달받을 수 있다.29
이 패턴은 장치의 상태 정보를 브로커 자체에 외부화(externalize)하는 효과를 가져온다. 즉, 브로커가 장치 상태에 대한 ‘단일 진실 공급원(Single Source of Truth)’ 역할을 하게 된다. 이는 상태 모니터링 로직을 장치의 운영 로직과 완벽하게 분리하는 강력한 아키텍처 패턴이다. 애플리케이션은 더 이상 장치가 온라인 상태인지 확인하기 위해 복잡한 핑퐁(ping-pong)이나 타임아웃 로직을 구현할 필요가 없다. 단순히 상태 토픽을 구독하고 브로커가 제공하는 현재 상태 정보를 신뢰하기만 하면 된다. 이는 애플리케이션 개발을 크게 단순화하고 시스템 전반의 상황 인지 능력을 향상시킨다.
영구 세션은 클라이언트가 오프라인 상태일 때도 구독 정보와 중요 메시지를 보존하여 통신의 연속성을 보장하는 핵심 기능이다.
동작 원리: 클라이언트가 CONNECT 패킷의 Clean Session 플래그(MQTT v3.1.1) 또는 Clean Start 플래그(MQTT v5.0)를 false로 설정하고 연결하면, 브로커는 해당 클라이언트 ID에 대한 세션 정보를 유지한다.4 클라이언트가 연결을 끊더라도 브로커는 다음 정보를 삭제하지 않고 보관한다:
PUBACK, PUBCOMP)받지 못한 QoS 1 및 QoS 2 메시지.세션 재개: 클라이언트가 나중에 동일한 클라이언트 ID와 Clean Start=false 설정으로 재연결하면, 브로커는 저장된 세션을 찾아 복원한다. 그리고 큐에 쌓여 있던 메시지들을 클라이언트에게 전달하기 시작한다.33 이는 불안정한 모바일 네트워크 환경에서 디바이스가 잠시 연결이 끊겼다가 다시 연결될 때 메시지 유실 없이 통신을 재개할 수 있게 해준다.25 만약
Clean Start=true로 연결하면, 브로커는 이전 세션 정보를 모두 삭제하고 완전히 새로운 세션을 시작한다.33
이 세 가지 기능(LWT, Retained Message, Persistent Session)은 MQTT가 단순한 메시지 전송 프로토콜을 넘어, 상태를 인지하고 관리하며, 불안정한 환경에서도 신뢰성을 유지하는 정교한 통신 프레임워크임을 보여주는 핵심 요소들이다
2019년에 발표된 MQTT 버전 5.0은 이전 버전인 v3.1.1의 성공을 기반으로, 대규모 IoT 시스템의 복잡성과 현대적인 애플리케이션의 요구사항을 해결하기 위한 중요한 기능들을 대거 도입했다. 이는 단순한 업데이트를 넘어, 프로토콜의 표현력과 견고함을 한 차원 높인 진화로 평가받는다.35
MQTT v3.1.1의 영구 세션(Clean Session=false)은 강력한 기능이었지만, 한 가지 중요한 단점을 가지고 있었다. 클라이언트가 영원히 돌아오지 않을 경우, 해당 세션 정보와 큐에 쌓인 메시지들이 브로커에 무기한으로 남아 시스템 자원을 점유하는 문제가 있었다.35
MQTT v5.0은 Session Expiry Interval이라는 새로운 속성을 도입하여 이 문제를 해결했다.38
CONNECT 패킷을 보낼 때, 연결이 끊어진 후 세션을 얼마나 오래 유지할지를 초 단위로 지정할 수 있다.0 또는 미지정: 세션은 연결이 끊어지는 즉시 만료된다. 이는 v3.1.1의 Clean Session=true와 동일한 동작이다.0xFFFFFFFF (무한대): 세션이 절대 만료되지 않도록 설정한다.이 기능은 브로커가 불필요한 세션 데이터를 영구적으로 보관하는 것을 방지하여 리소스 관리를 효율화하고, 시스템의 안정성을 높이는 데 크게 기여한다.35
MQTT v3.1.1의 또 다른 한계는 오류 처리의 모호성이었다. 예를 들어, 클라이언트의 연결 요청이 거부될 경우, CONNACK 패킷은 ‘수락되지 않음’이라는 포괄적인 반환 코드만을 제공할 뿐, 그 구체적인 원인(예: 잘못된 프로토콜 버전, 인증 실패, 서버 사용 불가 등)을 알려주지 않았다. 이로 인해 개발자는 문제의 원인을 파악하고 디버깅하는 데 어려움을 겪었다.
MQTT v5.0은 거의 모든 응답 패킷(CONNACK, PUBACK, SUBACK, UNSUBACK, DISCONNECT 등)에 Reason Code 필드를 추가하여 이 문제를 해결했다.37
SUBSCRIBE)이 실패했을 때, 브로커는 ‘구현 특정 오류’, ‘권한 없음’, ‘토픽 필터가 유효하지 않음’ 등의 이유 코드를 SUBACK 패킷에 담아 보낼 수 있다.4PUBACK이나 PUBREC 패킷에도 성공(0) 외의 이유 코드를 포함할 수 있게 되었다. 예를 들어, QoS 1 메시지를 수신했지만 처리할 권한이 없는 경우, 브로커는 ‘권한 없음’ 이유 코드를 담은 PUBACK을 보낼 수 있다. 이를 ‘부정 응답’이라 하며, 발행자는 이를 통해 메시지 전송 실패 원인을 즉시 파악하고 적절한 조치를 취할 수 있다.4이러한 개선 사항은 MQTT 기반 시스템의 디버깅 용이성과 운영 안정성을 크게 향상시켰다. 개발자는 더 이상 로그 파일을 뒤지거나 추측에 의존하지 않고도, 프로토콜 수준에서 제공되는 명확한 피드백을 통해 문제 상황에 신속하고 정확하게 대응할 수 있게 되었다.35
표 1: MQTT 버전별 핵심 기능 비교 (v3.1.1 vs v5.0)
| 기능 분류 | 세부 기능 | MQTT v3.1.1 | MQTT v5.0 | 주요 변경점 및 의의 |
|---|---|---|---|---|
| 세션 관리 | 세션 지속성 | Clean Session 플래그 (boolean) |
Clean Start 플래그 + Session Expiry Interval (integer) |
영구 세션의 유효 기간을 지정하여 브로커의 리소스 관리를 최적화하고, 좀비 세션 문제를 해결함.35 |
| 오류 처리 | 피드백 메커니즘 | 제한된 반환 코드 (예: CONNACK) | 모든 ACK 패킷에 Reason Code 도입, DISCONNECT 패킷에 이유 코드 추가 |
연결 실패, 발행/구독 거부 등의 원인을 명확하게 전달하여 디버깅 및 오류 처리 로직을 크게 개선함.37 |
| 메시지 속성 | 메타데이터 | 없음 (페이로드에 포함해야 함) | User Properties (사용자 정의 키-값 쌍) |
페이로드를 파싱하지 않고도 메시지 라우팅, 필터링 등 고급 로직 구현이 가능해져 시스템 간 상호운용성 증대.35 |
| 메시지 만료 | 없음 | Message Expiry Interval |
더 이상 유효하지 않은 메시지(예: 시한성 명령)가 오프라인 클라이언트에게 전달되는 것을 방지하여 데이터의 적시성 보장.4 | |
| 페이로드 정보 | 없음 | Payload Format Indicator, Content Type |
페이로드가 바이너리인지 UTF-8 텍스트인지, 그리고 어떤 형식(예: application/json)인지 명시하여 수신 측의 처리 로직을 단순화함.39 | |
| 구독 옵션 | 공유 구독 | 없음 (일부 브로커에서 비표준 지원) | 표준 기능으로 도입 ($share/...) |
여러 구독자가 하나의 구독을 공유하며 메시지를 분산 처리(로드 밸런싱)할 수 있어, 백엔드 시스템의 확장성을 프로토콜 수준에서 지원함.35 |
| 로컬 발행 방지 | 없음 | No Local 구독 옵션 |
클라이언트가 자신이 발행한 메시지를 다시 수신하지 않도록 설정 가능. 불필요한 루프백(loopback) 트래픽을 방지함.40 | |
| 통신 패턴 | 요청-응답 | 없음 (애플리케이션 수준에서 구현) | Response Topic, Correlation Data 속성 지원 |
요청-응답 패턴을 프로토콜 수준에서 공식적으로 지원하여, RPC(Remote Procedure Call)와 같은 상호작용 구현을 용이하게 함.4 |
| 성능 최적화 | 토픽 이름 | 매번 전체 토픽 이름 전송 | Topic Alias |
긴 토픽 이름을 짧은 정수 별칭으로 대체하여 전송함으로써, 네트워크 대역폭 사용량을 크게 절감함.4 |
| 흐름 제어 | 없음 | Receive Maximum, Maximum Packet Size |
클라이언트와 브로커가 한 번에 처리할 수 있는 미확인 QoS 1/2 메시지 수와 최대 패킷 크기를 서로에게 알려, 과부하를 방지하고 안정적인 통신을 유지함.4 |
전통적인 MQTT 구독 모델에서는 특정 토픽을 구독하는 모든 클라이언트가 해당 토픽에 발행된 모든 메시지의 복사본을 수신한다. 이는 정보 방송에는 유용하지만, 여러 백엔드 애플리케이션이 동일한 데이터 스트림을 병렬로 처리해야 하는 시나리오에서는 비효율적이다. 모든 애플리케이션이 동일한 메시지를 중복으로 처리하게 되기 때문이다.
MQTT v5.0은 이 문제를 해결하기 위해 ‘공유 구독’을 표준 기능으로 도입했다.35
동작 원리: 공유 구독은 여러 구독 클라이언트가 논리적인 ‘구독 그룹’을 형성하여 하나의 구독을 공유하도록 한다. 특정 토픽에 메시지가 도착하면, 브로커는 해당 구독 그룹 내의 단 하나의 클라이언트에게만 메시지를 전달한다.43 메시지를 분배하는 방식은 브로커 구현에 따라 다르지만, 일반적으로 라운드 로빈(Round-robin) 또는 다른 부하 분산 알고리즘을 사용한다.43
토픽 형식: 공유 구독을 사용하기 위해서는 특별한 형식의 토픽 필터를 사용해야 한다 43:
$share/{GroupID}/{TopicFilter}
$share: 이 구독이 공유 구독임을 나타내는 고정된 접두사이다.{GroupID}: 구독 그룹을 식별하는 문자열이다. 동일한 GroupID를 사용하는 클라이언트들이 하나의 그룹으로 묶여 메시지를 분산 처리하게 된다.{TopicFilter}: 실제 구독하고자 하는 토픽 필터(와일드카드 포함 가능)이다.worker_pool_1이라는 그룹에 속한 여러 애플리케이션이 telemetry/+/temperature 토픽의 데이터를 처리하고자 할 때, 모든 애플리케이션은 $share/worker_pool_1/telemetry/+/temperature를 구독한다.효과: 이 기능은 애플리케이션 수준에서 복잡한 부하 분산 로직을 구현할 필요 없이, 프로토콜 수준에서 메시지 처리 부하를 여러 소비자에게 분산시킬 수 있게 해준다. 이를 통해 백엔드 시스템의 수평적 확장(horizontal scaling)과 내결함성(fault tolerance)을 매우 간단하게 구현할 수 있다.37
MQTT v3.1.1에서는 메시지의 페이로드(payload) 외에 추가적인 정보를 전달할 표준화된 방법이 없었다. 모든 메타데이터는 페이로드 내부에 포함되어야 했고, 이는 수신 측에서 페이로드를 파싱해야만 해당 정보를 얻을 수 있음을 의미했다.
MQTT v5.0의 ‘사용자 속성’은 이 한계를 극복한다. 이는 HTTP 헤더와 매우 유사한 개념으로, 거의 모든 종류의 MQTT 패킷(CONNECT, PUBLISH, SUBSCRIBE 등)에 사용자 정의 키-값(key-value) 쌍 형태의 메타데이터를 추가할 수 있도록 허용한다.4
Content-Type: application/json, payload-encoding: base64, message-origin: factory-A와 같은 속성을 추가하여 수신자가 메시지를 어떻게 처리해야 할지 미리 알 수 있게 한다.39사용자 속성은 MQTT 프로토콜의 유연성과 확장성을 크게 향상시켜, 다양한 시스템 간의 상호운용성을 높이는 중요한 역할을 한다.
MQTT는 본질적으로 비동기적인 발행-구독 프로토콜이지만, 실제 애플리케이션에서는 동기적인 요청-응답 패턴이 필요한 경우가 많다. MQTT v5.0은 이를 프로토콜 수준에서 지원하기 위해 두 가지 새로운 속성을 도입했다.
Response Topic: 요청을 보내는 클라이언트(requester)가 PUBLISH 패킷에 이 속성을 포함시켜, 응답을 받을 토픽의 이름을 명시적으로 지정한다.Correlation Data: 요청자는 요청을 식별할 수 있는 고유한 데이터(예: 요청 ID)를 이 속성에 담아 보낸다. 응답자(responder)는 응답 메시지를 보낼 때 이 Correlation Data를 그대로 포함하여 반환해야 한다.PUBLISH 패킷에 처리할 작업 내용(페이로드), 응답을 받을 Response Topic, 그리고 요청을 식별할 Correlation Data를 담아 특정 요청 토픽으로 발행한다.Response Topic으로 응답 메시지를 발행한다. 이때 반드시 원본 요청의 Correlation Data를 함께 포함시킨다.Response Topic을 구독하고 있다가 응답을 수신하고, Correlation Data를 확인하여 어떤 요청에 대한 응답인지 식별한다.이 메커니즘은 MQTT를 통해 원격 프로시저 호출(RPC)과 같은 상호작용을 표준화되고 안정적인 방식으로 구현할 수 있게 해준다.4
MQTT v5.0에 도입된 이러한 새로운 기능들(공유 구독, 사용자 속성, 이유 코드 등)은 MQTT를 단순한 원격 측정 데이터 전송 프로토콜에서 복잡한 대규모 엔터프라이즈 통합을 위한 정교한 메시징 프레임워크로 변모시켰다. v3.1.1에서는 애플리케이션 수준에서 복잡하게 구현해야 했던 부하 분산, 메타데이터 전달, 명확한 오류 처리와 같은 공통적인 메시징 패턴과 운영상의 문제들이 이제 프로토콜 자체에 내장되었다. 이는 서로 다른 시스템 간의 상호운용성을 크게 향상시키고, 개발자가 비즈니스 로직에 더 집중할 수 있도록 하여, 결과적으로 더 빠르고 안정적인 IoT 시스템 통합을 가능하게 한다.
MQTT는 사물 인터넷(IoT) 통신 프로토콜 생태계에서 독보적인 위치를 차지하고 있지만, 유일한 선택지는 아니다. 특정 사용 사례와 요구사항에 따라 다른 프로토콜이 더 적합할 수 있다. MQTT의 기술적 특성과 위상을 명확히 이해하기 위해, 주요 통신 프로토콜인 HTTP, CoAP, AMQP와의 비교 분석을 수행한다.
MQTT와 HTTP는 웹 및 IoT 환경에서 가장 널리 언급되는 프로토콜이지만, 그 설계 철학과 동작 방식은 근본적으로 다르다.
CoAP(Constrained Application Protocol)는 MQTT와 마찬가지로 자원이 극도로 제한된(constrained) 장치와 네트워크를 위해 설계된 프로토콜이지만, 다른 기술적 접근 방식을 취한다.
GET, POST, PUT, DELETE와 같은 메소드를 사용한다. 또한, 리소스 관찰(Observe) 옵션을 통해 특정 리소스의 상태가 변경될 때마다 서버가 클라이언트에게 알림을 보내는 발행-구독과 유사한 기능을 제공할 수 있다.51AMQP(Advanced Message Queuing Protocol)는 주로 엔터프라이즈 환경의 안정적인 비동기 메시징을 위해 설계된 프로토콜로, MQTT와는 지향하는 목표와 복잡성에서 큰 차이를 보인다.
이러한 비교 분석을 통해, 각 프로토콜이 모든 시나리오에 적합한 만능 해결책이 아님을 알 수 있다. 이들은 복잡성, 신뢰성, 오버헤드라는 다차원적인 스펙트럼 위에 각자의 위치를 점하고 있다. 가장 경량화된 CoAP부터, IoT의 표준으로 자리 잡은 MQTT, 웹의 표준인 HTTP, 그리고 엔터프라이즈 메시징의 강자인 AMQP에 이르기까지, 각 프로토콜은 고유한 강점과 약점을 가진다. 성공적인 시스템 아키텍트는 특정 사용 사례의 제약 조건(장치 성능, 네트워크 상태)과 요구사항(데이터 중요도, 시스템 복잡도)을 종합적으로 평가하여, 이 스펙트럼 위에서 가장 적절한 프로토콜 또는 프로토콜의 조합을 선택해야 한다. 때로는 엣지에서는 CoAP를, 클라우드 연동에는 MQTT를, 그리고 백엔드 시스템 간의 연동에는 AMQP를 사용하는 하이브리드 아키텍처가 최적의 해답이 될 수 있다.
표 2: 주요 IoT 프로토콜 비교 (MQTT vs. HTTP vs. CoAP vs. AMQP)
| 비교 기준 | MQTT | HTTP | CoAP | AMQP |
|---|---|---|---|---|
| 기본 전송 프로토콜 | TCP | TCP | UDP | TCP |
| 통신 모델 | 발행/구독 (Publish/Subscribe) | 요청/응답 (Request/Response) | 요청/응답 (Request/Response) | 교환기-큐 기반 (Exchange-Queue) |
| 헤더 오버헤드 | 매우 낮음 (최소 2바이트) | 높음 (텍스트 기반, 수십~수백 바이트) | 매우 낮음 (최소 4바이트) | 중간~높음 (바이너리, 8바이트 이상) |
| 신뢰성 보장 | 3단계 QoS (0, 1, 2) | TCP 신뢰성, 애플리케이션 재시도 | 확인/비확인 메시지 (QoS 0, 1 유사) | 확인, 트랜잭션, 영속성 등 |
| 상태 관리 | 상태 기반 (영구 세션, LWT) | 무상태 (Stateless) | 상태 기반 (Observe) | 상태 기반 (큐, 영속성) |
| 주요 사용 사례 | IoT/IIoT, M2M, 모바일 메시징 | 웹 서비스, REST API | 자원 제약이 극심한 센서 네트워크 | 엔터프라이즈 메시징, 금융 시스템 |
| 장점 | 경량, 저전력, 양방향, 높은 확장성 | 범용성, 성숙한 생태계, 개발 용이성 | 극도의 경량성, 저전력, 멀티캐스트 | 강력한 라우팅, 높은 신뢰성, 풍부한 기능 |
| 단점 | 단순한 라우팅, 트랜잭션 미지원 | 높은 오버헤드, 폴링 방식, 실시간성 부족 | 신뢰성/순서 보장 자체 구현 필요 | 복잡성, 높은 오버헤드, 리소스 요구량 |
MQTT를 실제 시스템에 성공적으로 배포하고 운영하기 위해서는 프로토콜의 보안 메커니즘을 깊이 이해하고, 대규모 트래픽을 처리하기 위한 시스템 수준의 최적화를 수행하는 것이 필수적이다.
IoT 시스템은 수많은 디바이스가 외부 네트워크에 연결되므로 보안은 가장 중요한 고려사항 중 하나이다. MQTT는 다층적인 보안 아키텍처를 구축할 수 있는 메커니즘을 제공한다.
MQTT 통신의 가장 기본적인 보안 계층은 전송 데이터 자체를 암호화하는 것이다.
전송 계층의 암호화가 안전한 통로를 확보하는 것이라면, 애플리케이션 계층의 인증과 인가는 그 통로를 이용할 자격이 있는지를 판단하고, 자격이 있는 사용자가 할 수 있는 일을 제한하는 역할을 한다.
인증 (Authentication): 인증은 ‘당신은 누구인가?’를 확인하는 과정이다. MQTT는 CONNECT 패킷에 포함된 사용자 이름(Username)과 비밀번호(Password) 필드를 통해 가장 기본적인 인증 메커니즘을 제공한다.68 브로커는 이 자격 증명을 사전에 저장된 정보와 비교하여 클라이언트의 신원을 확인한다. 앞서 언급한 mTLS를 통한 클라이언트 인증서 확인 역시 강력한 인증 방법 중 하나이다.
인가 (Authorization): 인가는 ‘당신은 무엇을 할 수 있는가?’를 결정하는 과정이다. 성공적으로 인증된 클라이언트라 할지라도, 시스템의 모든 토픽에 접근해서는 안 된다. 인가는 특정 클라이언트가 어떤 토픽에 대해 발행(publish) 또는 구독(subscribe)할 수 있는지를 제어한다. 이 기능은 대부분의 MQTT 브로커에서 ACL(Access Control Lists)을 통해 구현된다.63 ACL은 특정 클라이언트 ID나 사용자 이름에 대해 허용 또는 거부되는 토픽 패턴과 작업(읽기/쓰기)을 명시한 규칙의 목록이다.
최소 권한 원칙 (Principle of Least Privilege): 견고한 보안 시스템을 구축하기 위한 핵심 원칙은 각 구성요소에 업무 수행에 필요한 최소한의 권한만을 부여하는 것이다.63 예를 들어, 온도 센서는
devices/thermostat-01/temperature/pub 토픽에 발행(write)할 권한만 가져야 하며, 다른 토픽을 읽거나(read) 제어 명령 토픽(devices/thermostat-01/control/sub)을 구독할 권한은 없어야 한다. 마찬가지로, 온도 조절 앱은 제어 토픽에 발행하고 온도 토픽을 구독할 권한만 가져야 한다. 이 원칙을 ACL에 엄격하게 적용함으로써, 만약 하나의 디바이스가 탈취되더라도 공격자가 시스템 전체에 미칠 수 있는 피해 범위를 최소화할 수 있다.
MQTT 프로토콜 자체는 비교적 단순하고 안전하게 설계되었지만, 실제 상용 및 오픈소스 브로커 구현체에서는 다양한 보안 취약점(CVE, Common Vulnerabilities and Exposures)이 발견되어 왔다. 이러한 취약점을 분석해 보면, 대부분이 프로토콜 명세 자체의 결함이라기보다는 개발자가 명세를 구현하는 과정에서 발생한 프로그래밍 오류에 기인한다는 것을 알 수 있다.
결론적으로, MQTT 시스템의 보안은 프로토콜 명세를 지키는 것만으로는 충분하지 않다. 시스템의 보안 수준은 결국 사용된 브로커 소프트웨어 코드의 품질에 크게 좌우된다. 따라서 아키텍처 설계 단계에서의 보안 고려(TLS, 인증/인가)와 함께, 운영 단계에서의 지속적인 보안 관리(취약점 스캐닝, 패치 관리)가 동등하게 중요하다.
수백만 개의 디바이스가 동시에 연결되고 초당 수십만 건의 메시지를 처리해야 하는 대규모 IoT 시스템에서 단일 MQTT 브로커는 명백한 한계를 가진다. 이는 단일 장애점(Single Point of Failure, SPOF)이 될 뿐만 아니라, CPU, 메모리, 네트워크 대역폭 등 물리적 자원의 한계로 인해 성능 병목 현상을 유발한다. 따라서 실제 운영 환경에서는 여러 브로커 인스턴스를 묶어 클러스터(cluster)를 구성함으로써 확장성(Scalability)과 고가용성(High Availability)을 확보해야 한다.74
MQTT 브로커 클러스터링은 여러 브로커 노드가 협력하여 하나의 논리적인 브로커 서비스처럼 동작하게 하는 기술이다. 클러스터링 아키텍처는 크게 두 가지 방식으로 나눌 수 있다.
topic_A를 구독했다면, topic_A로 메시지를 발행하는 클라이언트 B가 노드 2에 연결되어 있더라도 노드 2는 이 메시지를 노드 1로 전달하여 클라이언트 A에게 도달시켜야 한다. 이를 위해 노드 간에는 세션 정보, 구독 정보, 라우팅 테이블 등이 실시간으로 동기화되어야 한다.수백만 개의 동시 MQTT 연결을 안정적으로 처리하기 위해서는 브로커 소프트웨어의 성능뿐만 아니라, 그 기반이 되는 운영체제와 네트워크 스택의 성능을 극한까지 끌어올리는 튜닝 작업이 반드시 필요하다. 특히 Linux 환경에서 다음과 같은 커널 파라미터 튜닝이 일반적으로 수행된다.
파일 디스크립터(File Descriptors) 제한 증가: Linux에서는 모든 네트워크 소켓이 파일 디스크립터로 취급된다. 기본적으로 프로세스당 또는 시스템 전체에서 열 수 있는 파일 디스크립터의 수는 제한되어 있다. 수백만 개의 클라이언트 연결을 받으려면 이 제한을 대폭 상향 조정해야 한다.85
sysctl -w fs.file-max=2097152: 시스템 전체의 최대 파일 디스크립터 수를 설정한다.86
ulimit -n 1048576: 현재 셸 세션의 프로세스가 열 수 있는 파일 디스크립터 수를 설정한다.86 영구적인 변경을 위해서는
/etc/security/limits.conf 파일을 수정해야 한다.87
TCP 네트워크 스택 튜닝: 대량의 동시 연결 요청이 들어올 때 TCP 연결 수립 과정에서 병목이 발생하지 않도록 관련 큐의 크기를 늘려야 한다.
net.core.somaxconn: 애플리케이션의 listen() 호출에 대한 연결 대기 큐(accept queue)의 최대 길이를 설정한다. 이 값이 작으면 연결 요청이 폭주할 때 클라이언트 연결이 거부될 수 있다.86net.ipv4.tcp_max_syn_backlog: TCP 3-way handshake 과정에서 SYN_RECV 상태에 있는 연결, 즉 아직 완전히 수립되지 않은 연결을 보관하는 큐(SYN queue)의 크기를 설정한다. SYN Flooding 공격에 대한 방어 및 대규모 연결 처리에 중요하다.86net.ipv4.ip_local_port_range: 클라이언트로서 외부 서버에 연결할 때 사용할 수 있는 로컬 포트의 범위를 늘려, 포트 고갈(port exhaustion) 문제를 방지한다.86네트워크 인터페이스 카드(NIC) 및 드라이버 튜닝: 최신 NIC는 하드웨어 수준에서 네트워크 처리 성능을 향상시키는 다양한 기능을 제공한다.
이러한 시스템 수준의 튜닝은 MQTT 브로커가 하드웨어의 성능을 최대한 활용하여 대규모 트래픽을 안정적으로 처리할 수 있도록 하는 기반을 마련한다.
표 3: 오픈소스 MQTT 브로커 성능 벤치마크 요약
| 벤치마크 시나리오 | 성능 지표 | EMQX (v4.4.16) | Mosquitto (v2.0.15) | 분석 |
|---|---|---|---|---|
| Point-to-Point | 메시지 처리율 (msg/s) | 50,000 | 37,000 | EMQX가 더 높은 처리율을 보이며, 대규모 1:1 통신에 강점을 나타냄.92 |
| (50k 발행자, 50k 구독자) | 평균 지연 시간 (ms) | 1.58 | 353.82 | Mosquitto는 높은 부하에서 지연 시간이 급격히 증가하여 성능 저하가 발생함.92 |
| 평균 CPU 사용률 (%) | 80% | 6% | EMQX는 더 많은 CPU 자원을 활용하여 높은 처리량을 달성하는 반면, Mosquitto는 자원 사용량이 낮지만 성능 한계에 부딪힘.92 | |
| Fan-out | 메시지 처리율 (msg/s) | 250,000 | 82,000 | 1:N 방송 시나리오에서 EMQX의 다중 코어 아키텍처가 압도적인 성능을 보임.92 |
| (5 발행자, 1000 구독자/발행자) | 평균 지연 시간 (ms) | 1.99 | 12,240.83 | Mosquitto는 Fan-out 부하가 증가하면 심각한 지연 시간 문제를 겪음.92 |
| Shared Subscription | 메시지 처리율 (msg/s) | 50,000 | 40,000 (sub) | 공유 구독을 통한 부하 분산 시나리오에서도 EMQX가 더 나은 성능을 유지함.92 |
| (50k 발행자, 500 구독자 그룹) | 평균 지연 시간 (ms) | 1.47 | 12,723.07 | Mosquitto는 높은 부하의 공유 구독 처리 시 지연 시간 문제가 발생함.92 |
| Concurrent Connections | 최대 동시 연결 수 | 1,000,000 | 1,000,000 | 두 브로커 모두 대규모 연결 수립이 가능하나, 자원 사용량에서 차이를 보임.92 |
| (1M 연결, 5k cps) | 평균 연결 지연 (ms) | 2.4 | 5.74 | EMQX가 더 빠른 연결 수립 속도를 보임.92 |
| 안정화 시 메모리 (GB) | 8.68 | 1.0 | Mosquitto는 단일 스레드 아키텍처로 인해 메모리 사용량이 현저히 낮아, 자원이 제한된 환경에 유리함.92 | |
| 아키텍처 및 확장성 | 클러스터링 | 내장 (Masterless) | 미지원 (상용 버전에서 지원) | EMQX는 오픈소스 버전에서 수평적 확장을 위한 클러스터링을 기본 지원하지만, Mosquitto는 단일 노드 운영에 초점을 맞춤.93 |
주: 위 벤치마크는 EMQ에서 수행한 결과이며, 특정 하드웨어 및 테스트 조건 하에서의 성능을 나타낸다. Mosquitto는 영속성(persistence)을 비활성화한 상태로 테스트되었다.92 실제 환경에서는 워크로드 특성과 구성에 따라 성능이 달라질 수 있다.
MQTT는 이론적 우수성을 넘어, 다양한 산업 현장에서 실질적인 가치를 창출하며 사실상의 표준(de facto standard)으로 자리매김하고 있다. 또한, 기술 생태계의 변화에 발맞춰 끊임없이 진화하며 그 적용 범위를 넓혀가고 있다.
산업용 사물 인터넷(Industrial Internet of Things, IIoT) 환경, 특히 스마트 팩토리에서는 수많은 종류의 장비(PLC, 센서, 로봇 등)와 상위 시스템(SCADA, MES, ERP) 간의 원활한 데이터 교환이 필수적이다. 하지만 MQTT 프로토콜 자체는 메시지 페이로드의 형식이나 토픽 네임스페이스의 구조를 강제하지 않기 때문에, 각기 다른 제조사의 장비나 시스템이 서로 다른 데이터 형식을 사용하게 되면 상호운용성(interoperability) 문제가 발생할 수 있다.95
이러한 문제를 해결하기 위해 이클립스 재단(Eclipse Foundation)의 Tahu 프로젝트를 통해 ‘Sparkplug’라는 명세가 등장했다.97 Sparkplug는 MQTT를 기반으로 IIoT 환경에 필요한 추가적인 규칙을 정의한 오픈소스 명세이다.
spBv1.0/{Group_ID}/{Message_Type}/{Edge_Node_ID}/.96 이를 통해 전체 시스템의 데이터 구조가 통일되고 예측 가능해진다.NBIRTH/NDEATH (노드 탄생/사망 증명서), DBIRTH/DDEATH (장치 탄생/사망 증명서)와 같은 특정 메시지 타입을 통해 시스템의 모든 참여자는 각 구성요소의 현재 상태를 항상 인지할 수 있다(stateful awareness).100이처럼 MQTT와 Sparkplug B의 결합은 전통적인 SCADA 시스템을 현대화하고, OT(운영 기술)와 IT(정보기술)의 데이터를 완벽하게 통합하여 진정한 의미의 데이터 기반 스마트 팩토리를 구현하는 핵심 기술로 인정받고 있다.109
MQTT의 특성은 IIoT뿐만 아니라, 대규모의 이동성 객체와 도시 인프라를 연결하는 데에도 매우 적합하다.
MQTT는 현재의 성공에 안주하지 않고, 변화하는 기술 환경에 맞춰 지속적으로 진화하고 있다.
MQTT는 TCP/IP 네트워크를 전제로 하지만, 모든 IoT 디바이스가 TCP/IP 스택을 지원하는 것은 아니다. 특히 Zigbee, Bluetooth LE, LoRaWAN과 같은 저전력 단거리 무선 기술을 사용하는 센서 네트워크에서는 TCP/IP의 오버헤드가 부담스러울 수 있다.
Topic ID로 대체하여 전송 데이터의 크기를 획기적으로 줄인다.122 또한, UDP와 같은 비연결성 프로토콜 위에서 동작하며, 디바이스가 대부분의 시간 동안 잠들어(sleep) 있다가 데이터를 보낼 때만 깨어나는 ‘슬리핑 클라이언트’ 모드를 공식적으로 지원하여 배터리 소모를 최소화한다.125TCP는 신뢰성 있는 전송을 보장하지만, 헤드 오브 라인 블로킹(Head-of-Line Blocking) 문제와 긴 연결 설정 시간(3-way handshake)이라는 고질적인 한계를 가지고 있다. 특히 네트워크 환경이 수시로 바뀌는 모바일 환경에서는 이러한 단점이 더욱 부각된다.
인공지능(AI), 특히 거대 언어 모델(LLM)의 발전은 IoT와 결합하여 AIoT(Artificial Intelligence of Things)라는 새로운 패러다임을 열고 있다. 이제는 단순히 데이터를 수집하고 제어하는 것을 넘어, AI가 실시간 데이터를 이해하고 자율적으로 판단하며 시스템과 상호작용하는 시대가 오고 있다.
이처럼 MQTT는 단순한 데이터 전송 수단을 넘어, 산업 표준(Sparkplug B), 비-IP 네트워크(MQTT-SN), 차세대 전송 기술(QUIC), 그리고 인공지능(MCP)과 결합하며 그 생태계를 확장하고 있다. 이는 MQTT가 단순한 프로토콜이 아니라, 현대 분산 시스템을 위한 근본적이고 다목적인 ‘서비스 버스(Service Bus)’로 진화하고 있음을 보여준다. MQTT의 핵심인 발행-구독 모델은 그 자체로 매우 근본적이고 유연하여, 다양한 영역의 특정 문제(산업 상호운용성, AI 통합 등)를 해결하기 위한 새로운 프로토콜과 명세들이 MQTT를 기반으로 구축되고 있다. MQTT는 ‘사물들의 TCP/IP’와 같은 역할을 하며, 더 높은 수준의 전문화된 통신 패턴이 구축될 수 있는 안정적이고 신뢰할 수 있는 기반이 되어가고 있다.
MQTT는 지난 20여 년의 세월 동안, 특정 산업의 요구를 해결하기 위해 탄생한 경량 원격 측정 프로토콜에서 시작하여, 오늘날 사물 인터넷(IoT)과 산업용 사물 인터넷(IIoT)을 아우르는 가장 지배적인 메시징 프로토콜이자 사실상의 표준(de facto standard)으로 확고히 자리매김했다. 이러한 성공의 핵심 동력은 기술적 정교함 이전에, ‘경량성’과 ‘효율성’이라는 명확한 목표, 그리고 ‘발행-구독’ 모델이 제공하는 강력하고 우아한 ‘분리(Decoupling)’의 설계 철학에 있다. 시공간적, 동기적 분리는 시스템 구성요소 간의 의존성을 제거함으로써 본질적으로 높은 확장성, 유연성, 그리고 회복탄력성을 갖춘 아키텍처를 가능하게 했다.
MQTT v5.0의 등장은 프로토콜이 단순한 데이터 전달자의 역할을 넘어, 대규모 엔터프라이즈 시스템의 복잡한 운영 요구사항을 수용할 수 있는 성숙한 메시징 프레임워크로 진화했음을 명확히 보여준다. 이유 코드, 세션 및 메시지 만료, 공유 구독, 사용자 속성과 같은 정교한 기능들은 시스템의 안정성, 디버깅 용이성, 그리고 상호운용성을 프로토콜 수준에서 보장하며, 개발자들이 더 높은 수준의 비즈니스 로직에 집중할 수 있는 토대를 마련해주었다.
그러나 MQTT의 성공적인 대규모 배포는 프로토콜 자체의 기능만으로 보장되지 않는다. 본 고찰에서 분석한 바와 같이, 견고한 보안 아키텍처의 구축은 필수적이다. TLS/SSL을 통한 전송 계층 암호화, 인증서 기반의 강력한 인증, 그리고 최소 권한 원칙에 입각한 세분화된 ACL 인가 정책은 다층적 방어 체계의 핵심이다. 또한, 수백만 동시 연결을 지원하기 위한 브로커 클러스터링 아키텍처(Active-Active/Passive)의 이해와 Linux 커널 및 네트워크 스택에 대한 깊이 있는 튜닝은 이론을 현실로 만드는 운영 기술의 정수라 할 수 있다.
미래를 향한 MQTT의 여정은 더욱 역동적이다. Sparkplug B 명세를 통해 IIoT 데이터의 의미론적 상호운용성을 확보하고, MQTT-SN을 통해 비-IP 기반의 저전력 센서 네트워크까지 그 영역을 확장하고 있다. 더 나아가, QUIC과 같은 차세대 전송 프로토콜을 수용하여 모바일 및 불안정한 네트워크 환경에서의 성능을 극대화하고, MCP와 같은 AI 시대의 프로토콜과 결합하여 단순한 데이터 파이프라인을 넘어 지능형 에이전트가 상호작용하는 지능형 서비스 버스로의 진화를 꾀하고 있다.
결론적으로, MQTT의 현재적 가치는 검증된 신뢰성과 효율성에 있으며, 그 미래적 가치는 끊임없이 확장되는 생태계와 변화하는 기술 패러다임을 수용하는 놀라운 적응성에 있다. MQTT는 앞으로도 다가올 초연결 시대의 수많은 디바이스와 시스템을 잇는 보이지 않는 신경망으로서, 그 중요성과 영향력을 더욱 확대해 나갈 것으로 전망된다.
| MQTT QoS Levels Explained with Example | QoS 0 , 1, & 2 - Bevywise, 8월 4, 2025에 액세스, https://www.bevywise.com/blog/mqtt-qos-level-use/ |
| MQTT QoS 0, 1, 2 Explained: A Quickstart Guide | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/introduction-to-mqtt-qos |
| Retained Messages | MQTT Broker - ThingsBoard, 8월 4, 2025에 액세스, https://thingsboard.io/docs/mqtt-broker/user-guide/retained-messages/ |
| MQTT 5.0: 7 New Features and a Migration Checklist | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/introduction-to-mqtt-5 |
| MQTT 3.1 vs MQTT 5: Should you upgrade? | by Jayraj Roshan - IoTIFY, 8월 4, 2025에 액세스, https://blog.iotify.io/mqtt-3-1-vs-mqtt-5-should-you-upgrade-e891d71ae2c2 |
| MQTT Shared Subscriptions: Practical Guidelines and Use Cases | MQTT 5 Features | EMQ, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/introduction-to-mqtt5-protocol-shared-subscription |
| MQTT vs HTTP: Ultimate IoT Protocol Comparison Guide | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/mqtt-vs-http |
| MQTT vs AMQP | Svix Resources, 8월 4, 2025에 액세스, https://www.svix.com/resources/faq/mqtt-vs-amqp/ |
| MQTT vs AMQP for IoT Communications: Head to Head | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/mqtt-vs-amqp-for-iot-communications |
| MQTT Protocol Explained: The Complete Guide | Cedalo, 8월 4, 2025에 액세스, https://cedalo.com/blog/complete-mqtt-protocol-guide/ |
| Configure MQTT broker authentication - Azure IoT Operations | Microsoft Learn, 8월 4, 2025에 액세스, https://learn.microsoft.com/en-us/azure/iot-operations/manage-mqtt-broker/howto-configure-authentication |
| Security | MQTT Broker - ThingsBoard, 8월 4, 2025에 액세스, https://thingsboard.io/docs/mqtt-broker/security/ |
| MQTT-VET: Exploring MQTT Protocol Vulnerabilities | Proceedings of the 13th Latin-American Symposium on Dependable and Secure Computing, 8월 4, 2025에 액세스, https://sol.sbc.org.br/index.php/ladc_estendido/article/view/34305/34096 |
| Exploring the Basics of MQTT Broker Clustering: An Introduction | IoT For All, 8월 4, 2025에 액세스, https://www.iotforall.com/exploring-the-basics-of-mqtt-broker-clustering-an-introduction |
| MQTT Broker: How It Works, Popular Options, and Quickstart | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/the-ultimate-guide-to-mqtt-broker-comparison |
| Elevating MQTT Broker Availability and Inter-Broker Communication | IoT For All, 8월 4, 2025에 액세스, https://www.iotforall.com/elevating-mqtt-broker-availability-with-inter-broker-communicator |
| MQTT High Availability and Mosquitto Clustering | Cedalo, 8월 4, 2025에 액세스, https://cedalo.com/mqtt-broker-pro-mosquitto/high-availability/ |
| Active-Active Vs. Active-Passive High-Availability Clustering | JSCAPE, 8월 4, 2025에 액세스, https://www.jscape.com/blog/active-active-vs-active-passive-high-availability-cluster |
| High Availability | Apache BifroMQ (Incubating) - Open source MQTT Broker, 8월 4, 2025에 액세스, https://bifromq.apache.org/docs/cluster/high_availability/ |
| High Availability | BifroMQ.io - Multi-tenancy MQTT Broker, 8월 4, 2025에 액세스, https://bifromq.io/docs/operations/high_availability/ |
| Comparison of Open Source MQTT Brokers 2024 | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/a-comprehensive-comparison-of-open-source-mqtt-brokers-in-2023 |
| Sparkplug B | EMQX Docs, 8월 4, 2025에 액세스, https://docs.emqx.com/en/emqx/latest/data-integration/sparkplug.html |
| The Sparkplug Specification | The Eclipse Foundation, 8월 4, 2025에 액세스, https://sparkplug.eclipse.org/specification/ |
| Enhancing IIoT Interoperability through MQTT Message Standardization with Sparkplug and OPCRouter | by ca | Medium, 8월 4, 2025에 액세스, https://akpolatcem.medium.com/enhancing-iiot-interoperability-through-mqtt-message-standardization-with-sparkplug-7a5827078d93 |
| MQTT in Connected Cars: Key Benefits and Real-World Applications | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/mqtt-for-internet-of-vehicles |
| MQTT-Powered Smart Cities | Optimize Your City - HiveMQ, 8월 4, 2025에 액세스, https://www.hivemq.com/solutions/smart-cities/ |
| Exploring MQTT-SN: A Comprehensive Guide | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/connecting-mqtt-sn-devices-using-emqx |
| MQTT over QUIC: Next-Generation IoT Standard Protocol | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/mqtt-over-quic |
| Shaping the Future of IoT: 7 MQTT Technology Trends in 2023 | EMQ, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/7-mqtt-trends-in-2023 |
| MQTT over QUIC | EMQX Docs, 8월 4, 2025에 액세스, https://docs.emqx.com/en/emqx/latest/mqtt-over-quic/introduction.html |
| MQTTX + MCP: Enhancing MQTT Toolbox with AI Capabilities | EMQ - EMQX, 8월 4, 2025에 액세스, https://www.emqx.com/en/blog/enhancing-mqtt-toolbox-with-ai-capabilities |