diff --git a/WebSocket.js b/WebSocket.js new file mode 100644 index 0000000000000000000000000000000000000000..dc74200df3a1c104a9f5eff66f9d3a4d8461e20d --- /dev/null +++ b/WebSocket.js @@ -0,0 +1,83 @@ +const WebSocket = require('ws'); +const mongoose = require('mongoose'); + +class WebSocketServer { + constructor(server) { + this.wss = new WebSocket.Server({ server }); + this.clients = new Set(); // 모든 클라이언트 관리 + + this.wss.on('connection', (ws) => { + console.log('새로운 클라이언트 연결됨'); + this.clients.add(ws); + + ws.on('message', (message) => { + try { + const data = JSON.parse(message); + this.handleMessage(data, ws); + } catch (error) { + console.error('메시지 처리 중 오류:', error); + } + }); + + ws.on('close', () => { + this.clients.delete(ws); + console.log('클라이언트 연결 해제됨'); + }); + }); + + this.setupChangeStream(); + } + + handleMessage(data, ws) { + // 메시지 타입에 따른 처리 + switch (data.type) { + case 'update': + case 'delete': + case 'addPlace': + case 'removePlace': + case 'create': + // 다른 모든 클라이언트에게 변경사항 브로드캐스트 + this.broadcast(data, ws); + break; + } + } + + broadcast(data, sender) { + this.clients.forEach(client => { + if (client !== sender && client.readyState === WebSocket.OPEN) { + client.send(JSON.stringify(data)); + } + }); + } + + setupChangeStream() { + const pipeline = [ + { + $match: { + 'operationType': { $in: ['update', 'insert', 'delete'] } + } + } + ]; + + const changeStream = mongoose.model('Trip').watch(pipeline, { + fullDocument: 'updateLookup' + }); + + changeStream.on('change', (change) => { + const message = { + type: change.operationType, + documentId: change.documentKey._id.toString(), + data: change.fullDocument + }; + + // 모든 클라이언트에게 변경사항 전송 + this.clients.forEach(client => { + if (client.readyState === WebSocket.OPEN) { + client.send(JSON.stringify(message)); + } + }); + }); + } +} + +module.exports = WebSocketServer; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 37f9a02c71cb8fc2ec2a05249491061c97c3f6ee..bf1c37f9a32e05583ee59950450ed27d262469ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,8 @@ "mongodb": "^6.11.0", "mongoose": "^8.8.1", "passport": "^0.7.0", - "passport-google-oauth20": "^2.0.0" + "passport-google-oauth20": "^2.0.0", + "ws": "^8.18.0" } }, "node_modules/@mapbox/node-pre-gyp": { @@ -2092,6 +2093,27 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 06665b6817a399db4b322ae148faa9d899c920c0..e4d3946e8f8d09a719642619c27ef73bf317d285 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "mongodb": "^6.11.0", "mongoose": "^8.8.1", "passport": "^0.7.0", - "passport-google-oauth20": "^2.0.0" + "passport-google-oauth20": "^2.0.0", + "ws": "^8.18.0" }, "scripts": { "start": "node login.js"