[IOT-007][중급] MQTT로 센서 값과 장치 명령 주고받기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[IOT-007][중급] MQTT로 센서 값과 장치 명령 주고받기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 137회 작성일 26-09-03 01:36

본문

[이번 수업]
MQTT의 발행·구독 구조와 센서 데이터·장치 명령의 토픽·본문 형식을 배웁니다. 외부 브로커 없이 메시지를 검증하는 실습도 진행합니다.

[선수지식]
IOT-006의 Wi-Fi·저전력 통신을 알고 JSON, 문자열, Python 함수를 읽을 수 있어야 합니다.

[학습목표]
1. 발행자·브로커·구독자의 역할을 설명한다.
2. 토픽과 QoS를 메시지 성격에 맞게 고른다.
3. 버전과 단위가 있는 장치 메시지를 검증한다.

[핵심개념]
MQTT는 발행/구독(Publish/Subscribe) 메시지 전송 규약입니다. 장치는 브로커(Broker, 메시지 중계 서버)에 토픽(Topic, 분류 주소)과 본문을 발행하고, 구독자는 관심 토픽을 받습니다. 발행자와 구독자는 직접 연결되지 않습니다.

토픽은 `devices/device-01/telemetry`처럼 `/`로 계층을 나눕니다. 장치 ID와 메시지 종류의 위치를 고정합니다. 구독 필터의 `+`는 한 단계, `#`는 여러 단계와 일치하지만 발행 토픽에는 와일드카드를 넣지 않습니다. 센서 값, 상태, 명령, 명령 결과는 별도 토픽으로 나눕니다.

QoS(Quality of Service, 전달 보장 수준) 0은 최대 한 번, 1은 최소 한 번, 2는 정확히 한 번의 프로토콜 전달을 목표로 합니다. QoS 1은 중복될 수 있어 수신 측이 `message_id`로 중복 처리를 막아야 합니다. QoS가 높을수록 확인 절차와 자원 사용도 늘어납니다.

Retain을 켜면 브로커가 해당 토픽의 마지막 메시지를 보관합니다. 현재 상태에는 유용하지만 일회성 명령을 보관하면 재연결한 장치가 오래된 명령을 실행할 수 있습니다. MQTT는 본문 형식을 정하지 않으므로 스키마 버전, UTC 시간, 단위, 메시지 ID를 애플리케이션 규칙으로 정합니다.

[따라하기]
다음을 `device_message.py`로 저장합니다. 토픽의 장치 ID와 종류, 온도 범위와 스키마 버전을 검사합니다.

```python
import json
import re

TOPIC = re.compile(r"^devices/([a-z0-9-]{1,32})/telemetry$")

def make_message(device_id, temperature_c):
    topic = f"devices/{device_id}/telemetry"
    body = {
        "schema_version": 1,
        "message_id": "msg-0001",
        "sent_at": "2026-09-03T00:00:00Z",
        "data": {"temperature_c": temperature_c},
    }
    return topic, json.dumps(body, sort_keys=True, separators=(",", ":"))

def validate(topic, payload):
    match = TOPIC.fullmatch(topic)
    body = json.loads(payload)
    value = body.get("data", {}).get("temperature_c")
    valid_value = isinstance(value, (int, float)) and -40 <= value <= 125
    if not match or body.get("schema_version") != 1 or not valid_value:
        raise ValueError("지원하지 않는 메시지")
    return f"{match.group(1)}: {value} C"

topic, payload = make_message("device-01", 23.4)
print(topic)
print(payload)
print(validate(topic, payload))
```

Windows PowerShell에서는 `py device_message.py`, macOS·Linux에서는 `python3 device_message.py`를 실행합니다. 예상 결과입니다.

```text
devices/device-01/telemetry
{"data":{"temperature_c":23.4},"message_id":"msg-0001","schema_version":1,"sent_at":"2026-09-03T00:00:00Z"}
device-01: 23.4 C
```

[흔한 실수]
- 단위와 스키마 버전 없이 숫자만 보낸다.
- QoS 1이면 중복이 없다고 가정한다.
- 일회성 명령을 retained 메시지로 남긴다.
- `devices/#` 구독 권한을 모든 장치에 준다.

[보안 주의]
운영 환경에서는 TLS, 장치별 고유 자격증명, 브로커의 토픽 접근 제어를 사용합니다. 장치는 자기 토픽에만 최소 권한을 가져야 합니다. 토픽과 본문의 길이·형식·범위를 검증하고 명령 ID로 재실행을 막습니다. 비밀번호·토큰·개인정보를 토픽이나 로그에 넣지 않으며 실습은 본인 소유 로컬·격리 환경에서만 합니다.

[직접 해볼 과제]
습도 `humidity_percent`를 추가하고 0~100 범위를 검사하세요. 범위를 벗어난 값과 잘못된 토픽이 각각 예외를 내는지 기록합니다.

[확인문제]
1. 발행자와 구독자 사이에서 메시지를 중계하는 구성요소는 무엇인가요?
2. QoS 1 메시지에 `message_id`가 필요한 이유는 무엇인가요?
3. 일회성 장치 명령에 Retain을 피해야 하는 이유는 무엇인가요?

[다음 학습]
다음 CORE-008에서는 효율적인 검색과 정렬 방법을 배웁니다.

[공식 참고 자료]
- OASIS MQTT 5.0 표준: https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
- Mosquitto 발행 도구: https://www.mosquitto.org/man/mosquitto_pub-1.html
- NIST IoT 보안 기준: https://csrc.nist.gov/pubs/ir/8259/a/final

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
4,745
어제
6,862
최대
16,772
전체
770,696
Copyright © 소유하신 도메인. All rights reserved.