통합구현 2022/03/15(chat)

무간·2022년 3월 15일

파일명 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>
profile
당신을 한 줄로 소개해보세요

0개의 댓글