스마트홈 기기가 많아지면 이런 생각이 든다. "온도계, 창문 센서, 조명 — 이 녀석들이 서로 직접 대화하게 할 수는 없나?" 각각 다른 앱을 열어 확인하는 대신, 한곳에 메시지를 모으고 필요한 사람만 받아보는 구조 말이다. 그 구조가 MQTT이고, 그 메시지 교환소 역할을 하는 대표 소프트웨어가 Mosquitto다. 이 시리즈의 마지막 화는 도커로 MQTT 브로커를 세우고 홈어시스턴트와 연결하는 과정이다.
필요한 것은 도커 컨테이너 하나다.
MQTT는 IoT 기기들이 메시지를 주고받는 표준 프로토콜이고, Mosquitto는 그 메시지를 중개하는 브로커(교환소) 소프트웨어다. Eclipse 재단이 관리하는 오픈소스로, IoT 세계의 사실상 표준으로 쓰인다.
MQTT의 핵심 개념은 셋이다.
| 개념 | 뜻 | 예 |
|---|---|---|
| 발행(Publish) | 기기가 토픽에 메시지를 올림 | 온도계가 home/거실/온도에 23.5 발행 |
| 구독(Subscribe) | 관심 토픽을 등록해두면 자동 수신 | HA가 home/+/온도 구독 |
| 브로커 | 발행과 구독을 중개하는 교환소 | Mosquitto |
발신자와 수신자가 서로를 몰라도 된다는 점이 핵심이다. 새 기기를 추가해도 기존 기기는 아무 설정도 바꿀 필요가 없다 — 브로커에 올리고, 받고 싶은 쪽이 구독하면 끝이다.
| 기능 | 내용 |
|---|---|
| 경량 | 패킷이 작아 소형 기기·저전력 환경에 적합 |
| QoS 레벨 | 전달 보증 수준 선택(0: 최선, 1: 최소 1회, 2: 정확히 1회) |
| Retain | 마지막 메시지를 브로커가 기억 — 새 구독자가 즉시 현재 값 수신 |
| 유언장(LWT) | 기기가 갑자기 끊기면 "오프라인" 메시지를 대신 발행 |
| 인증·TLS | 계정 인증과 암호화 지원 |
flowchart LR
subgraph DEV["기기들"]
T["온도·습도 센서"]
S["스마트플러그"]
E["ESPHome 기기"]
end
subgraph SRV["Docker 서버"]
MB["Mosquitto 브로커"]
HA["Home Assistant"]
S2["스크립트 · 자동화"]
end
T -->|발행 home/온도| MB
S -->|발행 home/전력| MB
E -->|발행| MB
MB -->|구독| HA
MB -->|구독| S2
HA -->|명령 발행| MB
기기들은 브로커에만 이야기하고, 구독자들(HA, 스크립트)이 필요한 토픽만 받아간다.
services:
mosquitto:
image: eclipse-mosquitto:2
container_name: mosquitto
restart: unless-stopped
volumes:
- /opt/docker/mosquitto/config:/mosquitto/config
- /opt/docker/mosquitto/data:/mosquitto/data
ports:
- "1883:1883" # MQTT
설정 파일(/opt/docker/mosquitto/config/mosquitto.conf):
listener 1883
allow_anonymous false
password_file /mosquitto/config/passwd
persistence true
persistence_location /mosquitto/data/
사용자 생성:
docker exec -it mosquitto mosquitto_passwd -c /mosquitto/config/passwd 사용자이름
docker restart mosquitto
allow_anonymous false는 필수다. 익명을 허용한 채 두면 집안 기기 제어 채널이 누구나 열려 있는 셈이 된다.
HA 설정 → 기기 및 서비스 → 통합 추가 → "MQTT" → 브로커 주소(서버 IP)·계정 입력. 이제 Mosquitto를 거치는 기기들이 HA에 자동으로 나타나기 시작한다. 특히 ESPHome·Tasmota 같은 DIY 펌웨어 기기는 HA 자동 검색 토픽(homeassistant/)만 발행하면 별도 설정 없이 HA에 등록된다.
커맨드라인 테스트 도구가 기본 제공된다:
# 구독 대기 (다른 터미널에서)
docker exec -it mosquitto mosquitto_sub -h localhost -u 사용자 -P 비번 -t "home/거실/#" -v
# 발행 (테스트)
docker exec -it mosquitto mosquitto_pub -h localhost -u 사용자 -P 비번 -t "home/거실/온도" -m "23.5"
구독 중인 화면에 발행한 값이 찍히면 전 구간이 정상이다.
토픽 naming을 처음에 잘 설계하자. home/위치/기기종류 같은 계층 구조로 시작하면, 나중에 home/+/온도(전체 방 온도) 같은 와일드카드 구독이 자연스럽게 동작한다. 뒤늦게 구조를 바꾸면 기기 설정을 전부 다시 해야 한다.
retain은 상태에만, 이벤트에는 쓰지 않는다. "현재 온도"처럼 마지막 값이 의미 있는 토픽에는 retain을 걸어 새 구독자가 즉시 값을 받게 하고, "버튼 눌림" 같은 순간 이벤트에는 쓰지 않는다 — retain 걸린 이벤트는 나중에 접속한 누군가에게 유령 알림이 된다.
브로커 하나면 충분하다. 기기가 많아져도 Mosquitto 하나로 수만 연결을 감당한다. 시스템을 여러 개로 쪼개는 것보다, 토픽 구조를 잘 잡고 하나를 잘 쓰는 편이 운영이 편하다.
| 증상 | 원인 | 해결 |
|---|---|---|
| 연결이 거부된다 | 인증 실패·익명 차단 | 계정 생성과 클라이언트 자격증명 확인 |
| HA에 기기가 안 나타난다 | discovery 토픽 미발행 | 기기 펌웨어의 HA discovery 설정 확인 |
| 오래된 값이 계속 온다 | retain 메시지 잔존 | mosquitto_pub -r -n으로 해당 토픽 삭제 |
| 가끔 연결이 끊긴다 | keepalive 타임아웃 | 클라이언트 keepalive 간격 조정 |
| 외부에서 접속해야 한다 | 보안 리스크 | TLS+인증 필수, 가능하면 VPN 경유 |
"기기들이 정해진 주소(토픽)에 메시지를 붙여 올리고, 원하는 주소를 구독하는 시스템"이다. 신문사(브로커)에 기사(메시지)를 올리면, 구독자가 자동으로 받아보는 모델이다.
HTTP는 요청한 사람이 응답을 받고 끝나는 일회성 대화다. MQTT는 연결을 유지하며 상태 변화가 생기면 밀어준다. 기기는 대부분 "상태가 변하면 알려줘야 하는" 존재라 MQTT가 잘 맞는다.
가장 큰 도움이 된다. MQTT 기반 기기(ESPHome, Zigbee2MQTT 연동 등)는 클라우드 없이 완전 로컬로 동작하며, 인터넷이 끊겨도 집안 자동화는 계속 돌아간다.
서버 한 대로 충분하다 연재 목차 (완결) — 시리즈 소개 · 1화. Home Assistant · 2화. Frigate + go2rtc · 3화. Seafile 13 · 4화. Immich · 5화. Vaultwarden · 6화. Mailcow · 7화. MinIO · 8화. Umami · 9화. GitLab · 10화. Portainer · 11화. Komodo · 12화. n8n
시리즈 완결까지 읽어주셔서 감사합니다. 홈어시스턴트 MQTT 통합과 ESPHome 조합의 확장 편은 기회가 되면 다루겠습니다.
| 이전 | 12화. n8n — 반복 업무를 워크플로로. 자동화의 자동화 | 2026-10-01 | |
|---|---|---|---|
| 다음 | | lordly | 2026-09-29 |