-
WebSocket: 실시간 양방향 통신(polling/long-polling/streaming/SSE)CS 2024. 8. 27. 23:44
❓ WebSocket ❓
Web Socket은 두 프로그램 간의 메시지 교환을 위한 통신 방법으로 W3C와 IETF에 의해 표준화된 프로토콜이다.
특히, WebSocket을 지원하는 브라우저에서는 WebSocket 프로토콜을 통해 양방향 통신(Full-Duplex)을 구현할 수 있다.
이는 클라이언트와 서버가 서로에게 데이터를 동시에 주고받을 수 있는 구조인데, 일반적인 HTTP 통신의 경우 클라이언트가 요청을 보내는 경우에만 서버가 응답하는 단방향 통신 구조로 이루어져 있다.
즉, WebSocket을 사용하면 실시간으로 데이터를 주고받을 수 있으며, 서버 또는 클라이언트 측에서 데이터를 보낼 때 지연 시간을 최소화하고 효율적인 양방향 통신을 구현할 수 있다.
📌 WebSocket의 특징 📌
1️⃣ 양방향 통신(Full-Duplex)
위에서 언급했던 것처럼, WebSocket은 데이터 송수신을 동시에 처리할 수 있으며, 클라이언트와 서버가 서로 원할 때 데이터를 주고 받을 수 있다.
2️⃣ 실시간 네트워킹
WebSocket을 사용하면 웹 환경에서 연속된 데이터를 빠르게 전달할 수 있어, 실시간 업데이트가 필요한 어플리케이션에서 주로 사용된다.
3️⃣ 지속적 연결
WebSocket은 HTTP와 달리 연결을 계속 유지하여, 데이터 송수신을 위해 매번 새로운 연결을 설정하는 번거움이 줄어든다.
4️⃣ 낮은 지연 시간
WebSocket은 Header 정보의 크기를 최소화하고 연결 설정과 해제에 드는 시간을 줄여 실시간 통신에서 높은 성능을 제공한다.
🧐 WebSocket 이외 실시간 통신 방식 🧐
Polling
클라이언트가 일정 주기로 서버에 요청을 보내는 방식이다.
실시간 통신에서는 언제 통신이 발생할지 예측할 수 없으며, 불필요한 요청과 연결이 생성될 수 있다.
Long Polliing
Polling의 단점을 최소화하기 위해, 서버에서 이벤트가 발생할 때까지 대기한 후 응답을 보내는 방식이다.
하지만 많은 양의 메시지가 발생할 경우 Polling과 유사한 성능 문제가 발생할 수 있다.
Streaming
서버에 요청을 보내고, 끊기지 않은 연결 상태에서 데이터를 지속적으로 수신하는 방식이다.
하지만 서버로의 데이터 송신이 어렵다는 단점이 있다.
Server-Sent-Events(SSE, 서버 전송 이벤트)
서버에서 클라이언트로 실시간 데이터를 전송하는 단방향 통신 방식이다.
클라이언트는 서버로부터 이벤트 스트림을 받고, 이벤트가 발생할 때마다 데이터를 수신한다.
Push Notifications(푸시 알림)
서버에서 클라이언트로 알림을 보내는 방식이다.
모바일 앱과 웹 애플리케이션에서 주로 사용되며, 사용자가 앱을 열지 않은 상태에서도 중요한 정보나 알림 전송이 가능하다.
MQTT(Message Queuing Telemetry Transport)
경량 메시징 프로토콜이다.
발행-구독 모델을 기반으로 하며, 실시간 데이터를 다루는 데 적합하다.
WebRTC(Web Real-Time Communication)
주로 웹 브라우저 간에 음성 통화, 영상 통화 같은 실시간 미디어 통신을 위한 기술이다.
P2P(Peer-to-Peer) 통신을 지원한다.
HTTP/2
다중화된 요청-응답 통신을 지원하며, 헤더 압축 및 요청 우선순위 설정이 가능하다.
💡참고 💡
최근에는 GraphQL을 사용한 실시간 통신이 증가하고 있는데, 이 GraphQL의 'subscriptions' 기능을 구현하는 데 중요한 역할을 하는 것이 WebSocket으로, 이를 통해 실시간 데이터 업데이트를 구현할 수 있다.🔥 WebSocket의 동작 방식 🔥
WebSocket 프로토콜은 클라이언트와 서버 간의 Handshake 과정을 통해 연결을 설정한다.
이 과정은 클라이언트가 서버와 WebSocket 연결을 수립하기 위해 필요한 과정으로, HTTP 프로토콜을 사용하여 시작된다.
이후, 데이터 전송은 WebSocket Protocl을 이용하여 통신하게 된다.const socket = new WebSocket('ws://localhost:8080'); socket.onopen = () => { console.log('WebSocket Open'); socket.send('Hello Server!'); }; socket.onmessage = (event) => { console.log('서버로부터 메시지:', event.data); }; socket.onclose = () => { console.log('WebSocket Close'); };
위 코드의 WebSocket Handshake 과정은 다음과 같다.
const socket = new WebSocket('ws://localhost:8080');
- 'new WebSocket('ws://localhost:8080');'를 호출하면 WebSocket 객체가 생성되며, 클라이언트는 'localhost:8080'에 연결을 시도한다.
- 이때, 클라이언트는 HTTP 프로토콜을 사용하여 서버에 HTTP Upgrade 요청을 보낸다.
클라이언트가 보낸 요청 헤더는 다음과 같다.
GET / HTTP/1.1 Host: localhost:8080 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Version: 13
- GET: HTTP 메서드로, WebSocket 연결을 요청한다.
- Host: 서버의 호스트명과 포트번호를 나타낸다.
- Upgrade: 'websocket'이라는 값을 지정해 HTTP에서 WebSocket 프로토콜로 업그레이드하려는 걸 나타낸다.
- Connection: Upgrade 값을 사용해, 업그레이드 요청을 보냈다는 것을 의미한다.
- Sec-WebSocket-Key: 클라이언트가 생성한 Base64로 인코딩된 랜덤 키이다. 서버는 이 키를 이용해 응답할 때, Sec-WebSocket-Accept 헤더를 생성한다.
- Sec-WebSocket-Version: 클라이언트가 지원하는 WebSocket 프로토콜의 버전을 나타내는데, 일반적으로 13이다.
서버는 클라이언트가 보낸 HTTP Upgrade 요청을 수신한 후, WebSocket 연결을 수립하기 위해 HTTP 101 Switching Protocols 응답을 반환한다.
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
- HTTP/1.1 101 Switching Protocols: 서버가 클라이언트의 프로토콜 업그레이드 요청을 수락했음을 의미한다.
- Upgrade: 서버가 프로토콜을 WebSocket으로 변경했음을 나타낸다.
- Connection: Upgrade 값으로 클라이언트에 대한 응답임을 나타낸다.
- Sec-WebSocket-Accept: 클라이언트가 보낸 'Sec-WebSocket-Key'를 기반으로 서버가 생성한 응답 값이다. 이는 서버가 클라이언트의 요청을 인증하고 응답의 무결성을 보장하기 위해 사용된다.
서버가 101 응답을 반환하면, 클라이언트와 서버 간의 WebSocket 연결이 수립되고, 이때부터 클라이언트와 서버의 양방향 데이터 전송이 가능하다. 이때 데이터는 WebSocket 프레임으로 인코딩된다.
💡 참고 💡
WebSocket 연결 수립 후 데이터 전송 단위: 프레임(frame)
[ 프레임 구조 ]
1. FIN (1비트): 이 프레임이 메시지의 마지막 부분인지 나타내는 플래그이다.
1이면 메시지의 끝을 의미하고, 0이면 이후에 더 많은 프레임이 따라온다는 것을 의미한다.
2. Opcode (4비트): 이 프레임의 목적을 나타내는 코드이다.
예를 들어, 텍스트 메시지(1), 바이너리 메시지(2), 연결 종료(8) 등이 있다.
3. 마스킹 여부(MASK, 1비트): 프레임의 페이로드가 마스킹(암호화)되었는지 여부를 나타낸다.
클라이언트에서 서버로 전송할 때는 항상 1로 설정되어야 하며, 서버에서 클라이언트로 전송할 때는 0으로 설정된다.
4. Payload length (7, 7+16 또는 7+64 비트): 페이로드의 길이를 나타낸다.
짧은 메시지는 7비트로 표현되며, 더 긴 메시지는 추가 비트를 사용한다.
5. 마스킹 키(Masking key, 0 또는 32비트): 페이로드 데이터의 마스킹을 해제하기 위한 키다.
6. Payload Data: 실제 전송되는 데이터이다.📚 WebSocket의 장단점 📚
장점
- 지연 시간 감소: 지속적인 연결을 통해 요청-응답 지연 시간을 줄일 수 있다.
- 네트워크 효율성: 반복적인 HTTP 요청-응답을 하지 않아, 오버헤드를 줄일 수 있다.
단점
- 방화벽 및 프록시 문제: 일부 방화벽과 프록시 서버는 WebSocket 연결을 차단할 수 있다.
- 프로토콜 복잡성: WebSocket Handshake와 프레임 처리 과정이 다소 복잡하며, 잘못 구현할 경우 보안에 취약할 수 있다.
- 보안적 이슈: 지속적인 연결로 인해 Dos 공격의 표적이 될 수 있다.
- 브라우저 지원: HTML5를 지원하지 않는 브라우저에서는 사용할 수 없다.
- 서버 비용: 지속적인 연결을 유지하므로, 많은 수의 WebSocket 연결을 동시에 관리해야 하는 경우 서버 부하가 증가할 수 있다.
- 재연결 처리: 알 수 없는 에러로 인해 연결이 끊어지면 WebSocket 특성상 자동으로 재연결을 진행하지 않아, 재연결을 할 수 있도록 구현해야 한다.
'CS' 카테고리의 다른 글
[TS] Typescript를 왜 쓸까? (2) 2024.09.18 자바스크립트 배열(JS array)을 다루는 메소드들 (0) 2024.08.31 Ngnix란? (0) 2024.08.22 SEO(Search Engine Optimization, 검색 엔진 최적화) (0) 2024.08.18 Webpack vs Vite (0) 2024.08.16