노드에서의 웹소켓(양방향 통신) 사용은 ws나 Socket.io같은 패키지를 통해 가능하다.
간단한 웹 소켓을 사용하고자 할 땐 ws 패키지를 이용하면 되지만, 구현하고자 하는 서비스가 조금 더 복잡해진다면 Socket.IO를 사용하는 것이 편하다.
Socket.IO로 하는 일을 ws 패키지로 할 수 없는 건 아니지만 Socket.IO가 더 편의 기능이 많이 추가돼있기 때문이다. (그래서 이번 플젝에서는 Socket.io로 채팅을 구현하기로 결정했다~)
나는 단순히 로컬로 접속하여 Socket.io를 이용한 웹소켓을 연습해봤다.
먼저 Socket.IO를 설치!
$ npm i socket.io
그리고 socket.js
에서 ws 패키지 대신 Socket.IO를 연결한다.
//socket.js
const SocketIO = require('socket.io');
module.exports = (server) => {
const io = SocketIO(server, { path: '/socket.io' });
// path는 클라이언트와 연결할 수 있는 경로를 의미
// 1. 연결
io.on('connection', (socket) => {
const req = socket.request;
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
console.log('새로운 클라이언트 접속!', ip, socket.id);
// 2. 이벤트 리스너 붙이기
socket.on('disconnect', () => {
console.log('클라이언트 접속 해제', ip, socket.id);
clearInterval(socket.interval);
});
socket.on('error', (error) => {
console.log(error);
});
socket.on('reply', (data) => {
console.log(data);
});
// 3. 3초 간격으로 클라이언트에게 이벤트 보내기
socket.interval = setInterval(() => {
// 클라이언트가 이 메시지를 받으려면 'news' 이벤트리스터를 만들어둬야 함.
socket.emit('news', 'Hello SocketIO.IO');
}, 3000);
});
};
npm start
// views/index.pug
doctype
html
head
meta(charset='utf-8')
title GIF Chat
body
div Press F12 and check console tab and network tab.
script(src='/socket.io/socket.io.js')
script.
// ws와 달리 프로토콜이 http네 ^_^
var socket = io.connect('http://localhost:3000', {
path:'/socket.io',
});
// socket 객체에 이벤트 리스너 붙이기!
socket.on('news', function (data) {
console.log(data);
socket.emit('reply', 'Hello Node.JS');
});
클라이언트가 서버에 접속시
console.log('새로운 클라이언트 접속!', ip, socket.id);
이 실행돼서 콘솔에 저렇게 찍힌다.
::1 은 ip(localhost), RE어쩌구 는 소켓 고유 아이디!
Socket.IO는 일단 먼저 폴링 방식으로 서버와 연결한다. 그렇기 때문에 코드에서 HTTP 프로토콜을 사용한 것!
폴링(polling)이란?
웹 소켓이 나오기 이전에는 HTTP를 사용하여 실시간 데이터 전송을 구현했는데, 그 중 한 가지 방식이다. HTTP가 단방향 통신이므로 주기적으로 서버에 새로운 업데이트가 없는지 확인하는 요청을 보내고, 있다면 새로운 내용을 가져오는 비효율적인 방식.
폴링 연결 후, 웹 소켓을 사용할 수 있다면 웹 소켓으로 업그레이드되는 것이다. 웹 소켓을 지원하지 않는 브라우저는 폴링 방식으로, 지원하는 브라우저는 웹 소켓 방식으로 사용 가능한 것이다.
근데 처음부터 웹 소켓만 사용하고 싶으면, 클라이언트에서 연결할 때 다음처럼 transport
옵션을 추가하면 된다.
var socket = io.connect('http://localhost:3000', {
path:'/socket.io',
transports: ['websocket']
});