웹 소켓이란?
웹 소켓은 HTML5에 새로 추가된 스펙으로 실시간 양방향 데이터 전송을 위한 기술입니다. 최신 브라우저는 대부분 웹 소켓을 지원하고 노드에서는 ws나 Socket.IO 같은 패키지를 통해 웹 소켓을 사용할 수 있습니다. 웹 소켓이 생기기 전에는 주기적으로 서버에 새로운 업데이트가 있는지 확인해서 새로운 내용을 가져오는 방법을 사용했습니다. 웹 소켓은 연결이 이루어지고 나면 계속 연결된 상태이므로 업데이트가 있는지 요청을 보낼 필요가 없고 업데이트가 있으면 서버에서 클라이언트에게 바로 알려줍니다. HTTP 프로토콜과 포트를 공유할 수 있으므로 다른 포트에 연결할 필요도 없습니다.
1. ws 모듈로 웹 소켓 사용하기
socket.js 파일을 생성하고 웹 소켓 로직 코드를 작성합니다. 익스프레스 서버와 웹 소켓 서버 연결 후 웹 소켓 서버에 이벤트 리스너를 붙입니다. 웹 소켓은 이벤트 기반으로 작동합니다. 로컬 호스트로 접속한 경우 ip 가 ::1 로 뜹니다. ws 는 웹 소켓 객체이며 이벤트 리스너를 붙입니다. 웹 소켓에는 4가지 상태가 있는데 CONNECTING(연결 중), OPEN(열림), CLOSING(닫는 중), CLOSED(닫힘) 입니다. OPEN 상태일 때만 에러없이 메시지를 보낼 수 있습니다.
// socket.js
const WebSocket = require('ws');
module.exports = (server) => {
const wss = new WebSocket.Server({ server }); // 익스프레스 서버와 웹 소켓 서버 연결
wss.on('connection', (ws, req) => { // 클라이언트가 서버와 웹소켓 연결 시 발생하는 이벤트
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; // 클라이언트의 IP
console.log('새로운 클라이언트 접속', ip);
ws.on('message', (message) => { // 클라이언트로부터 메시지가 왔을 때
console.log(message);
});
ws.on('error', (error) => { // 웹 소켓 연결 중 문제가 생겼을 때
console.error(error);
});
ws.on('close', () => { // 클라이언트와 연결이 끊겼을 때
console.log('클라이언트 접속 해제', ip);
clearInterval(ws.interval); // interval 정리
});
ws.interval = setInterval(() => { // 3초마다 연결된 모든 클라이언트에게 메시지 전송
if (ws.readyState === ws.OPEN) { // 상태가 OPEN일 경우 메세지 전송
ws.send('서버에서 클라이언트로 메시지를 보냅니다.');
}
}, 3000);
});
};
app.js 에 웹 소켓을 연결합니다.
// app.js
// .. 생략
const webSocket = require('./socket');
// .. 생략
webSocket(server);
웹 소켓은 단순히 서버에서 설정한다고 해서 작동하지는 않습니다. 클라이언트에도 웹 소켓을 사용해야 하는데 index.html 파일에 웹 소켓을 설정하겠습니다.
// views/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>GIF 채팅방</title>
</head>
<body>
<div>F12를 눌러 console 탭과 network 탭을 확인하세요.</div>
<script>
const webSocket = new WebSocket("ws://localhost:8005"); // 연결할 서버 주소를 넣어 webSocket 객체 생성
webSocket.onopen = function () { // 서버와 연결된 경우
console.log('서버와 웹소켓 연결 성공!');
};
webSocket.onmessage = function (event) { // 서버로부터 메시지가 오는 경우
console.log(event.data);
webSocket.send('클라이언트에서 서버로 답장을 보냅니다');
};
</script>
</body>
</html>
콘솔에서 npm start 를 입력한 후 "http://localhost:8005" 에 접속하여 Network 탭의 Messages 를 확인하면 다음과 같은 화면을 볼 수 있습니다.
2. Socket.IO로 웹 소켓 사용하기
웹 소켓을 간단하게 사용할 때는 ws 모듈을 사용해도 되지만 구현하려는 서비스가 복잡해지면 Socket.IO 를 사용하는 것이 더 편리합니다. socket.js 파일을 생성하고 웹 소켓 로직 코드를 작성합니다. SocketIO 의 path는 클라이언트가 접속할 경로를 설정한 것입니다. connection 이벤트는 콜백으로 소켓 객체(socket) 을 제공합니다. reply 는 사용자가 직접 만든 이벤트로 클라이언트에서 reply 라는 이벤트명으로 데이터를 보내면 서버에서 받는 부분입니다. 이렇게 이벤트명을 사용하는 것이 ws모듈과 다른 점입니다.
// socket.js
const SocketIO = require('socket.io');
module.exports = (server) => {
const io = SocketIO(server, { path: '/socket.io' }); // 익스프레스 서버와 웹 소켓 서버 연결
io.on('connection', (socket) => { // 클라이언트가 서버와 웹소켓 연결 시 발생하는 이벤트
const req = socket.request; // 요청 객체
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; // 클라이언트의 IP
console.log('새로운 클라이언트 접속!', ip, socket.id, req.ip);
socket.on('disconnect', () => { // 클라이언트가 연결을 끊었을 때
console.log('클라이언트 접속 해제', ip, socket.id);
clearInterval(socket.interval);
});
socket.on('error', (error) => { // 통신 과정에서 에러가 발생했을 때
console.error(error);
});
socket.on('reply', (data) => { // 클라이언트로부터 메시지를 받을 때 (사용자가 직접 만든 이벤트)
console.log(data);
});
socket.interval = setInterval(() => { // 3초마다 클라이언트로 메시지 전송
socket.emit('news', 'Hello Socket.IO'); // 첫번째 인수 - 이벤트 이름, 두번째 인수 - 데이터
}, 3000);
});
};
클라이언트에 웹 소켓을 설정하겠습니다. index.html 파일을 작성합니다. socket 객체를 생성할 때 서버에서 path를 설정했으므로 클라이언트에도 똑같이 path를 설정합니다. path 가 똑같아야 통신할 수 있습니다.
// views/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>GIF 채팅방</title>
</head>
<body>
<div>F12를 눌러 console 탭과 network 탭을 확인하세요.</div>
<script src="/socket.io/socket.io.js"></script> // Socket.IO 에서 클라이언트로 제공하는 스크립트, 실제 파일은 아님
<script>
const socket = io.connect('http://localhost:8005', { // 연결할 서버 주소를 넣어 socket 객체 생성
path: '/socket.io',
transports: ['websocket'], // 웹 소켓만 사용
});
socket.on('news', function (data) { // 서버에서 보내는 news 이벤트를 받기 위해 이벤트 리스너 붙임
console.log(data);
socket.emit('reply', 'Hello Node.JS'); // 서버에게 reply로 메시지를 보냄
});
</script>
</body>
</html>
콘솔에서 npm start 를 입력한 후 "http://localhost:8005" 에 접속하여 Network 탭을 확인하면 다음과 같은 화면을 볼 수 있습니다.
'Back-end > Node.js' 카테고리의 다른 글
[Node.js] 노드 서비스 테스트 하기 (0) | 2021.08.03 |
---|---|
[Node.js] 웹 API 서버 만들기 (2) (0) | 2021.08.01 |
[Node.js] 웹 API 서버 만들기 (1) (0) | 2021.07.30 |
[Node.js] 익스프레스로 SNS 서비스 만들기 (3) (0) | 2021.07.27 |
[Node.js] 익스프레스로 SNS 서비스 만들기 (2) (0) | 2021.07.27 |