우선 Socket.io는 JavaScript를 이용하여 브라우저 종류에 상관없이 실시간 웹을 구현할 수 있도
록 한 기술이다. 또, Socket.io는 WebSocket, FlashSocket, AJAX Long Polling, AJAX Multi part
Streaming, IFrame, JSONP Polling을 하나의 API로 추상화한 것이다.
(즉 브라우저와 웹 서버의 종류와 버전을 파악하여 가장 적합한 기술을 선택하여 사용하는 방식)
다시 말해 socket.io를 통해 개발을 하면 websocket이 지원이 되지 않는 브라우저에서도 메시지
를 양방향으로 주고 받을 수 있다.
구조는 node.js 기반의 frontend(Vue.js) - client, backend - server 로 나눠서 간다.
* Backend
우선 backend쪽을 보면, root의 app.js에 아래의 코드를 추가한다.
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
app.use(express.static(path.join(__dirname, 'public')));
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With"); next();
});
app.get('/', function(req, res) {
res.sendFile('Hi Chating App Server');
});
io.on('connection', function (socket) {
console.log('Connect from Client: ' + socket)
socket.on('chat', function (data) {
console.log('message from Client: ' + data.message)
var rtnMessage = {
message : data.message
,socketId : data.socketId
}; // 클라이언트에게 메시지를 전송한다
socket.broadcast.emit('chat', rtnMessage);
});
})
server.listen(3001, function() {
console.log('socket io server listening on port 3001')
})
server.listen(3001, function() {
console.log('socket io server listening on port 3001')
})
여기서 3001번 포트는 아래의 frontend프로젝트에서 소켓객체를 선언할때의 포트와 일치 해야 한다.
routes/index.js
var express = require('express');
var path = require('path');
var router = express.Router();
router.get('/', function (req, res, next) {
res.sendFile(path.join(__dirname, '../public', 'index.html'))
});
module.exports = router;
* Frontend
frontend쪽에서 필요한 라이브러리를 다운 받는다.(marterial은 디자인 관련 파일)
npm install --save vue-material vue-socket.io
src/main.js
import Vue from 'vue'
import App from './App.vue'
import VueMaterial from 'vue-material'
import 'vue-material/dist/vue-material.css'
import 'vue-material/dist/theme/black-green-light.css'
import Directives from '../plugin/directives'
import io from 'socket.io-client'
import router from './router'
var socket = io('http://localhost:3001')
Vue.config.productionTip = false
Vue.prototype.$socket = socket
Vue.use(VueMaterial)
Vue.use(Directives)
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
render: h => h(App)
}).$mount('#app')
socket의 선언부를 보면 위에서 명시한 backend쪽 socket port와 동일하게 맞춰줘야 한다.
src/components/Chat.vue
<template>
<div class="page-container">
<md-app>
<md-app-toolbar class="md-primary">
<div class="md-toolbar-row">
<span class="md-title">My Chat App</span>
</div>
</md-app-toolbar>
<md-app-content>
<md-field>
<label>Message</label>
<md-textarea v-model="textarea" disabled v-auto-scroll-bottom></md-textarea>
</md-field>
<md-field>
<label>Your Message</label>
<md-input v-model="message"></md-input>
<md-button class="md-primary md-raised" @click="sendMessage()">Submit</md-button>
</md-field>
</md-app-content>
</md-app>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
created () {
this.$socket.on('chat', (data) => {
this.textarea += '[' + data.socketId + ']' + data.message + '\n'
})
},
data () {
return {
textarea: '',
message: '',
socketId: ''
}
},
methods: {
sendMessage () {
this.$socket.emit('chat', {
message: this.message,
socketId: this.$socket.id
})
this.textarea += '[' + this.$socket.id + ']' + this.message + '\n'
this.message = ''
this.socketId = this.$socket.id
}
}
}
</script>
<style>
.md-app {
height: 800px;
border: 1px solid;
}
.md-textarea {
height: 300px;
}
</style>
서버에서 emit을 통해 client로 메세지를 전달 하였고 client에서 같은 이벤트를 사용하여 서버로부터 데이터를 받도록 한다.
src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import IndexPage from '@/components/IndexPage'
import LoginPage from '@/components/LoginPage'
import Chat from '@/components/Chat'
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'IndexPage',
component: IndexPage
},
{
path: '/loginPage',
name: 'LoginPage',
component: LoginPage
},
{
path: '/chat',
name: 'Chat',
component: Chat
}
]
})
router 설정
plugins/directive.js
module.exports = (Vue) => {
Vue.directive('auto-scroll-bottom', {
update: (el) => {
el.scrollTop = el.scrollHeight
}
})
}
스크롤관련js. 추가로 폴더 및 파일을 생성시켜야된다.
webpack을 통해 frontend프로젝트 build파일을 backend프로젝트의 public폴더 하위에
위치 시켜 실제 서버 구동은 backend의 서버만 구동하는 방향으로 했지만, 따로 따로
구성해도 된다.
*결과
참조 : https://javacpro.tistory.com/72
'Back > Node' 카테고리의 다른 글
node.js Sequelize - (include, attributes) (0) | 2020.10.30 |
---|---|
node.js Sequelize (0) | 2020.09.09 |
Node.js Express 서버 설치 (0) | 2019.02.17 |
NodeJs설치 (0) | 2019.02.17 |