← posts/b.log()

blog92@web:~$ cat posts/websocket-03-handshake.md

NETWORK1 min read

WebSocket 완전 정복 3편 — 핸드셰이크: Upgrade 요청과 101, Sec-WebSocket-Accept의 정체

클라이언트의 Upgrade 요청 헤더와 서버의 101 Switching Protocols 응답을 줄 단위로 읽고, Sec-WebSocket-Accept가 고정 GUID와 SHA-1으로 계산되는 과정을 코드로 확인한 뒤, 이 절차가 보안 장치가 아니라는 사실과 101 이후 이 연결이 더는 HTTP가 아니라는 사실을 다룹니다.

WebSocket 완전 정복 · 1부. 기초 · 16편 중 3편

이전 편: 2편 — 프로토콜 개요

2편의 생애주기에서 첫 단계였던 핸드셰이크를 줄 단위로 읽습니다. 클라이언트가 보내는 Upgrade 요청, 서버의 101 응답, 그리고 Sec-WebSocket-Accept가 어떻게 계산되는지까지입니다.

클라이언트 요청 — Upgrade 핸드셰이크

http
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://example.com
Sec-WebSocket-Protocol: chat.v1

서버 응답 — 101 Switching Protocols

http
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat.v1

Sec-WebSocket-Accept는 어떻게 만들어지는가

Sec-WebSocket-Accept = Base64( SHA-1( 클라이언트 키 + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ) )

ts
import { createHash } from "node:crypto";
 
const GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
function acceptKey(key: string) {
  return createHash("sha1").update(key + GUID).digest("base64");
}
acceptKey("dGhlIHNhbXBsZSBub25jZQ=="); // "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="

이 절차는 보안 장치가 아니다

이 절차는 보안용이 아닙니다. 상대가 정말 WebSocket을 이해하는 서버인지 확인하고, HTTP 캐시가 응답을 재사용하지 못하게 하는 장치입니다. 인증은 별도로 해야 합니다(10편 — 인증과 인가).

101 이후, 이 연결은 더 이상 HTTP가 아니다

101 응답 이후 이 TCP 연결은 더 이상 HTTP가 아닙니다. 이 사실이 프록시·로드밸런서 문제의 근원입니다.

중간 장비가 구체적으로 어디서 이 연결을 끊고 무엇을 설정해야 하는지는 14편 — 인프라: Nginx, 로드밸런서, 그리고 OS 한계에서 다룹니다.

더 깊이

COMMENTS (…)

댓글을 불러오는 중이에요.

NEW COMMENT0 / 1000
⌘↵ 전송

blog92@web:~$ cd ..