MQTT란? Broker·Publisher·Subscriber·Topic으로 이해하는 IoT 통신
MQTT란? Broker·Publisher·Subscriber·Topic으로 이해하는 IoT 통신#
1장 수백 개의 센서는 왜 Server에 직접 연결하지 않을까#
주차장에 주차면 Sensor가 100개 있다고 생각해보겠습니다.
각 Sensor는 다음 상태를 전달해야 합니다.
주차면 1
→ FREE
주차면 2
→ OCCUPIED
주차면 3
→ FREE가장 단순하게 생각하면 Sensor가 각각 중앙 Server API를 호출하도록 만들 수 있습니다.
Sensor 1 ─────→ Server
Sensor 2 ─────→ Server
Sensor 3 ─────→ Server
Sensor 4 ─────→ Server
...
Sensor 100 ───→ Server처음에는 간단합니다.
하지만 나중에 이 데이터를:
관제 Server
Dashboard
Mobile App
통계 System
장애 Monitoring
AI 분석 System에서도 받아야 한다면 어떻게 될까요?
Sensor가 데이터를 받을 모든 System을 알아야 하는 구조는 점점 복잡해집니다.
MQTT는 이 관계를 중간의 Broker를 이용해 분리합니다.
Sensor
│
│ Publish
▼
MQTT Broker
│
├────→ 관제 Server
├────→ Dashboard
├────→ 통계 System
└────→ MonitoringMQTT는 제한된 Device와 낮은 Network 대역폭 같은 환경을 고려한 가벼운 Publish/Subscribe Messaging Protocol이며 IoT뿐 아니라 제조·자동차·물류 등에서도 사용됩니다.
2장 MQTT의 핵심은 Publish와 Subscribe다#
HTTP API에서는 일반적으로 Client가 특정 Server를 알고 Request를 보냅니다.
Client
↓
HTTP Request
↓
ServerMQTT에서는 기본적인 생각이 다릅니다.
Publisher는 수신자가 누군지 직접 알 필요가 없습니다.
대신 특정 Topic으로 Message를 Publish합니다.
Publisher
↓
Topic
↓
Broker
↓
Subscriber예를 들어 주차면 Sensor가:
parking/site01/slot05/state라는 Topic으로:
{
"state": "occupied"
}를 Publish한다고 하겠습니다.
이 Topic을 Subscribe하고 있는 Client들이 Message를 받을 수 있습니다.
MQTT 공식 설명에서도 Broker는 Publish된 Message를 Subscriber에게 Routing하는 Server 역할을 합니다.
3장 Broker·Publisher·Subscriber 역할을 구분하자#
Publisher#
Message를 발행하는 Client입니다.
예:
주차면 Sensor
Gateway
Gate Controller
Temperature Sensor주차면 Sensor가:
parking/site01/slot05/stateTopic으로 상태를 보냅니다.
Broker#
MQTT 통신의 중심입니다.
Publisher가 보낸 Message를 받고 어떤 Client가 해당 Topic을 Subscribe하고 있는지 확인한 뒤 전달합니다.
┌─ Dashboard
Sensor ─ Broker ┼─ Monitoring
├─ Database Consumer
└─ Mobile ServiceSubscriber#
관심 있는 Topic을 구독하는 Client입니다.
예:
Subscribe
parking/site01/slot05/state이후 해당 Topic으로 Message가 Publish되면 Broker를 통해 전달받습니다.
MQTT의 장점은 Publisher와 Subscriber가 서로의 주소나 구현을 직접 알 필요가 없다는 것입니다.
4장 Topic은 MQTT Message의 주소다#
MQTT의 Topic은 Message를 분류하는 문자열입니다.
예:
parking/site01/slot05/state계층적으로 설계하면 다음과 같이 읽을 수 있습니다.
parking
└─ site01
└─ slot05
└─ state다른 데이터도 다음처럼 구성할 수 있습니다.
parking/site01/slot05/state
parking/site01/slot05/battery
parking/site01/gate01/status
parking/site01/gate01/error좋은 Topic 구조는 MQTT 시스템을 운영하기 쉽게 만듭니다.
와일드카드 구독#
Subscriber는 하나의 Topic뿐 아니라 여러 Topic을 한 번에 구독할 수도 있습니다.
예:
parking/site01/+/state+는 한 단계의 Topic Level을 의미합니다.
따라서:
parking/site01/slot01/state
parking/site01/slot02/state
parking/site01/slot03/state등을 받을 수 있습니다.
#는 여러 단계의 하위 Topic을 포함하는 구독에 사용할 수 있습니다.
예:
parking/site01/#그러면 site01 아래의 여러 Topic을 받을 수 있습니다.
5장 실제 주차면 Sensor 흐름을 따라가보자#
주차면 5번에 차량이 들어왔다고 하겠습니다.
Sensor:
FREE
↓
OCCUPIED상태가 바뀝니다.
Gateway가 이를 MQTT Message로 변환합니다.
Topic:
parking/site01/slot05/statePayload:
{
"slotId": "slot05",
"state": "occupied",
"timestamp": "2026-09-24T15:30:20+09:00"
}그리고 Broker로 Publish합니다.
Sensor
↓
Gateway
↓
PUBLISH
↓
MQTT Broker
↓
┌──────────────┬──────────────┐
│ │ │
관제 Server Dashboard 통계 System관제 Server는 Database를 갱신할 수 있고 Dashboard는 화면의 주차면 색상을 바꿀 수 있습니다.
Publisher는 이 후속 작업들을 알 필요가 없습니다.
이것이 Publish/Subscribe 구조의 중요한 특징입니다.
6장 MQTT는 HTTP와 무엇이 다른가#
HTTP API와 MQTT는 경쟁 관계라기보다 용도가 다릅니다.
| 항목 | HTTP·REST | MQTT |
|---|---|---|
| 기본 모델 | Request / Response | Publish / Subscribe |
| 중간 Broker | 일반적으로 없음 | 있음 |
| Server Push | 별도 기술 필요 | 기본 구조에 적합 |
| Device 간 결합 | Endpoint를 알아야 함 | Topic을 통해 분리 |
| 지속 연결 | 상황에 따라 | 일반적으로 Broker 연결 유지 |
| 주요 활용 | API·Web Service | IoT·Event·Telemetry |
예를 들어:
회원 차량 조회
→ REST API
주차면 상태 Event
→ MQTT처럼 함께 사용할 수 있습니다.
실제 Architecture:
Sensor
↓
MQTT
↓
Backend
↓
Database
Web Application
↓
REST API
↓
Backend처럼 두 방식을 같이 사용하는 것도 자연스럽습니다.
7장 QoS 0·1·2는 무엇이 다른가#
MQTT에는 세 가지 Quality of Service Level이 있습니다.
공식 MQTT 설명에서는 각각 At most once, At least once, Exactly once 전달 수준으로 정의합니다.
QoS 0 — At most once#
Publisher
↓
PUBLISH
↓
Broker가장 단순합니다.
추가적인 MQTT 전달 확인 절차가 없습니다.
따라서:
빠름
Overhead 작음
Message 손실 가능이라는 특징이 있습니다.
자주 갱신되는 Sensor의 현재 상태처럼 다음 Message가 곧 도착하는 환경에서는 고려할 수 있습니다.
QoS 1 — At least once#
Message가 전달되었다는 확인을 주고받습니다.
PUBLISH
↓
PUBACK전달 신뢰성을 높일 수 있지만 같은 Message가 중복 전달될 가능성이 있습니다.
따라서 Consumer는:
Message ID
Event ID
업무 Key등을 이용해 중복을 처리할 필요가 있을 수 있습니다.
QoS 2 — Exactly once#
MQTT Protocol 수준에서 더 많은 Handshake를 사용해 한 번 전달되는 의미를 제공합니다.
그만큼:
Packet 증가
Latency 증가
Client·Broker 상태 관리 증가가 발생합니다.
여기서 중요한 점이 있습니다.
QoS 2가 Database Transaction이나 실제 업무의 Exactly Once까지 자동으로 보장하는 것은 아닙니다.
예를 들어 MQTT Message를 한 번 전달받았더라도 Consumer가:
Database 저장
↓
Process Crash하는 상황은 별도로 처리해야 합니다.
따라서 중요한 업무에서는 MQTT QoS와 Application의 Idempotency를 별도로 설계해야 합니다.
8장 모든 중요 데이터에 QoS 2를 쓰면 좋을까#
그렇지 않습니다.
QoS가 높을수록 무조건 좋은 것이 아니라 비용도 증가합니다.
주차면 Sensor 상태처럼:
FREE
OCCUPIED가 계속 갱신되고 가장 최신 상태가 중요한 데이터라면 QoS 0 또는 1로 충분한 시스템도 많습니다.
반면:
결제 Event
출입 승인 Event
정산 Event처럼 하나의 Event가 업무적으로 중요하다면 더 신중한 전달 정책을 설계해야 합니다.
하지만 이 경우에도:
QoS 2 하나면 끝이라고 생각하면 안 됩니다.
필요하다면:
QoS
Event ID
Consumer Idempotency
Persistent Storage
Retry
Dead Letter 처리등을 함께 고려해야 합니다.
9장 Retained Message와 Last Will을 알아두자#
MQTT에는 IoT 운영에서 특히 유용한 기능이 있습니다.
Retained Message#
Publisher가 Retain Flag를 사용해 Message를 Publish하면 Broker가 해당 Topic의 마지막 Retained Message를 저장할 수 있습니다.
예:
parking/site01/slot05/state마지막 값:
{
"state": "occupied"
}새로운 Subscriber가 나중에 접속하더라도 현재 상태를 빠르게 받아볼 수 있습니다.
이런 특성은:
현재 주차면 상태
장비 현재 Mode
마지막 알려진 상태처럼 최신 상태가 중요한 데이터에 유용할 수 있습니다.
Last Will and Testament#
Client가 비정상적으로 연결을 잃었을 때 Broker가 미리 지정된 Message를 대신 Publish하도록 설정할 수 있습니다.
예:
parking/site01/gateway01/statusWill Message:
{
"status": "offline"
}Gateway가 정상적인 DISCONNECT 없이 연결을 잃으면 다른 System이 이를 감지하는 데 활용할 수 있습니다.
10장 Keep Alive와 Session도 중요하다#
MQTT Client는 Broker와 연결을 유지합니다.
이때 Keep Alive 설정을 이용해 연결 상태를 관리할 수 있습니다.
필요하면:
PINGREQ
↓
PINGRESP같은 Control Packet이 사용됩니다.
하지만 Keep Alive를 너무 짧게 설정하면 불필요한 Traffic이 증가할 수 있고 너무 길게 설정하면 장애를 늦게 발견할 수 있습니다.
Session은 재접속과 관계가 있다#
MQTT에서는 연결이 끊겼다가 다시 접속했을 때 구독이나 미전달 Message와 관련된 Session 상태를 유지하도록 설정할 수 있습니다.
다만 MQTT 3.1.1의 Clean Session과 MQTT 5의 Clean Start, Session Expiry Interval은 세부 동작과 표현 방식이 다릅니다.
따라서 단순히:
Persistent Session = 항상 같은 설정으로 이해하지 말고 사용하는 MQTT Version과 Client Library를 확인해야 합니다.
11장 MQTT 연결 과정에서 어떤 Packet이 오갈까#
MQTT에는 여러 Control Packet이 있습니다.
대표적으로:
CONNECT
CONNACK
PUBLISH
PUBACK
SUBSCRIBE
SUBACK
UNSUBSCRIBE
UNSUBACK
PINGREQ
PINGRESP
DISCONNECT등이 있습니다.
기본 연결 흐름을 단순화하면:
Client
│
│ CONNECT
├─────────────→ Broker
│
│ CONNACK
←─────────────┤Subscriber:
Client
│
│ SUBSCRIBE
├─────────────→ Broker
│
│ SUBACK
←─────────────┤Publisher:
Client
│
│ PUBLISH
├─────────────→ Broker처럼 동작합니다.
QoS Level에 따라 추가적인 확인 Packet이 이어질 수 있습니다.
12장 주차관제에서 MQTT Gateway를 사용할 수 있다#
현장에는 MQTT를 직접 지원하지 않는 장비도 많습니다.
예를 들어 기존 Sensor나 Controller가 Modbus RTU만 지원한다고 하겠습니다.
이런 경우 Gateway를 둘 수 있습니다.
Sensor / Controller
↓
RS-485
↓
Modbus RTU
↓
IoT Gateway
↓
MQTT
↓
BrokerGateway는 Modbus Register를 읽습니다.
예:
Register 100
=
1이를 업무 상태로 해석합니다.
1
=
OCCUPIED그 뒤 MQTT Message로 변환합니다.
Topic
parking/site01/slot05/state{
"state": "occupied"
}이렇게 하면 오래된 산업 장비와 새로운 IoT Platform을 연결할 수 있습니다.
13장 MQTT를 직접 실행해보자#
Mosquitto Client를 이용하면 간단하게 Publish와 Subscribe를 시험할 수 있습니다.
Subscriber:
mosquitto_sub \
-h broker.example.local \
-t "parking/site01/#" \
-q 0Publisher:
mosquitto_pub \
-h broker.example.local \
-t "parking/site01/slot05/state" \
-m '{"state":"occupied"}' \
-q 0시험 환경에서 Subscriber를 먼저 실행하고 Publisher에서 Message를 보내면 Topic과 Payload가 전달되는 흐름을 확인할 수 있습니다.
Python에서 Publish하기#
현재 Eclipse Paho Python 문서에서는 Callback API Version 2 사용을 권장하고 있습니다.
간단한 시험 예:
import paho.mqtt.client as mqtt
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id="sensor-sim-01"
)
client.connect(
"test-broker.local",
1883,
60
)
client.loop_start()
info = client.publish(
"parking/test/slot01/state",
'{"state":"free"}',
qos=0
)
info.wait_for_publish()
client.loop_stop()
client.disconnect()Paho에서는 Network Loop가 실제 Network Traffic과 Callback 처리를 담당하므로 단순히 publish()만 호출하고 즉시 Process를 종료하는 방식은 피하는 것이 좋습니다.
14장 MQTT 보안과 장애를 어떻게 볼까#
MQTT의 대표적인 TCP Port는 1883이고 TLS를 사용하는 MQTT에는 8883이 등록되어 있습니다.
운영 환경에서는 단순히 Broker를 외부에 열어두어서는 안 됩니다.
최소한 다음을 검토합니다.
TLS
Client Authentication
Username / Password 또는 인증서
Topic ACL
Network 분리
Rate Limit
Connection Limit
Credential 관리특히 Topic 권한이 중요합니다.
예를 들어 Sensor 05가:
parking/site01/slot05/#만 Publish할 수 있어야 하는데:
parking/#전체에 Publish할 수 있다면 다른 장비 상태를 위조할 위험이 생깁니다.
Broker 장애도 고려한다#
Architecture가:
모든 Sensor
↓
Broker 한 대뿐이라면 Broker 장애가 전체 Messaging에 영향을 줄 수 있습니다.
운영 규모에 따라:
High Availability
Broker Cluster
Persistent Storage
Monitoring
Backup
Gateway Local Queue등을 검토할 수 있습니다.
다만 Cluster와 HA 방식은 MQTT Protocol 자체가 하나의 방식으로 규정하는 것이 아니라 사용하는 Broker 제품과 Architecture에 따라 달라집니다.
15장 MQTT 장애를 계층별로 진단한다#
MQTT가 안 된다는 말만으로는 원인을 찾기 어렵습니다.
다음 순서로 나눌 수 있습니다.
Broker에 연결되지 않는다#
확인:
DNS
IP
Routing
TCP Port
Firewall
TLS Certificate
Authentication
Broker 상태CONNECT는 되는데 Subscribe가 실패한다#
확인:
Topic ACL
Topic 이름
Authentication
Broker 정책Subscribe는 성공했는데 Message가 없다#
확인:
Publisher가 실제 Publish하는가?
Topic이 정확히 같은가?
Wildcard가 맞는가?
QoS 설정은 무엇인가?
Publisher Log가 있는가?Message가 중복된다#
특히 QoS 1에서는 중복 전달 가능성을 고려해야 합니다.
Event ID
Idempotency
Consumer 처리 Log를 확인합니다.
장비가 Offline인데 화면에는 Online이다#
확인:
Last Will
Heartbeat
Keep Alive
마지막 Message 시각
Retained Message를 함께 봅니다.
Retained Message는 과거 마지막 상태일 수 있으므로 Retained 값이 존재한다는 사실만으로 장비가 지금 Online이라고 판단해서는 안 됩니다.
16장 흔히 하는 MQTT 오해#
MQTT는 Message Queue의 약자다#
이름의 역사와 별개로 현재는 MQTT 자체를 고유한 Protocol 이름으로 다루는 것이 적절합니다.
Publisher가 Subscriber에게 직접 Message를 보낸다#
아닙니다.
일반적인 MQTT 구조에서는 Broker를 통해 전달됩니다.
QoS 0이면 Message가 반드시 손실된다#
아닙니다.
다만 MQTT Level에서 재전송을 통한 전달 보장을 제공하지 않는다는 의미입니다.
QoS 1이면 Message가 정확히 한 번만 온다#
아닙니다.
QoS 1은 At least once이므로 중복 전달 가능성을 고려해야 합니다.
QoS 2면 Database도 Exactly Once 처리된다#
아닙니다.
MQTT Protocol의 전달 의미와 Application Transaction은 별개의 문제입니다.
Retained Message는 Message History다#
아닙니다.
일반적으로 해당 Topic의 마지막 Retained 상태를 제공하기 위한 기능으로 이해하는 것이 좋습니다.
MQTT를 쓰면 Broker에 Message가 영원히 저장된다#
아닙니다.
저장 여부와 기간은 Session, Retain, QoS 및 Broker 정책 등에 따라 달라집니다.
MQTT는 무조건 배터리를 적게 사용한다#
Protocol이 가볍다는 것과 실제 Device 전력 사용량은 같은 문제가 아닙니다.
Radio 사용 시간, 연결 유지, Keep Alive, Publish 주기와 Network 기술 등이 전력 소비에 영향을 줍니다.
17장 MQTT 설계 체크리스트#
□ MQTT가 필요한 데이터인가?
□ HTTP API와 MQTT의 역할을 구분했는가?
□ Broker 위치는 어디인가?
□ Client ID 정책이 있는가?
□ Topic Naming Rule을 정했는가?
□ Publisher 권한을 제한했는가?
□ Subscriber 권한을 제한했는가?
□ QoS를 데이터 성격에 맞게 선택했는가?
□ QoS 1의 중복 가능성을 처리하는가?
□ 중요한 업무에 Event ID가 있는가?
□ Retained Message가 필요한가?
□ Last Will을 설정할 것인가?
□ Keep Alive는 얼마인가?
□ Session 정책을 정했는가?
□ 사용하는 MQTT Version을 확인했는가?
□ Reconnect 정책이 있는가?
□ Gateway Local Queue가 필요한가?
□ TLS를 사용하는가?
□ Topic ACL을 설정했는가?
□ Broker 장애에 대비했는가?
□ Connection·Message Rate를 Monitoring하는가?18장 자기 점검#
Broker는 어떤 역할을 하는가#
Publisher가 Publish한 Message를 받아 Topic Subscription에 따라 Subscriber에게 전달합니다.
Publisher와 Subscriber는 서로의 IP를 알아야 하는가#
일반적인 MQTT 구조에서는 서로의 IP를 직접 알 필요가 없고 각각 Broker와 연결합니다.
Topic은 무엇인가#
Message를 분류하고 Subscriber가 원하는 Message를 선택할 수 있도록 하는 계층형 문자열입니다.
QoS 1은 어떤 의미인가#
At least once 전달을 의미하므로 Message가 중복될 가능성을 고려해야 합니다.
QoS 2를 쓰면 업무가 정확히 한 번만 처리되는가#
반드시 그렇지 않습니다. MQTT 전달 과정과 Consumer의 Database·업무 Transaction은 별도로 설계해야 합니다.
Retained Message와 Last Will의 차이는 무엇인가#
Retained Message는 Topic의 마지막 상태를 새로운 Subscriber 등에게 제공하는 데 사용할 수 있고, Last Will은 Client가 비정상적으로 연결을 잃었을 때 Broker가 미리 설정한 Message를 Publish하는 기능입니다.
19장 이 글을 마치며#
MQTT의 핵심 구조는 의외로 단순합니다.
Publisher
↓
Topic
↓
Broker
↓
SubscriberPublisher는 누가 Message를 사용하는지 알 필요가 없습니다.
Subscriber도 Sensor의 IP나 구현을 직접 알 필요가 없습니다.
Broker와 Topic이 두 영역을 연결합니다.
여기에 실제 운영에서는:
QoS
Retained Message
Last Will
Keep Alive
Session
Authentication
TLS
Topic ACL
Reconnect같은 기능이 추가됩니다.
특히 다음 다섯 가지를 기억하면 됩니다.
MQTT는 Broker를 중심으로 Publisher와 Subscriber를 분리하는 Publish/Subscribe Messaging Protocol입니다.
Topic을 잘 설계하면 Sensor·Gateway·Server·Dashboard가 서로 직접 연결되지 않아도 같은 Event를 공유할 수 있습니다.
QoS 0·1·2는 MQTT Message 전달 수준을 조정하지만 Application의 업무 Transaction까지 자동으로 보장하지는 않습니다.
Retained Message는 현재 상태 전달에, Last Will은 비정상 연결 종료 감지에 유용하지만 각각의 의미를 정확히 구분해야 합니다.
MQTT의 장점은 단순히 Message 크기가 작다는 데 있는 것이 아니라 수많은 Device와 여러 Consumer 사이의 결합도를 낮출 수 있다는 데 있습니다.
결국 MQTT를 이해한다는 것은 mosquitto_pub 명령을 실행하는 데 그치지 않습니다.
어떤 Device가 어떤 Topic으로 무엇을 Publish하고, Broker가 그것을 어떤 Subscriber에게 어떤 QoS와 Session 정책으로 전달하며, 연결이 끊어졌을 때 어떻게 상태를 복구할 것인지 전체 Messaging 흐름을 설계하는 것이 핵심입니다.