본문 바로가기
C.W.K.
Stream
Lesson 07 of 08 · published

WebSocket 핸드셰이크

~13 min · foundations, rfc-6455, handshake

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

HTTP/1.1 에서 WebSocket 으로

겉보기의 마법을 걷어 내면 WebSocket 핸드셰이크는 핵심 헤더 네 개를 담은 HTTP/1.1 GET 요청이야. 바로 Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Key, Sec-WebSocket-Version: 13 이지. 서버는 이 헤더를 알아보고 파생 값을 계산한 뒤 101 Switching Protocols 로 응답해.

Sec-WebSocket-Accept 해시

클라이언트는 무작위 논스를 base64 로 인코딩해 Sec-WebSocket-Key 로 보내. 서버는 여기에 고정된 매직 GUID(258EAFA5-E914-47DA-95CA-C5AB0DC85B11) 를 이어 붙이고 SHA-1 해시를 계산한 다음, 그 결과를 다시 base64 로 인코딩해 Sec-WebSocket-Accept 로 돌려줘. 서버가 WebSocket 프로토콜을 실제로 이해한다는 증거라서 일반 HTTP 서버가 우연히 핸드셰이크를 끝낼 수 없어.

선택형 핸드셰이크 헤더

Sec-WebSocket-Protocolgraphql-wsmqtt 같은 하위 프로토콜을 협상할 때 써. Sec-WebSocket-Extensions 는 확장 기능을 협상하며, 가장 흔한 예가 압축을 위한 permessage-deflate 야. Origin 은 연결을 요청한 페이지를 나타내니 서버에서 반드시 검증해야 해.

Code

Sec-WebSocket-Accept 직접 계산·python
import hashlib, base64

GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'

def server_accept(client_key: str) -> str:
    raw = (client_key + GUID).encode('ascii')
    digest = hashlib.sha1(raw).digest()
    return base64.b64encode(digest).decode('ascii')

# From RFC 6455
print(server_accept('dGhlIHNhbXBsZSBub25jZQ=='))
# -> 's3pPLMBiTxaQ9kYGzzhZRbK+xOo='
연결을 수락하기 전에 Origin 검증하기·python
ALLOWED = {'https://app.example.com', 'https://admin.example.com'}

@app.websocket('/ws')
async def ws_endpoint(websocket: WebSocket):
    origin = websocket.headers.get('origin', '')
    if origin not in ALLOWED:
        # Reject during handshake — never .accept()
        await websocket.close(code=4003, reason='forbidden origin')
        return
    await websocket.accept()
    # ...

External links

Exercise

server_accept 함수를 무작위 base64 클라이언트 키 세 개에 실행해 봐. 그런 다음 아무 채팅 사이트에서나 브라우저 네트워크 패널로 실제 WebSocket 핸드셰이크를 잡아. 요청의 Sec-WebSocket-Key 로 함수가 계산한 값과 응답의 Sec-WebSocket-Accept 가 일치하는지 직접 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.