들어가며
주식, 채팅 같은 서비스 또는 프론트엔드 개발을 하다보면 자주 만나는 WebPack과 Vite등 빌드툴이 제공하는 devServer는 모두 실시간 통신을 위해 서버와의 양방향 통신을 하고 있습니다. 특히 웹 프론트엔드(HTML5)에서는 WebSocket이라는 프로토콜을 통해서 실시간 통신을 구현하게 됩니다. 이제부터 Socket은 무엇이며, 양방향 통신은 어떻게 이루어지고 마지막으로 웹소켓은 어떻게 사용할 수 있는지 정리하도록 하겠습니다.
양방향 통신
실시간 서비스를 위해 양방향 통신을 한다고 앞서 말하였습니다. 일반적으로 프론트엔드 영역에서 서버로부터 데이터를 받을 때 fetch API나 Axios 라이브러리를 이용해서 응답을 받곤 했었는데요. 이 때 데이터를 받는 것(응답)은 저희가 데이터를 달라고(요청) 해야 가능했었습니다. 이렇게 한쪽의 요청에 의해서만 응답을 받을 수 있는 형태의 통신을 단방향 통신이라고 합니다. 반면에 양방향 통신은 한쪽의 요청이 없어도 응답을 받을 수 있는 형태의 통신입니다.
Socket의 정의
Socket이란 네트워크 상에서 돌아가는 두 개의 프로세스 간 통신의 엔드포인트이며 TCP/IP 4계층에서 L4(응용계층)에서 L3(전송계층)로 데이터를 전달하는 인터페이스 역할을 합니다.
Socket은 실제 파일은 아니지만 파일이라고 생각하면 이해하기 쉽습니다. 프로세스는 파일에 접근하여 읽거나(Read) 쓰는(Write) 행위를 주로 합니다. Socket을 통해 데이터를 읽는 걸 Socket에서는 Receive(데이터를 받았다)라고 하며, 데이터를 쓰는 것을 Send(데이터를 보낸다)라고 합니다. 그림으로 보자면 다음과 같은 흐름으로 이해해 볼 수 있습니다.
TCP Socket
WebSocket을 알아보기 전의 전통적인 네트워크 통신에서 사용하는 TCP Socket 흐름에 대해서도 이해해보겠습니다. TCP Socket은 신뢰성 있는 연결 지향 프로토콜인 TCP를 기반으로 다음과 같은 특징이 있습니다.
- 데이터 전송 중 손실을 최소화 한다.
- 전송 순서를 보장한다.
- 오류 복구와 흐름 제어 기능이 내장되어 있다.
TCP/IP 4 계층에서 각 계층의 데이터 전송 단위는 다음과 같이 정리됩니다.
L4 | 데이터스트림 | L4 | 데이터스트림 | |
L3 | 세그먼트 | L3 | 세그먼트 | |
L2 | 패킷 | L2 | 패킷 | |
L1 | 프레임 | ↔️ | L1 | 프레임 |
- L4에서 소켓을 통해 데이터스트림을 L3로 내보내고 L3에서는 데이터스트림을 데이터 전송을 위해 Segmenation(세분화)합니다. 세분화한 데이터 조각들을 Segment라고 합니다.
- L2에서는 안정적이고 효율적인 전송을 위해 세그먼트를 패킷화 합니다. 주문한 상품을 깨지지 않게 상자에 잘 포장하는 것과 같다고 생각 할 수 있습니다.
- L1에서서는 프레임화를 합니다. 패킷이라는 택배상자를 배송을 위해 적재하는 것과 같다고 볼 수 있는데요. 물리적으로 데이터를 전송할 때 여러 패킷들을 프레임화 한 프레임을 전송합니다.
WebSocket
웹소켓은 HTTP 프로토콜을 기반으로 최초 연결 이후에 양방향 통신이 가능하도록 업그레이드된 프로토콜입니다. 웹브라우저(HTML5)와 서버 간 실시간 통신이 가능하도록 하는 프로토콜입니다.
- 실시간 통신을 위한 HTTP Long Polling과 같은 방식의 단방향 통신의 한계점을 한다.
- 핸드셰이크과정을 통해 Socket을 연결하고 양방향 통신이 가능하게 된다.
- 전송단위는 메시지(TCP Socket에서는 데이터스트림)이며 하나 이상의 프레임으로 나뉘어 전송된다.
- 메시지에는 텍스트와 바이너리만 담을 수 있다.
- 일반적인 HTTP와 다르게 헤더가 작다.
WebSocket Message
웹소켓의 메시지는 하나 이상의 프레임으로 나뉘어 전송된다는 말은, 하나 이상의 프레임이 모여 하나의 메시지를 만들어 낸다는 말과 같습니다. 아래의 그림은 웹 소켓 프레임 포맷을 도식화 한 것으로 아래 그림이 여러개가 모여 하나의 메시지가 구성됩니다.
프레임의 자세한 내용은 이쪽을 참고하시면 좋습니다.
핸드셰이크(Hankshake)
HTTP를 이용해 웹브라우저와 서버가 생성된 소켓을 통해 연결하는 과정을 핸드셰이크라고 합니다. 연결이 완료된 후에는 WebSocket 프로토콜로 업그레이드 되어 양방향 통신이 가능해집니다.
1) 최초 연결 시 HTTP를 통해서 웹브라우저가 아래와 같은 헤더정보로 서버에 Request 합니다.
GET /chat
Host: example.com
Origin: https://example.com
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: dkIdkf34/r3Rdf
Sec-WebSocket-Version: 13
2) 웹소켓 연결이 가능하다면 101 상태 값과 함께 서버로부터 Response를 받습니다.
101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: hsBlbuDTkk24srzEOTBUlZAlC2g=
'JS, TS' 카테고리의 다른 글
어떻게 CSS file을 JS file 안에 불러올 수 있을까? (1) | 2023.12.17 |
---|---|
Vite, nginx, docker 환경에서 무한 reload 현상 고치기 (0) | 2023.11.15 |
SocketIO로 실시간통신 프론트엔드 테스트 및 TDD 하는 법 (리액트) (2) | 2023.11.06 |
LoginPage로 보는 React 통합테스팅(with. msw, testing-library, vitest) (1) | 2023.10.28 |
testing-library, vitest로 리액트 Unit test 작성하며 리팩토링하기 (2) | 2023.10.20 |