파일명 routes/chat.js (백엔드)
// 파일명 routes/chat.js
var express = require('express');
var router = express.Router();
const app = express();
const http = require('http');
const httpServer = http.createServer(app);
const io = require('socket.io')(httpServer, {path:'/socket', cors : {origins:'*:*'}});
// 클라이언트가 접속했을때 수행됨.
io.on('connection', (socket) => {
console.log("====================");
console.log(socket.id);
// 클라이언트에서 메시지가 도착했을때
socket.on('publish', function(data){
console.log(data);
// 모든 클라이언트에 메시지를 전송함
io.emit('subscribe',{
userid : data.data.userid,
username : data.data.username
});
})
});
httpServer.listen(3001, ()=>{
console.log('127.0.0.1:3001/socket');
});
module.exports = router;
파일명 app.js
// routes 등록
require('./routes/chat') // rest apt가 아님, url필요없음
파일명 main.js (프론트)
import { createApp } from 'vue'
import App from './App.vue'
import routes from './routes/index';
import stores from './stores/index';
import ElementPlus from 'element-plus';
import 'element-plus/theme-chalk/index.css';
// npm i --save socket.io => 벡엔드
// npm i --save socket.io-client@4.4.1 => 프런트
import io from 'socket.io-client';
// 소켓 설정
const socket = io("/", {transports:['websocket'], path:'/socket'});
const app = createApp(App);
// 컴포넌트에서 사용가능하도록 설정
app.config.globalProperties.$socket = socket;
app.use(routes);
app.use(stores);
app.use(ElementPlus);
app.mount('#app');
파일명 vue.config.js
// CORS => 같은 서버가 아니면 연동이 안됨.
// proxy를 설정하면 해결됨. 단, android등은 CORS를 반드시 설정해야 함
module.exports = {
devServer:{
proxy : {
// socket.io, websocket => 문자나 파일을 통신
// webrtc => 실시간 화상채팅
'/socket' : {
target:'http://localhost:3001',
changeOrigin :true,
logLevel : 'debug'
},
'/member' : { //rest
target:'http://localhost:3000',
changeOrigin :true,
logLevel : 'debug'
},
},
},
}
파일명 index.js
컴포넌트 등록
import Chat from '@/components/ChatView';
{path : '/chat', name : 'Chat', component:Chat},
파일명 ChatView.vue
<template>
<div>
<h3>채팅</h3>
<hr />
<input type="text" v-model="state.userid" />
<input type="text" v-model="state.message" @keyup.enter="handleSendMessage" />
<hr />
<table border="1">
<tr v-for="tmp in state.list" :key="tmp">
<td>{{tmp.userid}}</td>
<td>{{tmp.username}}</td>
</tr>
</table>
</div>
</template>
<script>
import { getCurrentInstance, onMounted, reactive } from '@vue/runtime-core'
export default {
setup () {
const state = reactive({
userid : '',
message:'',
list : [],
});
const app = getCurrentInstance();
const socket = app.appContext.config.globalProperties.$socket;
console.log(socket);
onMounted(()=>{
socket.on('subscribe', (recv) => {
console.log(recv);
state.list.push(recv);
});
})
const handleSendMessage = () => {
socket.emit('publish', {
data : {userid : state.userid, username : state.message}});
state.message = '';
}
return { state, handleSendMessage }
}
}
</script>
<style lang="scss" scoped>
</style>