음악, 삶, 개발

socket.io 를 이용한 단체 채팅방 만들기 본문

개발 Web/Vue.js 공부방

socket.io 를 이용한 단체 채팅방 만들기

Lee_____ 2020. 11. 23. 10:17

< 개발 환경 설치 >

 

server (Max) : npm install socket.io

client  (Vue) : npm install socket.io-client


< 공식문서 & 참고 자료 >

 

server-api

client-api

// 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 의 대화도 일종의 채팅 프로그램, 즉 단체방이기때문이다.