1.웹소켓이란?
웹소켓은 양방향 통신을 위한 프로토콜입니다.
HTTP는 클라이언트의 요청이 있을때만 응답을 하는 단방향통신입니다. 또한 응답을 보낸후 통신을 종료해버립니다. 그렇기때문에 새로운 데이터가 갱신되면 다시 요청을 해야하고 데이터 변화가 적어도 전체 데이터를 갱신합니다. 즉, 자원낭비가 발생합니다.
이런 문제를 해결하고자 ajax라는 기술이 등장합니다. Asynchronous JavaScript And XML의 약자로 자바스크립트와 xml을 이용하여 동적인 웹페이지를 만들 수 있습니다. 자바스크립트로 백그라운드에서 서버에 필요한 데이터만 xml형식으로 요청하여 응답받은 데이터를 통해 웹페이지 일부분을 갱신할 수 있습니다. 자원낭비는 줄었지만 ajax도 HTTP 프로토콜을 이용한 단방향 통신입니다.
이를 보완하여 양방향 통신처럼 보이기위해 폴링(Poling), 롱폴링(Long Poling), 스트리밍(Streaming)이라는 방식이 등장합니다.
폴링은 서버에 주기적으로 요청을 하는 방식입니다. 양방향 통신처럼 보이지만 주기가 짧을수록 서버에 과부하가 발생할 수 있고 자원낭비가 심해집니다.
롱폴링은 요청이 있으면 이벤트가 발생할때까지 기다렸다가 응답해주는 방식입니다. 폴링보다 자원낭비는 줄었지만 이벤트가 발생하는 빈도가 많을수록 자원낭비가 심해지고 서버에 과부하가 발생할 수 있습니다.
스트리밍은 요청이 있으면 통신을 종료하지 않고 이벤트가 발생할때마다 응답해주는 방식입니다. 자원낭비도 줄었고 트래픽도 심하지않지만 보안성과 안전성에 문제가 발생합니다.
이런 배경속에 html5와 함께 양방향통신 웹표준 프로토콜로서 웹소켓이 등장합니다.
2. 웹소켓의 구조
웹소켓은 HTTP 프로토콜을 통해 성립됩니다. HTTP 핸드쉐이크 과정을 거쳐 웹소켓 프로토콜로 전환됩니다. 웹소켓이 열리면 메시지를 전송할 수 있는데 이 메시지를 데이터 프레임이라고 합니다. 클라이언트 요청
key |
value |
GET / HTTP/1.1
|
Host |
서버 주소 |
Connection |
Upgrade |
Upgrade |
websocket |
Origin |
클라이언트 주소 |
Sec-WebSocket-Version |
13 |
Sec-WebSocket-Key |
임의의 16바이트 숫자를 base64 인코딩 |
서버 응답
key |
value |
HTTP/1.1 101 Switching Protocols
|
Upgrade |
websocket |
Connection |
Upgrade |
Sec-WebSocket-Accept |
아래 설명 |
Sec-WebSocket-Accept는 클라이언트로부터 받은 Sec-Websocket-Key에 웹소켓 GUID인 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"을 이어붙여 SHA-1 바이너리 해시값을 구합니다. 이 값을 다시 Base64로 인코딩하면 Sec-WebSocket-Accept 값이 됩니다.
데이터 프레임 Fin (1bit) : 뒤에 오는 데이터가 더 있는지 확인하기위한 패킷입니다.
RSV (3bit) : 사용하지 않음 OPCODE (2bit) : 프레임 종류
OPCODE |
프레임 종류 |
설명 |
0 |
연속된 조각 |
Fin값이 1인경우 연속된 조각임을 나타냅니다. |
1 |
문자열(text) |
프레임값이 문자열입니다. |
2 |
바이너리(binary) |
프레임값이 바이너리입니다. |
8 |
웹소켓 접속 종료(close) |
웹소켓 접속을 종료합니다. |
9 |
Ping |
Ping을 보냅니다. |
10 |
Pong |
Pong을 보냅니다. |
MASK (1bit) : 클라이언트에서 서버로 보낸 메시지는 1, 서버에서 클라이언트로 보낸 메시지는 0
Payload length (7bit) : 비트값이 125 이하인 경우 해당 비트값이 페이로드 길이; 126인 경우 다음 16비값이 페이로드 길이; 127인 경우 다음 64비트값이 페이로드 길이 Masking-Key (32bit) : 마스킹된 경우 존재(클라이언트에서 서버로 보낸 메시지의 경우)
마스킹된 페이로드의 경우 디코딩이 필요합니다.
var DECODED = ""; for (var i = 0; i < ENCODED.length; i++) { DECODED[i] = ENCODED[i] ^ MASK[i % 4]; } |
여기서 MASK는 Masking-Key입니다.
3. Socket.io
Socket.io는 웹소켓과 같은 표준 기술이 아닌 라이브러리입니다. 웹소켓은 표준임에도 불구하고 브라우저마다 지원여부가 다릅니다. 그와 달리 Socket.io는 자바스크립트를 기반으로 하여 폴링, 롱폴링, 스트림, 웹소켓 중 적절한 기술을 사용하여 대부분의 브라우저에서 작동됩니다. 또한 방의 개념을 이용하여 일부 클라이언트에게만 브로드캐스트가 가능합니다. |