1. 웹 소켓이란?
- 두 프로그램 간의 메세지를 교환하기 위한 통신 방법 중 하나
- W3C와 IETF에 의해 자리잡은 표준 프로토콜 중 하나
- 현재 HTML5 환경에서 많이 사용
- 실시간 통신이 필요한 서비스를 구현하려 하면 HTTP 프로토콜이 아닌 웹소켓 프로토콜을 사용하는 것이 좋다.
2. HTTP의 한계
- 초기 웹의 목적 = 단순 문서 전달.
- HTTP는 요청한대로 응답을 보내주기만 하는 단순한 프로토콜이다. 이는 단순 문서 전달에 매우 효율적이라 널리 사용되었다.
- 하지만, 인터넷이 발전하면서 채팅, 게임 등의 실시간 통신이 필요한 것들을 바람.
- 하지만 HTTP 프로토콜은 요청에 대해서만 응답을 보낼 수 있기 때문에 채팅에서 계속 메세지를 받기만 하는 상황같은 것을 구현하기 힘들었다.
- 또한, HTTP 프로토콜은 매 요청과 응답마다 연결을 수립하고 끊는 과정을 반복해야해서 유사한 통신을 계속 반복하는 비효율성에 대한 문제
3. 웹 소켓 특징
- 양방향 통신(Full-Duplex)
- 데이터 송수신을 동시에 처리할 수 있는 통신 방법
- 클라이언트와 서버가 서로에게 원할 때 데이터를 주고 받음.
- 통상적인 HTTP 통신은 클라이언트가 요청을 보내는 경우에만 서버가 응답하는 단방향 통신이다.
- 실시간 네트워킹 (Real Time-Networking)
- 웹 환경에서 연속된 데이터를 빠르게 노출한다.
- 여러 단말기에 데이터를 빠르게 교환한다.
- ex) 채팅, 주식, 비디오 데이터
4. 웹 소켓 프로토콜
- 웹소켓은 HTTP와 같은 OSI 모델의 7계층에 위치하는 프로토콜, 4계층의 TCP에 의존한다.
- HTTP 프로토콜을 이용할 때: "http"를 사용, 보안을 강화하기위해 "https"
- 웹소켓을 이용할 때: "ws"를 이용하고 보안을 강화하기 위해 "wss"
- HTTP를 이요해 연결을 수립하며 연결 된 이후에도 연결을 할 때 사용했던 포트인 80과 443포트를 이용한다. 연결 수립은 핸드쉐이크를 통해 이루어지며 핸드쉐이크시 HTTP를 이용한다.
5. 웹 소켓 동작
5.1) Hand Shaking
- 핸드쉐이크는 한번의 HTTP 요청과 HTTP 응답
- 핸드쉐이크가 끝나면 HTTP 프로토콜을 웹소켓 프로토콜로 변환하여 통신을 하는 구조
- 핸드쉐이크는 먼저 클라이언트가 HTTP로 웹소켓 연결 요청을 하면서 시작
웹 소켓 연결 요청
- 웹소켓 연결 요청에는 “Connection:Upgrade”와 “Upgrade:websocket” 헤더를 통해 웹소켓 요청임을 표시합니다. 또한 “Sec-WebSocket-Key” 헤더를 통해 핸드쉐이크 응답을 검증할 키 값을 보냅니다. 그 외에도 WebSocket 연결시 보조로 이용할 프로토콜 정보등의 추가적인 정보를 헤더에 담아 보낼 수 있습니다.
- 웹소켓 연결 요청 예시
// 웹 소켓 요청 HTTP 헤더의 예시 (클라이언트 -> 서버)
GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
GET /chat HTTP/1.1
: 반드시 GET 방식으로만 요청해야함, HTTP는 1.1 이상이여햐 함.
Host: example.com:8000
: 웹 소켓 서버의 주소
Upgrade: websocket
: 현재 클라이언트, 서버, 전송 프로토콜 연결에서 다른 프로토콜로 업그레이드 또는 병경하기 위한 규칙
Connection: Upgrade
: 송신자는 반드시 Upgrade 옵션을 지정한 Connection헤더 필드가 필요
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
: 클라이언트와 서버 간 서로의 신원 인증
Origin: http://example.com
: 클라이언트 주소
Sec-WebSocket-Protocol: chat, superchat
: 여러 서브 프로토콜을 의미. 이 중에서 서버가 지원하는 프로토콜을 다시 반환한다.
웹 소켓 응답
- 이에 대한 응답 역시 HTTP로 온다.
- 정상적인 응답의 상태코드는 101(Switching Protocols)
- “Sec-WebSocket-Key” 헤더를 통해 받은 값에 특정 값을 붙인 후, SHA-1로 해싱하고 base64로 인코딩한 값을 “Sec-WebSocket-Accept” 헤더에 보낸다.
- 이 값을 통해 클라이언트는 정상적인 핸드쉐이크 과정을 검증
- 웹소켓 연결 요청에 대한 응답 예시
// 웹 소켓 응답 HTTP 헤더의 예시 (서버 -> 클라이언트)
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
101 Switching Protocols
: 101 Switching Protocols가 응답으로 오면 웹 소켓이 연결되었다는 의미
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
: 클라이언트로 부터 받은 Sec-WebSocket-Key를 사용하여 계산된 값으로 서로의 신원을 인증하는 과정에 필요한 헤더, 클라이언트에서 계산한 값과 일치하지 않으면 연결하지 않는다.
5.2) 데이터 전송
- 핸드쉐이킹 완료 후 프로토콜이 WS로 변경. 이 순간부터 양방향 통신이 가능해진다.
- ws(80) or wss(443) 으로 통신한다.
- Message : 여러 Frame이모여서 구성하는 하나의 논리적 메시지 단위. ws 프로토콜을 통해 주고 받는 단위라고 생각하면 편하다.
- Frame : Communication에서 가장 작은 단위의 데이터 (작은 헤더 + Payload 로 구성) -> 기존 무거운 헤더의 단점을 보완
- 웹 소켓 통신에 사용되는 데이터는 UTF-8 인코딩을 통해서만 지원
- 0x00{보내고 싶은 데이터}0xff 와 같은 형태로 데이터를 주고 받는다.
5.3) 프레임
- 구조
FIN (END)
: 이 프레임이 전체 메시지의 끝인지 나타내는 플래그
OPCODE
:
- Continue(0x0): 전체 메세지의 일부임을 의미
- Text(0x1): 포함된 데이터가 UTF-8 텍스트라는 의미
- Binary (0x2): 포함된 데이터가 이진 데이터라는 의미
- close(0x8): Close 핸드쉐이크를 시작한다는 의미
- Length: 이 프레임에 포함된 데이터의 총 길이를 나타내는 단위
- RSV 1~3: 프로토콜 별로 사용할 수 도 있고 사용하지 않을 수도 있는 것들.
출처