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
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>
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);
});
서버를 재구동하고 테스트해보면 잘 동작한다.