WebSocket이란?

Taemin Jang·2023년 11월 22일
1

등장 배경

Polling

일정한 주기로 서버에 요청을 보내는 방법
예시로 setTimeout, setInterval 등으로 일정 주기마다 서버에 요청을 보낼 수 있음
이렇게 사용하면 불필요한 Request와 Connection을 생성하여 서버에 부담이 됨

즉, 요청 주기가 짧을수록 서버에 대한 비용이 커지게 됨
일정 주기를 짧게 잡으면 실시간처럼 보일 수 있지만, 실시간이라고 하기에 애매
또한 HTTP 통신을 함으로 Request와 Response 헤더가 불필요하게 필요함

Poling을 사용하는 경우

  • 실시간으로 받지 않아도 되는 경우
  • 다수의 사용자가 동시에 사용하는 경우

Long Polling

Polling과 비슷하게 일정 주기마다 요청을 보내지만 서버가 응답을 바로 전달하지 않는 방식

요청을 보냈을 때, 서버가 응답을 바로 보내지 않고 특정 이벤트나 타임아웃이 발생했을 때 응답을 전달한다.

불필요한 요청이 줄어서 Polling보다 좋아보이지만, Long Polling도 동시 다발적인 요청과 응답이 생기면 부하가 발생할 수 있다.

또한 HTTP 통신이기 때문에 Request, Response 헤더가 불필요하게 크게 필요함

Long Polling 방식을 사용하는 경우

  • 응답을 실시간으로 받아야하는 경우
  • 적은 수의 사용자가 동시에 사용할 경우

Streaming

이벤트가 발생했을 때 응답을 해주지만, 응답을 완료시키지 않은 상태로 계속 연결 유지하는 방식

Long Polling에 비해 응답마다 다시 요청하지 않아도 돼서 효율적이지만, 연결 시간이 길어질수록 연결 유효성 관리에 대한 부담이 크다.

WebSocket

웹소켓은 HTML5 표준 기술로, 전이중 통신 채널을 제공하는 컴퓨터 통신 프로토콜
⇒ 즉 서버와 클라이언트 간의 연결을 유지한 상태로 메시지(데이터) 교환을 위한 통신 프로토콜

이때 데이터는 패킷 형태로 전달
HTTP의 Request, Response로 동작하는 프로토콜의 한계를 극복하기 위한 기술
커넥션을 유지하면 서버에서 먼저 데이터를 보낼 수 있다

특징

양방향 통신 (Full-Duplex)

데이터 송수신을 동시에 처리 가능

HTTP 통신은 Client가 요청을 보내는 경우에만 Server가 응답하는 단방향 통신

실시간 네트워킹 (Real Time Networking)

웹 환경에서 연속된 데이터를 빠르게 노출할 수 있음
해당 특징을 사용하여 주로 채팅, 주식 등에 사용이 됨

HTTP로 실시간 네트워킹을 구현하려면 Polling, Long Polling등 방법을 이용해야함

한 번 연결(핸드셰이크 수행)이 설정되면 데이터는 요청 보낼 필요 없이 주고받을 수 있음

웹 소켓 연결을 맺는 과정에서 HTTP가 개입이 되며, 이 과정이 끝나면 웹 소켓으로 프로토콜이 바뀐다. 이를 protocol switching 과정이라 함.

  • WS : 일반적인 웹 소켓 (웹 소켓에서 HTTP 느낌)
  • WSS : 데이터 보안을 위해서 SSL을 적용한 프로토콜 (HTTPS 느낌)

따라서 웹 소켓을 호출할 때 ws:// 사용

웹 소켓 동작 방식

Opening Handshake

new WebSocket(url)을 호출하면 소켓이 생성되고, 즉시 연결이 된다.

const socket = new WebSocket("ws://주소");

핸드셰이크를 위해 클라이언트는 서버에 아래와 같은 HTTP Request(HTTP Upgrade)를 보낸다.

