채팅 기능을 구현하다 보면 Websocket과 socket.io를 많이 들어봤을 것이다.
일단 저거를 써서 채팅 기능을 구현하는건 알겠는데
도대체 뭐지? 라는 생각이 든다.
Websocket이란?
일단 Websocket이 나오게 된 배경 부터 알아보자
맨 처음에 웹이라는 것이 나왔을때 브라우저의 렌더링 방식은 HTTP요청에 대하나 응답을 받아서 화면을 새로 만들어주는 방식이었다.
이를 stateless방식이라고 하는데 클라이언트에서 요청을 보내면 서버는 요청 받은것에 대한 응답을 건네주고 연결을 끊어버리는 식이다.
왜 서버와의 연결을 계속 유지하지 않지?
클라이언트가 10억이라고 치면 서버에서 그 많은 연결을 유지하게 되면 과부하가 걸려 다운된다. 왜 stateless상태를 채택했는지 알 수 있다.
이렇게 요청,응답을 받게 되면 화면이 깜빡거리면서 리렌더링 되는것을 볼 수 있는데 우리가 채팅 기능을 이용하다보면 메세지 하나를 보내면 화면이 다시 요청되지 않는 듯이 과거의 사람들도 이렇게 사용자와 실시간 상호작용을 하고 싶었나보다.
물론 Websocket을 사용하지 않고 stateless상태를 유지하면서 채팅 기능을 구현할 수도 있다.(Long Polling, Stream등)
하지만 오늘은 양방향 메시지 송수신 방식에 대해 알아보자
양방향 메시지 송수신 방식을 사용하려고 Websocket이라는 것이 나오게 되었다.(드디어..!)
Websocket은 소켓을 이용하여 기존의 방식보다 더 쉽게 데이터를 교환할 수 있는 것이다.
따라서 Websocket은 특정 라이브러리가 아니라 이렇게 하자!하는 프로토콜이다.
Websocket을 어떻게 사용하지?
Websocket은 다른 HTTP 요청과 마찬가지로 80번 포트를 통해 서버에 연결한다.
GET /... HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
브라우저에서는 위와 같이 Upgrade 헤더와 함께 랜덤하게 생성된 키를 보낸다. 서버는 받은 키를 바탕으로 토큰을 생성하고 브라우저에 응답해준다.
이러한 과정을 TCP/IP 핸드쉐이킹과 유사한 Websocket 핸드쉐이킹이라고 한다.
브라우저가 "나 웹소켓 사용할 거야"라고 서버에게 알려주고 서버가 "알겠어 이제 사용해"라고 응답하는 과정인 것이다.
그뒤에 Protocol Overhead방식으로 데이터를 주고 받는데 Protocol Overhead는 여러 TCP 커넥션을 생성하지 않고 80번 포트만을 이용하고, 헤더 등으로 논리적인 흐름을 파악하고 커넥션을 나누는 것이다.
Websocket의 간단한 사용방법
클라이언트
// 웹소켓 전역 객체 생성
const ws = new WebSocket("ws://localhost:3000");
// 연결이 수립되면 서버에 메시지를 전송한다
ws.onopen = function(event) {
ws.send("Client message: Hi!");
}
// 서버로 부터 메시지를 수신한다
ws.onmessage = function(event) {
console.log("Server message: ", event.data);
}
// error event handler
ws.onerror = function(event) {
console.log("Server error message: ", event.data);
}
처음에 웹소켓 전역 객체를 생성하고
연결이 되면(onopen) 서버에 메시지를 전송한다.
onmessage로 서버로부터 오는 메시지를 수신한다.
서버
const WebSocketS = require("ws").Server;
const wss = new WebSocketServer({ port: 3000 });
// 연결이 수립되면 클라이언트에 메시지를 전송하고 클라이언트로부터의 메시지를 수신한다
wss.on("connection", function(ws) {
ws.send("Hello! I am a server.");
ws.on("message", function(message) {
console.log("Received: %s", message);
});
});
서버에서는 연결이 수립되면 클라이언트로 메시지를 전송하고 클라이언트로 부터 메시지를 받아 출력한다.
이렇게 Websocket을 이용하면 실시간 상호작용을 할 수 있는데 socket.io는 왜 나온거지?
Websocket은 웹 브라우저의 버전과 서버의 버전에따라 될수도 있고 안될 수도 있다.
그래서 socket.io가 나온것이다.
socket.io는 뭔데?
socket.io는 자바스크립트를 이용해서 브라우저 종류에 상관없이 실시간 상호작용을 할 수 있게 해주는 기술이다.
Websocket, FlashSocket, AJAX Long Polling, AJAX Multi part Streaming, IFrame, JSONP Polling 같은 실시간 상호작용을 할 수 있게 해주는 여러 기술들이 존재하는데 이것을 하나의 API로 만들었다고 생각하면 될 것 같다.
socket.io에서 브라우저와 서버의 종류,버전을 파악해서 그에 맞는 방법을 골라 적용해준다! 라고 말하면 쉽다.
socket.io의 간단한 사용방법
클라이언트
<script src="/socket.io/socket.io.js"></script>
<script>
// localhost로 연결한다.
const socket = io.connect('http://localhost');
// 서버에서 news 이벤트가 일어날 때 데이터를 받는다.
socket.on('news',
function (data) {
console.log(data);
//서버에 my other event 이벤트를 보낸다.
socket.emit('my other event',
{ my: 'data' });
});
</script>
localhost로 소켓을 연결한 다음에 서버로 부터 news이벤트를 받아 내부의 로직을 실행한다.
서버
// 80 포트로 소켓을 연다
const io = require('socket.io').listen(80);
// connection이 발생할 때 핸들러를 실행한다.
io.sockets.on('connection', function (socket) {
// 클라이언트로 news 이벤트를 보낸다.
socket.emit('news', { hello: 'world' });
// 클라이언트에서 my other event가 발생하면 데이터를 받는다.
socket.on('my other event', function (data) {
console.log(data);
});
});
일단 소켓을 열고 연결할때 클라이언트로 news 이벤트를 데이터와 함께 보낸다.
만약 클라이언트에서 my other event가 발생하면 받은 데이터를 가지고 출력한다.
이상으로 Websocket과 socket.io에 대해 알아보았다.
끝!
'웹 프로그래밍 > BackEnd' 카테고리의 다른 글
[Express] pm2로 로컬에서 배포하기 (0) | 2021.10.20 |
---|---|
[Express, nodejs] SPA에서 socket.io로 채팅 구현하기 (2) | 2021.10.13 |
[Backend] OAuth란?(+ 동작방법) (3) | 2021.09.30 |
[Backend] ORM과 Sequelize (0) | 2021.09.29 |
로그인 - 쿠키와 세션 (0) | 2021.09.29 |