음악, 삶, 개발
socket.io 를 이용한 단체 채팅방 만들기 본문
< 개발 환경 설치 >
server (Max) : npm install socket.io
client (Vue) : npm install socket.io-client
< 공식문서 & 참고 자료 >
// sending to sender-client only
socket.emit('message', "this is a test");
// sending to all clients except sender
socket.broadcast.emit('message', "this is a test");
// sending to all clients in 'game' room(channel) except sender
socket.broadcast.to('game').emit('message', 'nice game');
// sending to sender client, only if they are in 'game' room(channel)
socket.to('game').emit('message', 'enjoy the game');
// sending to individual socketid
socket.broadcast.to(socketid).emit('message', 'for your eyes only');
// sending to all clients, include sender
io.emit('message', "this is a test");
// sending to all clients in 'game' room(channel), include sender
io.in('game').emit('message', 'cool game');
// sending to all clients in namespace 'myNamespace', include sender
io.of('myNamespace').emit('message', 'gg');
// send to all connected clients
socket.emit();
// send to all connected clients except the one that sent the message
socket.broadcast.emit();
// event listener, can be called on client to execute on server
socket.on();
//for emiting to specific clients
io.sockets.socket();
// send to all connected clients (same as socket.emit)
io.sockets.emit();
//initial connection from a client.
io.sockets.on();
< 단체 채팅방 만들기 >
모 컴퓨터공학과 3학년인 대학생 철수는 학교에서 아웃사이더였고,
온라인에서 친구를 사귀고자 단체방을 개발하였다.
이 단체방의 주소는 http://localhost:3000/ 로 결정하였다.
/* server.js */
const express = require('express');
const app = express();
const port = 3000;
const server = app.listen(port);
const io = require('socket.io')(server);
const clientModel = 'vue';
app.use(express.static(clientModel)); // Proive vue folder as client model.
철수는 사람들이 단체방에 접속한 순간('connection'),
자동으로 '철수의 단체방에 오신것을 환영합니다 ^^!' 라는 인사말을 발신(emit)하도록 등록하였다.
/* server.js */
// 자동 인사말
// io.on is callback whenever new client gets connected.
io.on("connection", (socket) => {
socket.emit('철수', '철수의 단체방에 오신것을 환영합니다 ^^!');
});
또한 자신이 보낸 자동인사말을 새로 접속한 사람이 잘 전달받을수있도록 설정하였다.
<!-- App.vue -->
<script>
import io from 'socket.io-client'
export default {
setup() {
const socket = io();
socket.on('철수', (message) => {
console.log(message);
});
}
}
</script>
조금 기디리자, "민수" 라는 사용자가 단체방에 참여하였고,
철수의 자동 인사말이 민수에게 전달되었다.
이를 들은 민수는 철수에게 '아 반갑습니다 저는 민수에요 ^^! ㅋㅋ' 라고 대답하였다.
<!-- App.vue -->
<script>
import io from 'socket.io-client'
export default {
setup() {
const socket = io();
// 방장에게 메세지 보내기
socket.emit('민수', '아 반갑습니다 저는 민수에요 ^^! ㅋㅋ');
}
}
</script>
/* server.js */
// 접속한 민수로 부터 메세지 받기
io.on('connection', (socket) => {
socket.on('민수', (message) => {
console.log(message);
});
});
조금 더 기다리자, 영희가 단체방에 접속하였고,
철수의 자동인사말이 민수에게는 아까 했기때문에, 영희에게만 전달되었다.
철수는 학교에서 아웃사이더인데,
채팅방에 2명이나 있으니 들뜬 마음에
채팅방 사람들에게 '두 분이 오셔서 너무 좋네요~! ㅋㅋ' 라고 말하였다.
// 모두에게 메세지 보내기.
function sendMessageToAll() {
io.emit('철수', '두 분이 오셔서 너무 좋네요~! ㅋㅋ');
}
sendMessageToAll();
위와 같이 철수, 영희, 민수가 단체방에서 수다를 떨고있다.
철수는 어느날 단체방을 만든 방장이다.
철수와 달리, 민수와 영희는 추후 이 방에 접속하여 참여하게된 참여자다.
이 셋은 오랜 시간 이 단체방에서 대화를 하며, 서로를 알아가게되었다.
오랜 시간이 흐른뒤, 민수는 영희가 자신의 이상형이라는것을 알게되었고,
영희에게 고백하기로 하였다.
하지만 문제는 철수또한
< Client 와 Server >
Server 와 Client 의 의미를 가장 잘 이해할수있는것이 채팅 프로그램이다.
< 우리가 생각하는 현실 vs 실제 현실 : Server 는 모든것을 알수있다 >
우리가 생각하는 현실 (은밀한 Client 간에 대화) : Client 철수 <-> Client 영희
실제 현실 (Server 를 통해 전파되는 대화) : Client 철수 <-> Server <-> Client 영희
Client 는 다른 Client 에게 직접적으로 메세지를 전달할수없으며, 모든것은 Server 로 보내지고,
이 Server 가 다른 Client 또는 다수의 Client 들에게 전파.
< Server 는 하나님. 그는 모든것을 알수있고, 할수있다 >
Server 는 Client 의 말을 다른 Client 에게 전달할뿐 아니라,
모든 Client 들에게 한번에 공지사항을 전파할수있다.
< Server 가 Client들 에게 공지사항을 전달하는 방법 >
/* server.js */
io.on("connection", (socket) => {
socket.emit('fromServer', "Server : 모두에게 전하는 공지사항 입니다");
});
< Server 가 한 Client 에게 들은 말을 다른 Client 들에게 전달하는 방법 >
/* server.js */
io.on('connection', function (socket) {
socket.on('fromClient', function (clientMessage) {
socket.broadcast.emit('fromServer', `Server : 여러분, Client ${socket.id} 님이 ${clientMessage} 라고 하네요~`);
});
});
< 우리가 하고싶은것은 Vue 와 Max 의 대화 >
Vue 와 Max 의 대화 = Vue 프로젝트와 Max 프로젝트간의 대화
Vue 프로젝트와 Max 프로젝트간의 대화 = Server 와 Client 의 대화
Serve 와 Client 의 대화 = App.vue 와 my-node-server.js 의 대화
Client 는 Browser 이다.
따라서 Client 는 한명이 아니다.
App.vue <-> my-node-server.js
위의 대화는 불가능, 서로를 모르기때문에.
따라서 중간 프로그램이 필요.
App.vue <-> socket.io-client <-> socket-io <-> my-node-server.js <-> [node.script] <-> inlet, outlet
socket-io 는 한명. 즉 Server. 즉 Max.
socket-io 는 여러명. 즉 Browser.
< Vue 프로젝트와 Max 프로젝트가 필요한 것들 >
1. Vue 프로젝트 : socket.io-client
<script>
import io from 'socket.io-client';
export default {
setup() {
const socket = io();
// Do something to send message to Max here!
}
}
</script>
2. Max 프로젝트 : socket.io
< 최종 코드 >
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
<div id="app"></div>
</body>
</html>
설명..
<!-- App.vue -->
<template>
<button @click="setDisplayMessage('One')"> One </button>
<button @click="setDisplayMessage('Two')"> Two </button>
<button @click="setDisplayMessage('Three')"> Three </button>
<button @click="setDisplayMessage('Four')"> Four </button>
<div v-text="displayMessage"></div>
</template>
<script>
import { ref } from 'vue';
import io from 'socket.io-client';
export default {
setup() {
const socket = io();
const displayMessage = ref('Click any button..');
// Send message to Max.
function setDisplayMessage(messageToDisplay) {
displayMessage.value = messageToDisplay;
socket.emit('fromVue', messageToDisplay);
}
// Get message from Max.
socket.on('fromMax', function (msg) {
displayMessage.value = msg;
console.log('From Max!');
});
return { displayMessage, setDisplayMessage };
}
}
</script>
설명..
/* main.js */
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app');
설명..
/* my-node-server.js */
const maxApi = require('max-api');
const express = require('express');
const app = express();
const port = 3000;
const server = app.listen(port);
const io = require('socket.io')(server);
/* Proive vue folder as frontEnd */
app.use(express.static('vue'));
/* Send message to all clients */
io.on("connection", (socket) => {
maxApi.addHandler('toVue', function (msg) {
socket.emit('fromMax', msg);
});
});
/* Get message from a client */
io.on('connection', function (socket) {
socket.on('fromVue', function (msg) {
maxApi.outlet(msg);
// Broadcast message which came from this client, to all other clients except him.
socket.broadcast.emit('fromMax', msg);
});
});
설명..
설명..
< Vue 와 Max 의 대화 : 단체방 >
우리가 원하는 Vue 와 Max 가 대화를 한다는것은,
결과적으로 단체 채팅방을 만드는것이다.
아래의 그림을 보자.
위의 그림은, 간단히 Vue 와 Max 를 사용하여 구현한것이다.
브라우저 3개의 각 버튼을 클릭하면 모두가 이 결과를 적용하고,
Max 에서도 메세지를 보내면, 브라우저 3개에 모두 이 결과가 적용된다.
이는 결국 단체방에서 여러명이 채팅을 하고있는 상황과 동일하다.
따라서 우리는 Node.js 를 통해 채팅 프로그램을 만드는 방법을 이해해야한다.
결국 Max 와 Vue 의 대화도 일종의 채팅 프로그램, 즉 단체방이기때문이다.