Request Header

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
  • GET /chat HTTP/1.1 : 웹소켓 통신 요청에서 HTTP 버전은 1.1 이상이어야 하고 GET메서드를 사용
  • Upgrade : 프로토콜을 전환하기 위해 사용하는 헤더로써 웹소켓 요청 시에는 반드시 websocket이라는 값을 가짐
    만약 이 값이 없거나, 다른 값이면 cross-protocol attack이라고 간주하여 웹 소켓 접속 중단
  • Connection : 현재의 전송이 완료된 후 네트워크 접속을 유지할 것인가에 대한 정보
    웹 소켓 요청 시 Upgrade라는 값을 가지며, 만약 이 값이 없거나 다른 값이면 웹 소켓 접속 중단
  • Sec-WebSocket-Key : 유효한 요청인지 확인하기 위해 사용되는 키 값
  • **Sec-WebSocket-Protocol :** 사용하고자 하는 하나 이상의 웹 소켓 프로토콜 지정, 필요한 경우에 사용
  • Sec-WebSocket-Version : 클라이언트가 사용하고자 하는 웹소켓 프로토콜 버전 (현재 최신 13)
  • Origin : CORS 정책으로 인해 만들어진 헤더

Response Header

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
  • HTTP/1.1 101 Switching Protocols : 101 code는 HTTP에서 WS로 프로토콜 전환을 허용했다는 응
  • Sec-WebSocket-Accept : 요청 헤더의 Sec-WebSocket-Key에 유니크 아이디를 더해서 SHA-1으로 해싱한 후 base64로 인코딩한 결과가 담겨있다.
    즉, 웹 소켓 연결이 성공적으로 되었다는 의미이다.

Data Transfer

소켓이 정상적으로 만들어지면 아래 네 개의 이벤트를 사용할 수 있게 됨

  • open – 커넥션이 제대로 만들어졌을 때 발생함
  • message – 데이터를 수신하였을 때 발생함
  • error – 에러가 생겼을 때 발생함
  • close – 커넥션이 종료되었을 때 발생함

커넥션이 만들어진 상태에서 데이터를 보내고 싶으면 socket.send(data)를 사용하면 된다.

주로 이벤트의 순서는 open → message → close 순으로 동작이 된다.

메시지 :
프레임 :

Closing Handshake

클라이언트와 서버 모두 커넥션을 종료하기 위해 컨트롤 프레임을 전송한다.

서버가 커넥션을 종료한다는 프레임을 보내고, 클라이언트가 이에 대한 응답으로 Close 프레임을 전송하게 되면 웹소켓 연결이 종료된다.

종료된 이후에 수신되는 모든 추가적인 데이터는 버려진다.

WebSocket Event

이벤트란 addEventListner() 혹은 on이벤트이름을 활용하여 서버로부터 들어오는 이벤트에 따라 특정한 작동을 하도록 하는 것을 의미

open

웹 소켓 연결이 발생했을 때 생성되는 이벤트

socket.addEventListener("open", () => {
  console.log("WebSocket is open");
});

// or

socket.onopen = () => {
  console.log("WebSocket is open");
};

message

웹 소켓으로 연결된 서버로부터 데이터(message)가 수신되었을 때의 이벤트

socket.addEventListener("message", (event) => {
  console.log("Message from server:", event.data);
});

// or

socket.onmessage = (event) => {
  console.log("Message from server:", event.data);
};

close

웹 소켓 연결이 닫혔을 때 발생하는 이벤트

socket.addEventListener("close", () => {
  console.log("WebSocket is closed");
});

// or

socket.onclose = () => {
  console.log("WebSocket is closed");
};

error

웹 소켓과의 연결이 잘못 되거나 데이터 전송의 실패 등의 오류가 발생했을 때의 이벤트

socket.addEventListener("message", (error) => {
  console.log("Error has occured:", error);
});

// or

socket.onerror = (error) => {
  console.log("Error has occured:", error);
};

WebSocket Method

메서드는 웹소켓과의 연결을 닫거나 서버로 데이터를 전송할 때 사용된다.

send()

브라우저로부터 서버로 데이터를 전송할 때 사용되는 메서드

socket.onopen = (event) => {
  socket.send("Hello Server, we are connected");
};

close()

웹소켓 연결을 닫기 위해 사용되는 메서드

socket.onerror = (error) => {
  socket.close();
  console.log("WebSocket connection is closed due to:", error);
};

참고 자료

https://datatracker.ietf.org/doc/html/rfc6455
https://ko.wikipedia.org/wiki/웹소켓
https://developer.mozilla.org/ko/docs/Web/API/WebSocket
https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers

https://ko.javascript.info/websocket
https://doozi0316.tistory.com/entry/WebSocket이란-개념과-동작-과정-socketio-Polling-Streaming
https://kellis.tistory.com/65
https://moon-ga.github.io/javascript/websocket/
https://gdsc-university-of-seoul.github.io/websocket/
https://www.joinc.co.kr/w/man/12/websocket

profile
하루하루 공부한 내용 기록하기

0개의 댓글