Socket.IO개요

  • 웹소켓과 비슷하게 양방향 통신을 지원하나 웹소켓과는 다른 기술이라고 한다.
  • 웹소켓이 1:1통신에 적합하다면 socket.IO는 1:N으로 다른 클라이언트들에 브로드캐스팅을 하는 용도에 적합하다고 하는 것 같다.
  • Node.js로 개발되어 있으므로 socket.IO를 구동하려면 Node.js실행환경이 필요하다.

목표

  • socket.IO를 사용해서 샘플 프로그램을 만들어 본다.
  • https://socket.io/get-started/chat 를 참고로 하나하나 실행해본다.

샘플적용

Web Framework 적용하기

새로운 디렉토리를 만들고 이동한 후 package.json파일을 만든다.

{
  "name": "socket-chat-example",
  "version": "0.0.1",
  "description": "my first socket.io app",
  "dependencies": {}
}

express웹서버를 사용하자. 다음 명령으로 설치한다.

npm install express@4

index.js파일을 만들고 서비스한다.

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);

app.get('/', (req, res) => {
  res.send('<h1>Hello world</h1>');
});

server.listen(3000, () => {
  console.log('listening on *:3000');
});
node index.js

express서버구동

HTML 페이지 개발

index.js파일에서 send함수대신에 sendFile함수를 사용하도록 변경한다.

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

다음 코드를 index.html로 저장한다.

<!DOCTYPE html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }

      #form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
      #input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
      #input:focus { outline: none; }
      #form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }

      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages > li { padding: 0.5rem 1rem; }
      #messages > li:nth-child(odd) { background: #efefef; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form id="form" action="">
      <input id="input" autocomplete="off" /><button>Send</button>
    </form>
  </body>
</html>

chat윈도우개발

Socket.IO 적용하기

다음 명령으로 socket.io를 설치한다.

npm install socket.io

index.js코드를 다음과 같이 수정한다.

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io"); // 추가된 부분
const io = new Server(server); //추가된 부분

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
  console.log('a user connected');
});

server.listen(3000, () => {
  console.log('listening on *:3000');
});

index.html파일의 </body>이전에 다음 코드를 추가한다.

<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<script>
  var socket = io();
</script>

웹 브라우저로 http://localhost:3000에 접속하면 서버측에서 다음과 같은 로그를 확인할 수 있다.

node .\index.js
listening on *:3000
a user connected
a user connected
a user connected

다음 코드로 disconnect 이벤트도 캐치할 수 있다. index.js의 connection이벤트핸들링 부분을 다음 코드로 변경한다.

io.on('connection', (socket) => {
  console.log('a user connected');
  socket.on('disconnect', () => {
    console.log('user disconnected');
  });
});

서버를 재구동한 뒤 브라우저로 접속하거나 탭을 닫거나 해서 확인하면 다음과 같이 disconnect이벤트에도 잘 반응하는 것을 확인할 수 있다.

node .\index.js
listening on *:3000
a user connected
a user connected
a user connected
user disconnected

서버로 이벤트 발송(emit)

html 의 클라이언트측 js 코드를 다음과 같이 변경한다. 유저가 폼에서 메세지를 입력하고 전송버튼을 누르면 서버로 전송된다. socket.emit() 메서드를 통해 서버로 메세지를 전송할 수 있다.

var socket = io();
var form = document.getElementById('form');
var input = document.getElementById('input');

form.addEventListener('submit', function(e){
  e.preventDefault();
  if (input.value){
    socket.emit('chat message', input.value);
    input.value = '';
  }
});

서버측 js코드를 다음과 같이 바꾼다. chat message이벤트에 대한 핸들러가 추가되었다. 유저로부터 메세지를 받으면 서버 로그에 출력한다.


io.on('connection', (socket) => {
  console.log('a user connected');

  socket.on('disconnect', () => {
    console.log('user disconnected');
  });

  socket.on('chat message', (msg) => {
    console.log('message:' + msg);
  });
});

서버의 로그는 다음과 같다.

node .\index.js
listening on *:3000
a user connected
a user connected
message:hi
user disconnected
a user connected
message:hi there~

브로드캐스팅

브로드캐스팅을 위해서 Socket.IO는 io.emit()메서드를 제공한다. (특정 소켓을 제외한 모두에 보내고 싶을 때는 socket.broadcat.emit()을 사용한다고 한다. )

서버측 js코드를 다음과 같이 수정한다.

io.on('connection', (socket) => {
  socket.on('chat message', (msg) => {
    io.emit('chat message', msg);
  });
});

클라이언트 측 js코드에 다음 코드를 추가한다.

socket.on('chat message', function(msg) {
  var item = document.createElement('li');
  item.textContent = msg;
  messages.appendChild(item);
  window.scrollTo(0, document.body.scrollHeight);
});

서버를 재구동하고 테스트해보면 잘 동작한다.

브로드캐스팅