Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- allow_anonymouse
- c# datagridview 데이터 넣기
- AntDesign
- Replication
- datagridview 직접입력
- pm2 설치
- pm2 시작
- transfer
- html #select #option #multiple
- DataGridView 직접 입력
- listener 1883
- 1883
- pm2 상태 확인
- setInterval 중지
- 맥 어드레스
- setInterval 정지
- mosquitto
- mySQL_Replication
- pm2
- invalid data
- setInterval 외부 정지
- setInterval clear
- 서버동기화
- DatePicker
- 공인IP
- mosquitto.conf
- pm2 확인
- map이 undefined가 뜰 때
- 데이터테이블 데이터 넣기
- timepicker
Archives
- Today
- Total
개발 노트
[Next.js] web worker을 이용한 mqtt와 웹소켓 적용하기 본문
mqtt
web socket
참고: https://ko.wikipedia.org/wiki/%EC%9B%B9%EC%86%8C%EC%BC%93
web worker
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
web worker 적용하기
1. 기존에 Mqtt와 웹소켓을 적용한 코드
'use client';
import mqtt, { MqttClient } from 'mqtt';
import React, { useEffect, useState } from 'react';
const mqttUri = 'ws://127.0.0.1:9001';
const options: mqtt.IClientOptions = {
clientId: 'nextjs',
reconnectPeriod: 2000,
};
const Mqtt: React.FC = () => {
const [messages, setMessages] = useState<string[]>(['init']);
const addMessage = () => {
const newMessages = [...messages, Math.random().toString()];
setMessages(newMessages);
};
useEffect(() => {
const client: MqttClient | undefined = mqtt.connect(mqttUri, options);
console.dir(client);
client.subscribe('#');
client.on('message', (topic, message) => {
setMessages((prevMessages) => [...prevMessages,topic+ ' : ' +message.toString()]);
});
return () => {
if (client) {
client.unsubscribe('#');
client.end();
}
};
}, []);
return (
<div>
<button
className='border'
onClick={addMessage}>addMessage</button>
<h2>Received Messages: </h2>
<ul>
{messages.map((message, index) => (
<li key={index}>{message}</li>
))}
</ul>
</div>
);
};
export default Mqtt;
2. public에 mqttWorker.ts만들기
// mqttWorker.ts
import mqtt, { MqttClient } from 'mqtt';
const mqttUri = 'ws://127.0.0.1:9001';
const options: mqtt.IClientOptions = {
clientId: 'nextjs',
reconnectPeriod: 2000,
};
self.addEventListener('message', (e) => {
const client: MqttClient | undefined = mqtt.connect(mqttUri, options);
client.subscribe('#');
client.on('connect',()=>{
console.log('connected');
})
client.on('error', (error) => {
postMessage('Error: ' + error.message);
});
client.on('message', (topic, message) => {
postMessage(topic + ' : ' + message.toString());
});
});
3. mqttWorker를 빌드하기 위해 webpack.worker.config.js만들기
const WorkerPlugin = require('worker-plugin');
const path = require('path');
module.exports = {
mode: 'production',
target: 'webworker',
entry: './public/mqttWorker.ts',
output: {
filename: 'mqttWorker.built.js',
path: path.resolve(__dirname, 'public'),
},
resolve: {
extensions: ['.ts', '.tsx', '.js'],
},
module: {
rules: [
{ test: /\.tsx?$/, loader: 'ts-loader' },
],
},
plugins: [
new WorkerPlugin()
]
};
4. build용 package설치하기
pnpm add webpack webpack-cli worker-plugin ts-loader
//package.json
{
"name": "controlweb",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"build:worker": "webpack --config webpack.worker.config.js"
},
"dependencies": {
"mqtt": "^5.3.5",
"next": "14.1.0",
"react": "^18",
"react-dom": "^18",
"worker-plugin": "^5.0.1",
"zustand": "^4.5.0"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"eslint": "^8",
"eslint-config-next": "14.1.0",
"postcss": "^8",
"tailwindcss": "^3.3.0",
"ts-loader": "^9.5.1",
"typescript": "^5",
"webpack": "^5.90.1",
"webpack-cli": "^5.1.4"
}
}
5. src\component\MqttWorker.tsx만들기
'use client';
import React, { useEffect, useRef } from 'react';
import { useMqttStore } from '@/store/useMqttStore';
const MqttWorker: React.FC = () => {
const { messages, addMessage } = useMqttStore();
const workerRef = useRef<Worker | null>(null); // 웹 워커 참조를 저장하는 ref
useEffect(() => {
const URL = '/mqttWorker.built.js';
const worker = new Worker(URL);
workerRef.current = worker; // 웹 워커 객체를 ref에 저장
worker.onmessage = function (event) {
addMessage(event.data); // Zustand 스토어의 addMessage 액션 사용
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const startMqtt = () => {
if (workerRef.current) {
workerRef.current.postMessage({ CMD: 'MQTT_START' }); // 웹 워커에 메시지 보내기
}
};
const stopMqtt = () => {
if (workerRef.current) {
workerRef.current.postMessage({ CMD: 'MQTT_STOP' }); // 웹 워커에 메시지 보내기
}
};
const subscribeMqtt = () => {
if (workerRef.current) {
workerRef.current.postMessage({
CMD: 'MQTT_SUBSCIBE',
DATA: ['dawoon/ALIVE/#', 'dawoon/Robot/#', '/dawoon/RMAN/#', 'dawoon/Feeder/#'],
}); // 웹 워커에 메시지 보내기
}
};
return (
<div className='relative flex flex-col w-full'>
<ul className='fixed flex gap-2 justify-center w-full bg-[#d6dbdc] p-2 shadow-lg'>
<li >
<button
className='border bg-white px-2.5 py-1.5 rounded-3xl shadow-xl border-gray-400 hover:bg-gray-600 hover:text-white active:bg-[#121212] active:text-white'
onClick={startMqtt}>
startMqtt
</button>
</li>
<li>
<button
className='border bg-white px-2.5 py-1.5 rounded-3xl shadow-xl border-gray-400 hover:bg-gray-600 hover:text-white active:bg-[#121212] active:text-white'
onClick={stopMqtt}>
stopMqtt
</button>
</li>
<li>
<button
className='border bg-white px-2.5 py-1.5 rounded-3xl shadow-xl border-gray-400 hover:bg-gray-600 hover:text-white active:bg-[#121212] active:text-white'
onClick={subscribeMqtt}>
subscribeMqtt
</button>
</li>
</ul>
<h2 className='ml-2 text-lg font-semibold mt-16'>Received Messages: </h2>
<ul className='flex flex-col gap-y-2 px-2'>
{messages.map((message: string, index: number) => (
<li
className='bg-white border px-2.5 py-1.5 rounded-xl'
key={index}>
{message}
</li>
))}
</ul>
</div>
);
};
export default MqttWorker;
6. Mqtt에서 받아온 값을 전역으로 관리하기 위해 useMqttStore.tsx만들기
// useMqttStore.ts
import { create } from 'zustand';
type Store = {
messages: string[];
addMessage: (message: string) => void;
};
export const useMqttStore = create<Store>((set) => ({
messages: [],
addMessage: (message) => set((state) => ({ messages: [...state.messages, message] })),
}));
'React' 카테고리의 다른 글
[실패]mqtt로 받은 메세지 컴포넌트 내부에 전달 (0) | 2024.02.23 |
---|---|
MQTT/web-worker 다중 컴포넌트 연동 (0) | 2024.02.22 |
webWorker관련 참고자료 (0) | 2024.02.05 |
Next.js 13 이상 localization 적용하기 (0) | 2024.01.22 |
Next.js 13 이상 국제화(i18n) 적용 (0) | 2024.01.19 |