검증 도구
MQTT 문제는 대개 “누가 무엇을 어느 토픽에 보냈고, 브로커가 누구에게 전달했는가”를 확인하면 풀립니다. 이 문서는 그 질문에 답하는 도구를 정리합니다.
mosquitto_sub로 관찰하기
섹션 제목: “mosquitto_sub로 관찰하기”mosquitto_sub를 와일드카드 필터로 실행하면 브로커를 지나는 메시지를 볼 수 있습니다.
MQTT 5.0 속성을 보려면 반드시 -V 5를 줍니다.
mosquitto_sub -V 5 -t 'opcua/#' -F '%t qos=%q retain=%r content-type=%C user-properties=%P %l bytes'-F 코드 |
출력 |
|---|---|
%t |
토픽 |
%q, %r |
받은 QoS, RETAIN 플래그 |
%C |
Content Type 속성 |
%P |
사용자 속성(이름:값, 쉼표로 구분) |
%l |
페이로드 길이(바이트) |
%x |
페이로드의 16진수 |
%p |
페이로드 원문 |
%I |
받은 시각(ISO 8601) |
%j |
메시지 전체를 JSON 한 줄로 |
-F '%j'는 속성까지 JSON으로 보여 줍니다.
{"tst":"2026-10-15T02:07:35.001558+0900","topic":"demo/a","qos":0,"retain":false,"payloadlen":2,"properties":{"content-type":"text/plain","user-properties":[{"k":"v"}]},"payload":"hi"}자주 쓰는 다른 옵션은 다음과 같습니다.
| 옵션 | 뜻 |
|---|---|
-q 1 |
QoS 1로 구독합니다. 기본값은 QoS 0입니다. |
-C <개수> |
메시지를 그만큼 받으면 끝냅니다. |
-W <초> |
그 시간 안에 끝나지 않으면 Timed out을 출력하고 종료 코드 27로 끝납니다. |
-N |
페이로드 뒤에 줄바꿈을 붙이지 않습니다. 바이너리를 파일로 받을 때 씁니다. |
-d |
클라이언트가 주고받는 패킷을 출력합니다. |
mosquitto_pub로 메시지 넣기
섹션 제목: “mosquitto_pub로 메시지 넣기”시뮬레이터 구독자가 받는지 시험하려면 mosquitto_pub에 OPC UA PubSub 속성을 붙입니다.
mosquitto_pub -V 5 -q 1 -t opcua/uadp/data/77/demo \ -D publish content-type application/opcua+uadp \ -D publish user-property UAMessageType ua-data \ -f dataset.bin-f는 파일 내용을 그대로 페이로드로 보냅니다. UADP 페이로드를 만드는 방법은 시뮬레이터로 발행·구독에 있습니다.
브로커 로그 읽기
섹션 제목: “브로커 로그 읽기”mosquitto -v 또는 log_type all로 실행한 Mosquitto는 패킷마다 한 줄을 남깁니다.
New client connected from 127.0.0.1:64658 as pdcomm-opcua-sim-79619-17 (p5, c1, k30).Received SUBSCRIBE from pdcomm-opcua-sim-79619-17 opcua/uadp/data/77/quickstart (QoS 1)Received PUBLISH from pdcomm-opcua-sim-79619-17 (d0, q1, r0, m2, 'opcua/uadp/data/77/quickstart', ... (48 bytes))Sending PUBLISH to pdcomm-opcua-sim-79619-17 (d0, q1, r0, m1, 'opcua/uadp/data/77/quickstart', ... (48 bytes))Sending PUBACK to pdcomm-opcua-sim-79619-17 (m2, rc0)| 표기 | 뜻 |
|---|---|
p5, c1, k30 |
MQTT 5.0, Clean Start 1, Keep Alive 30초. 인증서나 사용자 이름이 있으면 u'…'가 붙습니다. |
d0, q1, r0, m2 |
DUP 0, QoS 1, RETAIN 0, 패킷 식별자 2 |
rc0 |
이유 코드 0x00(성공). rc135는 0x87(Not authorized) |
Denied PUBLISH from … |
ACL이 발행을 거부했습니다. |
disconnected: not authorised. |
인증에 실패해 연결을 끊었습니다. |
시뮬레이터의 클라이언트 식별자는 pdcomm-opcua-sim-<프로세스 ID>-<DataSetWriterId>이므로 로그에서 어느 시뮬레이터인지 구별할 수 있습니다.
$SYS 토픽
섹션 제목: “$SYS 토픽”Mosquitto는 $SYS/broker/ 아래에 브로커 정보를 발행합니다. 값은 sys_interval(기본 10초)마다 갱신됩니다.
mosquitto_sub -V 5 -t '$SYS/broker/version' -t '$SYS/broker/clients/connected' -t '$SYS/broker/messages/received' -v$SYS/broker/version mosquitto version 2.1.2#로 시작하는 필터는 $SYS와 일치하지 않으므로 $SYS 토픽은 따로 구독합니다.
시뮬레이터 상태 값으로 판단하기
섹션 제목: “시뮬레이터 상태 값으로 판단하기”시뮬레이터의 PubSub 상태(GUI 상태 줄, 헤드리스 pubsub_status)만으로 많은 것을 알 수 있습니다.
| 관찰 | 뜻 | 다음 확인 |
|---|---|---|
sent가 acknowledged보다 계속 큼 |
브로커가 PUBACK을 보내지 않았거나 실패로 답했습니다. | error의 MQTT publish refused: 0x.., 브로커 로그의 Denied PUBLISH |
rejected가 늘어남 |
메시지를 받았지만 형식이나 속성이 맞지 않았습니다. | error 값과 전달 문제 |
관찰자에는 보이는데 received가 그대로 |
토픽이 다르거나 브로커가 읽기 권한이 없어 전달하지 않았습니다. | 시뮬레이터 토픽과 ACL |
running이 false이고 error가 MQTT: … |
브로커 연결이 끊겼습니다. | 브로커 로그와 연결 문제 |
dropped가 늘어남 |
받은 메시지를 꺼내지 않아 대기열(256개)이 넘쳤습니다. | pubsub_received나 Show received를 더 자주 실행 |
시뮬레이터 추적
섹션 제목: “시뮬레이터 추적”시뮬레이터는 실행한 동작을 추적(trace)에 남깁니다. GUI에서는 Trace & Diagnostics 탭의 Refresh trace, 헤드리스에서는 {"action":"trace"}로 봅니다.
실패한 동작에는 오류 문장이 함께 남습니다.
{"action":"pubsub_start","elapsed_us":112,"error":"MQTT broker connection failed: MQTT transport I/O: ConnectionRefused","ok":false,"sequence":2,"time_ms":0,"workspace":"pubsub"}진단 로그 파일은 같은 탭의 **Diagnostic log (off by default)**와 Apply logging으로 켭니다. 헤드리스에서는 logging_configure를 씁니다.
{"action":"logging_configure","config":{"enabled":true,"file":"logs/opcua-simulator.jsonl"}}로그 형식과 수준은 도구 섹션의 진단 로그 문서를 따릅니다.