2차 프로젝트에서 Socket.io를 이용해 실시간 채팅을 구현했던 로직을 정리해보려고 한다.
코드 로직을 정리하기전, 먼저 기반이 되는 배경지식들에 대해 알아보자.
웹 소켓은 사용자의 브라우저와 서버 사이의 인터액티브 통신 세션을 설정할 수 있게 하는 고급 기술이다. 개발자는 웹 소켓 API를 통해 서버로 메시지를 보내고 서버의 응답을 위해 서버를 폴링하지 않고도 이벤트 중심 응답을 받는 것이 가능하다.
(출처 mdn- webSocket)
HTTP 프로토콜은 request, response의 반복을 통해 클라이언트와 서버가 서로 통신하며, 무상태(Stateless)성, 비연결성, 단방향 프로토콜이다.
HTTP/1.1 버전에서는 모든 자원에 대한 응답이 돌아온 후 연결을 종료하지만, 클라이언트와 서버가 실시간으로 통신하기에는 한계가 있다.
HTTP에서도 실시간 통신을 구현하는 3가지 방법이 존재한다.
polling은 실시간 통신이라고 말하긴 어렵지만, 브라우저가 일정한 주기마다 HTTP 요청을 하는 방식이다.
필요할때만 요청을 하는 방식이 아닌, 일정한 주기를 바탕으로 계속해서 요청을 보내기 때문에 서버부하가 늘어난다.
또한, 실시간으로 바로 Update된다고도 말하기 어렵다.
polling의 서버부하를 줄이면서 실시간성을 높이려는 방식으로 등장했다.
클라이언트에서 서버에 request을 보내면 연결을 끊지않고 기다린다.
이때 서버에서 클라이언트에게 이벤트를 방출하게 되면 response를 전달하고 연결이 종료된다.
연결종료이후 클라이언트에서는 바로 http request를 보내 다음 서버의 이벤트를 기다리는 방식이다.
여러 클라이언트가 long polling 방식을 사용하게 되거나 잦은 데이터 변경이 일어나면 문제가 발생할 수 있다.
수천개의 클라이언트가 연결된 채팅 서버에서, 채팅이 이루어지면, 서버는 수천개의 request를 동시에 받고, 이에 대한 response도 응답해야 하기 때문이다.
클라이언트와 서버간 연결된 연결 통로로 연결을 끊지않고 데이터를 계속해서 내려받는 방식이다.
연결과정이 없어졌기 때문에 Long Polling 방식에 비해 서버부하가 덜하다.
하지만, 클라이언트에서 서버로 데이터를 보내기가 힘들어서 실시간 단방향 통신에 많이 이용된다.
또한 세가지 방법 모두 http를 통해 통신하기 때문에 요청시 header가 불필요하게 크다는 단점이 존재한다.
실시간 통신을 구현하기 위해 HTML5에서는 HTTP 환경에서 클라이언트와 서버가 하나의 TCP연결을 통해 실시간으로 양방향 통신을 가능하게 하는 Web Socket 프로토콜이 등장했다.
Web Socket은 TCP 기반 프로토콜과는 다르게 HTTP 요청기반 HandShake 과정을 거쳐서 연결을 수립한다.
HandSake 과정이 성공하면, HTTP 프로토콜이 WS프로토콜로 변경되는 프로토콜 스위칭이 이루어진다. (http는 ws로, https는 wss로 변함)
WebSocket은 최초접속을 제외하면 요청시 헤더를 보내지 않고, 계속 같은 라인을 이용해 통신한다. (네트워크 비용을 아낄 수 있다.)
Socket.io는 Web Socket을 기반으로 만들어진 라이브러리로 Web Socket이 제공하지 않는 추가 기능들을 제공한다.
연결 실패시 fallback을 통해 다른 방식으로(polling, automatic reconnection)해당 클라이언트와 연결을 시도한다.
또 Room 개념이 존재해 Room에 속한 일부 클라이언트에게만 데이터를 전송하는 브로드캐스팅이 가능하다. (채팅방의 개념이라고 생각하면 쉽다)
이벤트를 방출하는 Socket.emit이라는 메소드가 존재한다.
Web Socket은 이벤트 명이 정해져 있고(send) string 형태의 data만 보낼 수 있지만, Socket.emit은 Socket.io롤 사용하면 이벤트명을 직접 생성 가능하며, object와 여러개의 파라미터를 보낼 수 있다.
세번째(마지막) 파라미터로 Callback Funtion을 보낼 수 있다. 서버에서 특정 조건 이후 클라이언트에서 인자로 받은 Callback Function을 실행할 수 있다.
글이 길어져서 구현했던 코드는 다음 글에서 작성하겠다.
ref)
HTTP, Websocket : https://ws-pace.tistory.com/104
https://velog.io/@hahan/Polling-Long-Polling-Streaming#%ED%95%9C%EA%B3%84%EC%A0%90%EA%B3%BC-%ED%95%B4%EA%B2%B0%EC%B1%85%EC%9D%80
Websocket : https://tecoble.techcourse.co.kr/post/2021-08-14-web-socket/
Websocket MDN : https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications