새로 들어간 사이드 프로젝트에서 채팅 기능을 구현하게 되어 WebSocket과 SSE(Server-Sent-Event)를 조사하였고, 이전의 실시간 통신 방식도 알아보게 되었다. 이를 함께 소개하며 WebSocket과 SSE에 대한 이해를 돕고자 한다.
⚠️ 이 포스팅은 WebSocket 이전 실시간 통신 방식과 WebSocket에 관한 글로, SSE에 대해 알고싶다면 다음 포스팅에서 확인할 수 있다.
기본적으로 웹 어플리케이션은 클라이언트-서버간의 HTTP요청과 응답을 하는 것으로부터 통신을 하게 된다.
이러한 통신을 실시간으로 하기 위하여, 다음과 같은 방법들이 등장하게 되었다.

💡HTTP 오버헤드
보내지는 헤더와 같은 정보로 인해 데이터량이나 처리시간이 오히려 증가하는 것을 의미한다.
헤더 정보를 통해 트래픽을 거르게 되면 안정성이 확보되지만 결국은 작은 정보라도 TPS(전송시간)가 늘어나게 되는데, 거기서 HTTP 오버헤드가 발생하게 된다.
출처: https://inpa.tistory.com/608

기존 Polling과의 차이점
Polling방식에 비해 HTTP 오버헤드가 적게 발생한다.
클라이언트로 보내는 이벤트들의 시간간격이 좁거나, 다수의 클라이언트에게 동시에 이벤트가 발생할 경우, 모두 서버에 접속을 시도해 서버 부담이 급증하게 되므로 Polling방식과 큰 차이가 없다.
The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The security model used for this is the origin-based security model commonly used by web browsers. The protocol consists of an opening handshake followed by basic message framing, layered over TCP. The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that does not rely on opening multiple HTTP connections (e.g., using XMLHttpRequest or iframes and long polling).
출처: RFC 6455
위의 설명을 요약한 WebSocket의 정의는 다음과 같다.

최초 한번만 HTTP Protocol로 handshaking을 하게 되는데, 클라이언트는 GET 요청으로 서버에 연결을 요청한다. 아래는 WebSocket 연결을 위한 주요 헤더 정보이다.
GET /chat HTTP/1.1 // 반드시 GET 요청, HTTP는 1.1이상
Host: server.example.com // WebSocket 서버의 주소
Upgrade: websocket // 현재 클라이언트, 서버, 전송 Protocol 연결에서 다른 Protocol로 업그레이드 또는 변경 요청
Connection: Upgrade // Upgrade 헤더 필드가 있으면 Upgrade 옵션 필수
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== // 연결을 위한 base64 인코딩 키 값, 신원 인증을 위한 키
Origin: http://example.com // 클라이언트 주소
Sec-WebSocket-Protocol: chat, superchat // 서브 Protocol
Sec-WebSocket-Version: 13
그러면 서버로부터 다음과 같은 응답헤더를 받아 데이터를 전송할 준비를 완료한다.
HTTP/1.1 101 Switching Protocols // 101 Switching Protocols가 Response로 오면 WebSocket이 연결됐다는 의미
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
요청-응답 후에는 WebSocket Protocol로 변경된다. (ws://www~)
데이터 보안을 위해서 wss Protocol도 사용,권장된다.
클라이언트와 서버가 모두 handshake를 보내고 handshake가 성공하면 데이터 전송 부분이 시작된다.
클라이언트와 서버는 이 사양에서 message라고 하는 개념 단위로 데이터를 양방향으로 전송한다.
여기서 message는 여러 frame이 모여서 구성하는 하나의 논리적 메세지 단위이다.
그렇다면 어떻게 데이터를 전송할까?
참고: frame
frame은 아래와 같이 데이터 전송 과정에서 가장 작은 단위의 데이터로 작은 헤더와 payload로 구성된다.

봐도 무슨 말인지 모르겠지만🤷🏻♀️ 간단히 용어를 짚고 넘어가보려 한다.
(너무 어려우면 넘어가도 좋겠다.)
FIN: 메시지의 마지막 fragment(조각)이란 것을 알려주는 플래그이다.(1이면 마지막 프레임, 0이면 메시지가 더 있음)
RSV1, RSV2, RSV3: 기본은 0값이고 정의를 했을 경우에만 다른 값을 넣을 수 있다.
만약 정의하지 않은 값이면 Fail the WebSocket Connection이 실행되어야 한다.
opcode: payload 데이터의 해석을 정의한다. 알 수 없는 opcode가 수신되면 Fail the WebSocket Connection이 실행되어야 한다.
- 0x0: 계속 프레임(Continuation frame). 전체 데이터의 일부 의미
- 0x1: 텍스트 프레임(Text frame). 데이터가 UTF-8텍스트이다.
- 0x2: 바이너리 프레임(Binary frame) 데이터가 이진 데이터이다.
- 0x8: 연결 닫기(Close connection)
MASK: payload 데이터를 마스킹할지 여부를 정의한다. 1로 설정하면 마스킹 키가 존재하며 이 키는 payload 데이터의 마스킹을 해제하는데 사용된다. 클라이언트에서 서버로 전송되는 모든 프레임은 이 비트가 1로 설정되어 있다.
Payload Len: 이 프레임에 포함된 데이터의 총 길이를 나타낸다.
Extended Payload Length (16/64비트): Payload length가 126 이상일 경우 이 필드를 사용하여 실제 데이터 길이를 나타낸다.
Masking Key : MASK 비트가 1로 설정된 경우 사용되며, 클라이언트가 서버로 보내는 데이터는 항상 마스킹되어야 합니다.
Payload Data: 전송할 실제 데이터입니다. 텍스트 또는 바이너리 데이터로, 필요한 경우 마스킹 키로 마스킹 처리된다.
WebSocket은 HTML5 이후로 등장한 기술이므로, HTML5 이전의 기술로 구현된 서비스에서 사용할 수 없다.
=> Socket.IO 라이브러리로 하위 호환이 가능하다.
HTML5 이전의 기술로 구현된 서비스에서 웹 소켓처럼 사용 할 수 있도록 도와주고 그 외 편리한 기능을 제공한다.(직접 구현하면서 알아봐야겠다.)
WebSocket은 대략적으로 문자열들을 주고받게 해줄 뿐 그 이상의 일은 해줄 수 없다.
또한 주고 받는 문자열의 해독은 온전히 어플리케이션에 맡기기 때문에 해석이 어려울 수 있다. 때문에 WebSocket 방식은 sub-protocol을 사용해서 약속을 하는 경우가 많다.
=> STOMP(Simple Text Oriented Message Protocol) 같이 해석이 편한 프로토콜이 있다.
주의할 점
SSE까지 파헤쳐보려 했지만 글이 너무 길어져 다음 시리즈에서 작성해보는 것으로 하겠다..🪄
polling
https://medium.com/techieahead/http-short-vs-long-polling-vs-websockets-vs-sse-8d9e962b2ba8
websocket개요
https://youtu.be/MPQHvwPxDUw?si=7tWbiVvC8Kbbfr4o
data frame
https://www.rfc-editor.org/rfc/rfc6455#section-5.2
sending data
https://www.rfc-editor.org/rfc/rfc6455#section-6.1
websocket특징
https://gdsc-university-of-seoul.github.io/websocket/