-
Web Socket과 STOMP 이해하기Today I Learned 2022. 12. 17. 02:33
Web Socket
- 클라이언트와 서버 간의 메시지를 교환하기 위한 통신 방법 중의 하나
- 2011년 RFC 6455에 의해 표준화
- Web Socket을 지원하는 브라우저는 Web Socket Protocol을 지원
Web Socket의 특징
- 양방향 통신 (Full-Duplex)
- 데이터 송/수신을 동시에 처리할 수 있음
- 클라이언트가 요청을 보낼 때만 서버가 응답하는 단방향 통신인 HTTP 통신과는 달리, 클라이언트와 서버가 서로 원하는 순간에 데이터를 주고받을 수 있음
- 실시간 네트워킹 (Real-Time Networking)
- 연속된 데이터를 빠르게 노출시킬 수 있음
- 여러 단말기에 빠르게 데이터를 교환할 수 있음
- Web Socket의 주 사용처: 주식, 게임, 채팅, 영상 등
Web Socket 이전의 HTTP를 이용한 실시간 통신 기술
- Polling
- 클라이언트가 서버에 일정 주기로 요청을 지속적으로 송신
- 불필요한 요청 생성으로 인한 오버헤드가 발생할 수 있음
- Long Polling
- 클라이언트가 서버에 요청을 보낸 뒤, 응답을 수신할 때까지 연결을 종료하지 않고 대기, 응답 시 연결을 끊고 다시 요청
- 통신의 양이 많아질 경우 Polling 방식과 유사해짐
- Streaming (Server Side Events?)
- 클라이언트가 서버에 요청을 보내면, 연결을 유지한 상태로 서버로부터 지속적으로 응답을 수신
- 클라이언트에서 서버로의 데이터 송신이 어려움
- HTTP를 이용한 실시간 통신은 요청, 응답 모두 빠르게 데이터를 주고받기에는 Header가 불필요하게 크다는 단점이 존재
Web Socket의 동작
Web Socket의 동작은 크게 핸드 쉐이킹(Opening Handshake), 데이터 전송(Data Transfer), 연결 종료(Close Handshake)의 과정으로 이루어짐
핸드 쉐이킹
요청
GET /chat HTTP/1.1 Host: localhost:8080 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://localhost:9000
- 연결 수립
- ws/wss 프로토콜이 아닌 http/https 프로토콜을 사용
- GET
- HTTP는 1.1 이상
- Host
- 웹 서버의 주소
- 웹 서버의 주소
- Upgrade
- 프로토콜 전환을 위한 헤더
- 웹 소켓 요청 시에는 반드시 websocket 값을 부여
- 해당 헤더가 없거나 다른 값일 경우 cross-protocol attack으로 간주하여 웹 소켓 접속을 중지시킴
- Connection
- 요청 완료 후 네트워크 접속 유지 여부에 대한 정보
- Upgrade 헤더가 명시되었을 경우, 요청에는 반드시 Upgrade 옵션을 지정한 Connection 헤더를 같이 명시해야 함
- 해당 헤더가 없거나 다른 값일 경우 웹 소켓 접속을 중지시킴
- Sec-WebSocket-Key
- 16byte 길이의 임의의 숫자를 base64로 인코딩한 값
- 클라이언트와 서버 간 인증에 사용
- Sec-WebSocket-Protocol
- 클라이언트가 요청하는 프로토콜들로, 하나 이상의 웹 소켓 프로토콜들을 지정
- 공백 문자로 구분, 순서에 따라 우선권을 부여
- 서버에서 각 프로토콜이나 프로토콜 버전에 따라 서비스를 나눌 경우 필요
- Origin
- 클라이언트의 주소
- 해당 헤더가 없는 경우 요청이 거부될 수 있음 (CORS 정책)
응답
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
- 101 Switching Protocols
- 웹 소켓이 연결되었음을 나타냄
- 웹 소켓이 연결되었음을 나타냄
- Upgrade, Connection: 요청과 동일
- sec-WebSocket-Accept
- Sec-WebSocket-Key 값을 unique id 값을 더해 SHA-1로 해싱한 값을 base64로 인코딩한 결과값
- 해당 값이 클라이언트에서 계산된 값과 일치해야 연결 수립
데이터 전송
- 프로토콜이 http/https에서 ws/wss로 변경
- port는 http와 같은 port를 사용 (ws: 80, wss: 443)
- port는 http와 같은 port를 사용 (ws: 80, wss: 443)
- 클라이언트와 서버는 Message 단위로 데이터를 주고받으며, Message는 한 개 이상의 Frame으로 구성됨
- Message
- 여러 Frame들이 모여 구성되는 논리적 단위
- Message에는 텍스트 데이터와 이진 데이터만이 담길 수 있음
- Frame
- 데이터 전송에 사용되는 가장 작은 단위의 데이터
- 헤더 + payload로 구성
- 텍스트 데이터 (UTF-8), 이진 데이터, 컨트롤 프레임(프로토콜 레벨 신호) 등이 있음
- Message
- Web Socket 통신에는 UTF-8 인코딩을 사용
- [0x00][UTF-8 Payload][0xff]
- [0x00][UTF-8 Payload][0xff]
Frame
Web Socket Frame의 헤더는 위와 같이 구성되며, 주요 구성 요소들은 다음과 같다.
- FIN(END): 해당 프레임이 전체 메시지의 끝인지를 나타내는 플래그
- OPCODE
- Frame의 용도를 나타냄
- 0x0: 전체 메시지의 일부임을 의미
- 0x1: 포함된 데이터가 UTF-8 텍스트임을 의미
- 0x2: 포함된 데이터가 이진 데이터임을 의미
- 0x8: Close 핸드 쉐이크를 시작함을 의미
- Length
- Frame에 포함된 데이터의 총 길이를 나타냄
- Frame에 포함된 데이터의 총 길이를 나타냄
연결 종료
- 클라이언트 혹은 서버가 상대방에게 연결 종료를 위한 Close Frame을 전송
- 요청을 받은 쪽에서 응답으로 Close Frame을 전송하여 Web Socket 연결 종료
Socket.io, SockJS
- HTML5 이전의 기술로 구현된 서비스에서 Web Socket과 유사한 실시간성을 보장하도록 지원
- JavaScript를 이용하여 구현
- 여러 실시간 통신 기법들을 하나의 API로 추상화한 뒤, 브라우저와 웹 서버의 종류, 버전을 파악하여 가장 적합한 기술을 선택해 사용
- WebSocket, FlashSocket, AJAX Long Polling, AJAX Multipart Streaming, IFrame, JSONP Polling 등
- WebSocket, FlashSocket, AJAX Long Polling, AJAX Multipart Streaming, IFrame, JSONP Polling 등
STOMP (Simple Text Oriented Messaging Protocol)
- Frame 기반의 서브 프로토콜 (sub-protocol)
- Web Socket 자체는 메시지를 주고받는 형식이 정해져있지 않음
- Web Socket에서 클라이언트와 서버가 주고받는 메시지의 형태를 약속
- TCP, Web Socket과 같은 양방향 네트워크 프로토콜에서 사용될 수 있음
- 메시지 브로커를 활용하여 채팅 통신을 위한 형식을 정의
- Publish-Subscribe 구조: 메시지를 공급하는 주체와 소비하는 주체를 분리해 메시징을 제공
- Message Broker: 발신자가 메시지를 발행하면 수신자들이 발행된 메시지를 수신하도록 메시지를 전달하는 주체
- Spring은 WebSocket 사용 시 STOMP를 지원
STOMP의 Frame 구조
STOMP의 Frame은 Command, Header, Body로 구성됨
COMMAND header1:value1 header2:value2 Body^@
- Command
- 종류: CONNECT, SEND, SUBSCRIBE, UNSUBSCRIBE 등
- 종류: CONNECT, SEND, SUBSCRIBE, UNSUBSCRIBE 등
- Header
- key:value 형태로 정보를 포함
- Header와 Body는 빈 줄로 구분
- Body
- 데이터(Payload)가 포함됨
- Body의 마지막은 NULL 문자로 설정됨
STOMP 기반의 통신 흐름
- 구독자들이 특정 경로를 구독
- 발신자가 메시지를 송신
- 메시지가 서버 내에서 처리 과정을 거친 뒤, 혹은 즉각적으로 Message Broker에게 전달됨
- Message Broker는 특정 경로를 구독하고 있는 모든 구독자들에게 전달받은 메시지를 송신
References
개요
- https://www.rfc-editor.org/rfc/rfc6455
- https://www.youtube.com/watch?v=MPQHvwPxDUw
Web Socket
- https://kellis.tistory.com/65
- https://alnova2.tistory.com/915
- https://ko.javascript.info/websocket
STOMP
- https://www.youtube.com/watch?v=rvss-_t6gzg
- https://velog.io/@gillog/Protocol-STOMP
- https://zamezzz.tistory.com/319
'Today I Learned' 카테고리의 다른 글
WebSocket을 이용한 실시간 채팅 구현하기 2: 클라이언트 (0) 2022.12.21 WebSocket을 이용한 실시간 채팅 구현하기 1: 서버 (0) 2022.12.18 Polling 방식을 이용해 간단한 실시간(?) 채팅 구현하기 (0) 2022.12.15 중첩된 DTO을 Validation할 때는 DTO 필드에 @Valid 어노테이션을 붙이기 (1) 2022.12.14 한 번의 끝맺음을 준비하기 (0) 2022.12.11