React와 MQTT over WebSocket으로 실시간 데이터 표시
React 앱에서 MQTT over WebSocket을 통해 센서·디바이스 실시간 데이터를 구독하고 렌더링하는 방법, 설정과 보안 고려사항을 담은 설명서
목차
소개
이 글은 React 애플리케이션에서 MQTT 브로커와 WebSocket을 연결해 실시간 데이터를 수신하고 화면에 표시하는 과정을 쉽게 이해하도록 정리한다. 처음 접하는 개발자도 흐름을 따라가며 예제 코드를 통해 구현할 수 있도록 구성되었다. 주요 키워드로는 react mqtt websocket 예제, react mqtt 실시간 업데이트, web mqtt react 튜토리얼이 자연스럽게 포함된다.
MQTT와 WebSocket 개념 정리
MQTT란 무엇인가
MQTT는 경량 메시징 프로토콜로 센서·IoT 환경에서 자주 사용된다. 퍼블리시/서브스크라이브 모델을 통해 토픽 기반 메시지 전달을 제공한다.
왜 WebSocket을 사용하는가
브라우저 환경에서는 TCP 소켓을 직접 열 수 없다. 따라서 MQTT 브로커에 WebSocket 인터페이스가 있으면 브라우저에서 실시간 연결을 유지하며 메시지를 주고받을 수 있다. 이 조합이 React 기반 실시간 UI와 잘 맞는다.
아키텍처 개요
간단한 구성은 다음과 같다.
- 센서/디바이스 → MQTT 브로커 (TCP)
- 브라우저(React) ↔ MQTT 브로커 (WebSocket)
- 브로커는 WebSocket 포트를 통해 브라우저 연결을 수용하고 토픽을 배포
사전 준비
- 브로커: Mosquitto, EMQX 등 WebSocket 지원 여부 확인
- React 프로젝트: Create React App 또는 Vite
- 클라이언트 라이브러리: mqtt.js
브로커 설정 예시 (Mosquitto)
Mosquitto에서 WebSocket을 활성화하려면 설정 파일에 listener를 추가하면 된다. 예시는 로컬 개발용으로 간단히 제시한다.
listener 9001
protocol websockets
React 구현 (핵심 코드)
아래 코드는 mqtt 패키지를 사용해 WebSocket으로 브로커에 연결하고 메시지를 수신하여 화면에 실시간 업데이트를 반영하는 최소 예제이다. JSX의 < > 문자는 이스케이프 처리되어 있다.
import React, { useEffect, useState } from 'react'
import mqtt from 'mqtt'
export default function MqttLive() {
const [messages, setMessages] = useState([])
useEffect(() => {
// 브로커 주소 예: ws://localhost:9001/mqtt
const client = mqtt.connect('ws://localhost:9001')
client.on('connect', () => {
client.subscribe('sensors/temperature', { qos: 0 })
})
client.on('message', (topic, payload) => {
const text = payload.toString()
setMessages(prev => [{ topic, text, time: Date.now() }, ...prev].slice(0, 50))
})
client.on('error', err => {
console.error('MQTT error', err)
client.end()
})
return () => client.end()
}, [])
return (
<div>
<h3>실시간 센서 데이터</h3>
<ul>
{messages.map((m, i) => (
<li key={i}>{m.topic}: {m.text} <small>{new Date(m.time).toLocaleTimeString()}</small></li>
))}
</ul>
</div>
)
}
핵심 포인트
- connect 시 WebSocket URL(ws:// 또는 wss://)을 사용한다.
- 구독(subscribe)은 연결 후 실행한다.
- on('message')에서 수신한 데이터를 state로 관리해 UI를 업데이트한다.
- 정리(cleanup)에서 client.end()로 연결을 닫아 메모리 누수를 방지한다.
실시간 업데이트 고려사항
UI 성능과 데이터 흐름을 관리하는 몇 가지 팁.
- 빈번한 메시지는 버퍼링하거나 샘플링해 렌더링 횟수를 줄인다.
- 복수 컴포넌트가 같은 메시지를 소비하면 Context 또는 전역 상태 관리로 중복 구독을 피한다.
- 토픽 네이밍 규칙을 명확히 해 필터링을 쉽게 한다.
보안 및 배포
프로덕션 환경에서는 wss://를 사용해 TLS로 암호화해야 한다. 인증과 권한 관리를 위해 브로커의 인증 플러그인이나 토큰 기반 인증을 검토한다. 퍼블릭 인터넷에 브로커를 노출할 때는 방화벽과 접근 제어를 설정한다.
문제 해결(트러블슈팅)
- 연결 불가: 브로커 WebSocket 포트와 경로를 확인한다.
- 구독은 성공하나 메시지가 없음: 퍼블리셔가 동일한 토픽과 QoS로 발행하는지 확인한다.
- 브라우저 콘솔에서 CORS나 Mixed Content 관련 에러가 발생하면 브로커와 프론트엔드의 프로토콜·포트 정책을 점검한다.
마무리
Mqtt와 WebSocket을 활용하면 React 앱에서 실시간 데이터를 효율적으로 표시할 수 있다. 예제 코드를 기반으로 브로커 설정, 보안, 성능 최적화 요소를 차례로 적용하면 안정적인 실시간 인터페이스를 구축할 수 있다. 필요한 경우 이 구조를 확장해 인증, 권한, 로깅을 추가하면 운영 안정성이 높아진다.