4개월 학습한 비전공자의 WebSocket 포스팅글입니다.
피드백 적극 환영합니다. 성장을 위해 도와주세요.
스프링을 활용한 OTT 서비스 개발 프로젝트 당시 웹소켓을 활용한 실시간 알림이나 채팅 기능을 구현해 본
적이 있다. 당시에 너무 흥미를 느껴 깊이 파보고자 했으나 시간 할애를 하지 못했었다.
시간이 나서 깊게 공부해보고자 포스팅을 시작하게 되었다.
시작에 앞서 웹소켓에 관심을 갖게 되면서 재밌게 본 유튜브 영상이 있어 공유하려고 한다.
https://www.youtube.com/watch?v=MPQHvwPxDUw&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=98
WebSocket
서버와 클라이언트 사이에 데이터를 주고 받을 수 있는 프로토콜로 양방향 소통이 가능하다.
ex) 채팅, 게임, 실시간 차트 등
http에서 실시간 통신을 할 수 없는 문제를 해결하기 위해 나온 기술이다.
http는요청을 보내면 응답이 오는 단방향적 구조로 통신을 하기 때문에 TCP/IP 프로토콜을 사용하는 소켓처럼 계속 connection이 유지되는 실시간 통신을 할 수 없다.
http의 특징
단방향 통신(비연결성)
request - response의 구조
헤더의 비중이 너무 크다(실시간으로 많은 데이터를 주고 받을 경우 비경제적임)
ajax또한 http를 이용하기 때문에 요청을 통한 응답의 구조이다.
변경된 데이터를 가져오기 위해서는 이벤트를 발생시키거나, 일정 시간 주기로 요청을 보내야한다.
특징
1. 양방향 통신
2. 실시간 네트워킹 (연결 유지)
3. 핸드쉐이크 과정에서는 헤더의 비중이 크지만, 연결 된 후에는 간단한 메세지들만 오가기 때문에 경제적이다.
동작 과정
크게 세가지로 분류되는데, Openeing HandShake, Data transfer, Closing HandShake로 나뉜다
HandShake
악수는 두 명의 사람이 만나서, 악수를 요청하고, 악수를 받는다. 총 세 가지의 과정을 거쳐 "악수" 라는 연결이 성립되는 것이다. 이를 통해 클라이언트와 서버간의 연결을 성립하는 과정이 필요하다는 것을 알 수 있다.
핸드쉐이크란 통신이 시작되기 전 두 지점이 확립된 연결을 가지도록 설정하는 것이다.
HandShake
접속 요청은 http로 진행되며, HandShake가 완료되면 웹소켓 프로토콜(WS)로 변경된다.
RequestHeader
<!-- ws로 변경되기 위한 httprequestheader -->
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:9090
GET /path HTTP/1.1
Host: ip:port
<!-- 반드시 HTTP버전 1.1이상, GET을 사용 -->
<!-- ip:port/path으로의 접속 ex)localhost:8080/chat-->
Upgrade: websocket
<!-- 프로토콜을 전환하기 위해 사용하는 헤더 -->
<!-- websocket의 값이 없거나 다른 값이면 cross-protocol-attack으로 간주하여 접속 중지 -->
Connection: Upgrade
<!-- 전송이 완료된 후 네트워크 접속을 유지할 것인지에 대한 정보 -->
<!-- 웹소켓 요청 시 반드시 Upgrade -->
<!-- 위의 Upgrade 헤더와 마찬가지로 값이 없거나 다른 값이면 접속 중지 -->
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
<!-- Key : 유효한 요청인지 확인하기 위해 사용하는 키값 -->
<!-- Protocol : 사용하고자 하는 하나 이상의 웹 소켓 프로토콜 지정, 필요한 경우 사용 -->
<!-- Version : 버전 -->
Origin: http://ip:port
<!-- CORS 정책으로 만들어진 헤더 -->
<!-- CSWSH(Cross-Site Websocket Hijacking)과 같은 공격을 피하기 위한 헤더 -->
CORS(교차 출처 리소스 공유)
웹 페이지에서 실행되는 자바스크립트 XMLHttpRequest(XHR) 호출이 출처가 다른 도메인의 리소스와 상호작용할 수 있도록 허용하는 표준 메커니즘
CSWSH(Cross-Site Websocket Hijacking)
Cross domain간 사용 정책인 Origin 헤더에 대한 검증 미흡으로 발생하는 문제로 서버가 Origin을 제대로 검증하지 않는다면 어떤 도메인에서도 사용자의 세션을 통해 WebSocket을 사용할 수 있다.
ResponseHeader
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
HTTP/1.1 101 Switching Protocols
<!-- 101 : http에서 ws로 프로토콜 전환이 승인되었다는 응답코드 -->
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
<!-- 요청 헤더의 Sec-WebSocket-Key에 고유ID를 더해 SHA-1로 해싱 후 base64로 인코딩한 결과 -->
<!-- 웹소켓 연결이 개시되었음을 알림 -->
Data Transfer
HandShake를 통해 ws프로토콜이 생성되고 나면 진행되는 과정으로 데이터는 메세지단위로 전달된다.
메세지
여러 프레임이 모여 구성되는 하나의 논리적인 단위
프레임
통신에서 가장 작은 단위의 데이터
데이터 링크계층(이더넷)에서 주고받는 가장 작은 단위로 작은 헤더+payload로 구성되어 있다.
※ 패킷 : 전 네트워크 통신 과정에서 가장 작은 단위
웹소켓의 한계
웹소켓은 HTML5의 기술이기 때문에 오래된 버전의 웹에서는 지원하지 않는다.
Socket.io / sockJS
HTML5 이전의 기술로 구현된 서비스에서 웹 소켓처럼 사용할 수 있도록 도와주는 기술 (JS 라이브러리)
웹 소켓, 폴링, 스트리밍 등 다양한 방법을 하나의 API로 추상화한 것이다.
브라우저 종류에 상관 없이 실시간 웹을 구현할 수 있는 라이브러리이다.
또한 웹소켓은 메세지를 주고받을 뿐 어떠한 역할도 하지 않으며, 주고받은 문자열은 온전히 어플리케이션에게 해석을 맡긴다. HTTP는 형식을 정해두었기 때문에, 약속을 따르기만 한다면 해석이 가능하지만, 웹 소켓은 그렇지 않기 때문에, 해석하기가 힘들다.
때문에 웹 소켓에서는 서브 프로토콜을 사용하여 주고받는 메세지의 형태를 약속하는 경우가 많다.(STOMP)
STOMP
웹 소켓에서 동작하는 문자 기반 메세징 프로토콜로써 메세지의 유형, 형식, 내용들을 정의하는 매커니즘
참고 (웹 소켓 이전의 실시간 통신 기술)
웹 소켓이 나오기 전, 양방향 통신과 실시간 네트워킹을 가능하게 했던 통신 방식들이 있었다.
1. polling
- 일정 주기로 서버에 요청을 보내는 방법
2. long-polling
- 서버가 응답을 바로 보내지 않고 특정 이벤트나 타임아웃이 발생했을 때 응답을 전달하는 방법
3. streaming
- 이벤트 발생 시 응답하지만, 응답을 완료시키지 않고 계속 연결을 유지하는 방식
세 방식 모두 부하가 발생할 수 있고 Header가 불필요하게 커진다.
참조
https://velog.io/@codingbotpark/Web-Socket-%EC%9D%B4%EB%9E%80
https://fgh0296.tistory.com/24
https://velog.io/@qkrqudcks7/STOMP%EB%9E%80
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!