
이번 포스트에서는 이전에 프로젝트를 진행하면서 사용하였던 WebSocket 프로토콜에 대해 자세히 알아보려고 한다!
WebSocket은 클라이언트(보통은 웹 브라우저)와 서버 간에 하나의 TCP 연결을 유지하면서 양방향 통신을 가능하게 해주는 프로토콜이다.
정확히 말하면, WebSocket은 전송 계층(Transport Layer) 프로토콜이 아니다.
WebSocket은 TCP(전송 계층)를 기반으로 동작하는 애플리케이션 계층(Application Layer) 프로토콜이다.
즉:
OSI 7계층 기준으로 보면:
| 계층 | 예시 | WebSocket |
|---|---|---|
| 7 - 애플리케이션 | HTTP, FTP, WebSocket | ✅ WebSocket 위치 |
| 4 - 전송 | TCP, UDP | ⚙️ WebSocket이 사용하는 기반 |
따라서 WebSocket은 전송 계층을 '사용'할 뿐, 그 자체는 애플리케이션 계층에 속한다.
HTTP는 클라이언트가 요청해야 서버가 응답할 수 있는 단방향 통신 구조이다.
따라서 서버가 클라이언트에게 먼저 데이터를 보낼 수 없다.
이를 극복하기 위한 방식으로는 다음과 같은 것들이 있었다:
| 방식 | 설명 | 한계 |
|---|---|---|
| Polling | 클라이언트가 일정 주기로 서버에 요청 | 실시간성 부족, 서버 과부하 |
| Long Polling | 서버가 응답을 지연하다가 새 데이터가 생기면 응답 | 지연 시간, 다중 연결 유지 필요 |
| SSE (Server Sent Events) | 서버에서 클라이언트로 단방향 스트리밍 | 클라이언트 → 서버 전송 불가 |
⬇️ 이 모든 방식은 HTTP의 틀을 억지로 비틀어 쓴 방식이다.
✅ WebSocket은 이 한계를 완전히 극복한 기술이다.
WebSocket은 HTTP 기반으로 연결을 시작한다. 이 과정을 Handshake라고 한다.
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket - 'WebSocket으로 프로토콜을 바꾸고 싶다'라는 명시적인 요청
Connection: Upgrade - 'Upgrade 요청을 실제로 적용하'라는 지시
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
wss://를 사용하며, TLS(SSL) 기반이다.WebSocket은 메시지를 프레임 단위로 분할해서 전송한다.
프레임은 크게 다음과 같은 종류가 있다:
💡 프레임은 WebSocket 자체의 논리적 단위이며,
실제로는 TCP 위에서 전송되고 TCP는 내부적으로 이를 여러 개의 IP 패킷으로 나눠 전송할 수 있다.즉, WebSocket 프레임은 TCP 세그먼트를 통해 전송되며,
세그먼트가 패킷으로 캡슐화되어 전송되는 구조이다.
close 프레임을 통해 연결을 종료할 수 있다.예시 흐름:
ping/pong 프레임은 RFC6455에 따라 제어 프레임(control frame)에 속하며, 응답이 오지 않으면 연결을 종료하거나 재연결할 수 있는 근거가 된다.
const socket = new WebSocket("wss://example.com/socket");
socket.addEventListener("open", () => {
console.log("WebSocket 연결 완료");
socket.send("Hello, server!");
});
socket.addEventListener("message", (event) => {
console.log("서버로부터 메시지:", event.data);
});
socket.addEventListener("close", () => {
console.log("연결 종료");
});
socket.addEventListener("error", (err) => {
console.error("에러 발생:", err);
});
ws:// 또는 wss://로 URL을 시작한다.단순 API, 낮은 빈도의 요청이라면 오히려 REST가 효율적일 수 있다.
query, headers 활용이 가능하다.