웹소켓, 폴링, 롱폴링은 클라이언트와 서버 간에 실시간 또는 거의 실시간으로 데이터를 주고 받는 다양한 방식들이다. 각각의 장단점과 동작 방식에 큰 차이가 있다.
1. 폴링(Polling)
동작 방식은 다음과 같다.
- 클라이언트가 주기적으로 서버에 새로운 데이터가 있는지 요청(HTTP GET 요청)을 한다.
- 서버는 요청 시점에 가지고 있는 최신 데이터를 클라이언트에게 응답한다.
- 클라이언트는 일정 시간(예: 1초, 5초)을 기다린 후 다시 서버에 요청한다.
특징은 구현이 가장 간단하다. 일반적인 HTTP 요청-응답이니까. 그래서 비효율적이다. 새로운 데이터가 없어도 클라이언트는 계속해서 서버에 요청을 보내야하고 이는 불필요한 네트워크 트래픽과 서버 자원 낭비를 초래한다. 또 클라이언트가 요청하는 주기만큼 데이터 업데이트에 지연 시간이 발생할 수도 있으며 특히 주기를 짧게 하면 트래픽과 부하가 증가하고, 길게 하면 실시간성이 떨어진다. 각 요청은 독립적이기 때문에 stateless하다.
장점은 구현이 쉽고 모든 웹 환경에서 지원되며(HTTP니까…) 방화벽이나 프록시를 통과하기 쉽다.
보통 아주 높은 실시간성이 요구되지 않고, 주기적으로 데이터를 갱신해도 되는 경우나 오래된 웹 브라우저나 시스템과의 호환성 문제로 다른 방법을 사용할 수 없을 때 사용된다.
2. 롱 폴링(Long Polling / Comet)
동작 방식
- 클라이언트가 서버에 새로운 데이터가 있는지 요청한다.
- 서버는 새로운 데이터가 생길 때까지 응답을 보류(Hold)하고 연결을 열어둔다.
- 새로운 데이터가 생기면 서버는 즉시 클라이언트에게 데이터를 응답하고 연결을 닫는다.
- 클라이언트는 응답을 받으면 즉시 새로운 요청을 다시 서버로 보낸다.
- 이건 옵션인데 특정 시간 동안 데이터가 없으면 서버는 빈 응답을 보내고 연결을 닫으며, 클라이언트는 다시 요청을 보낸다.
특징은 새로운 데이터가 있을 때만 응답하므로 불필요한 트래픽이 줄어들기 때문에 폴링보다는 효율적이다. 또 새로운 데이터가 생기면 거의 즉시 클라이언트에 전달되어 낮은 지연 시간을 가지며 서버가 클라이언트로 데이터를 푸시하는것처럼 단방향(서버 → 클라이언트) 푸시 효과가 나타난다. 여전히 기본적으로 HTTP 요청-응답 모델을 사용한다. 각 이벤트마다 새로운 HTTP 연결이 설정될 수 있다.
장점으로는 폴링보다 실시간성이 좋고, 트래픽이 적다. 또 폴링과 마찬가지로 HTTP 기반이므로 방화벽/프록시 통과가 용이하다.
단점으로는 서버가 각 클라이언트의 열린 연결을 유지해야 하므로 연결 유지 비용(Connection Overhead)이 발생한다. 동시에 많은 클라이언트가 연결되면 서버 자원 소모가 커질 수 있다. 또한 새로운 이벤트마다 연결을 열고 닫는 오버헤드가 있다.
실시간 채팅 앱, 알림 서비스 등 어느 정도의 실시간이 중요하면서도 HTTP 기반의 한계를 넘어서야 할 때 소켓 연결이 어려운 환경에서 대안으로 사용한다.
3. 웹소켓(WebSocket)
동작 방식
- 클라이언트와 서버가 한 번의 HTTP 핸드셰이크(Handshake) 과정을 통해 영구적인 양방향(Full-duplex) 통신 채널을 수립한다.
- 이후에는 이 영구적인 연결을 통해 클라이언트와 서버가 언제든지 서로에게 자유롭게 데이터를 주고 받을 수 잇다. 별도의 HTTP 요청-응답 헤더 없이 원시 데이터(Raw data)를 주고 받는다.
특징은 다음과 같은데
- 진정한 실시간 양방향 통신 : 클라이언트와 서버가 동시에 서로에게 데이터를 보낼 수 있다.
- 낮은 오버헤드 : 한 번 연결이 수립되면 헤더가 거의 없는 데이터 프레임만 주고 받으므로, 매우 효율적이다.
- 낮은 지연 시간 : 즉각적인 데이터 전송이 가능하다.
- 상태 유지(Stateful) : 연결이 유지되는 동안 세션 정보가 유지된다.
세 방식 중 최고의 실시간성과 최소한의 네트워크 트래픽을 가지며 대규모 동시 통신에 매우 효율적이다. 또한 서버 푸시를 매우 효율적으로 구현할 수 있다.
단점으로는 일반 HTTP와 다른 프로토콜이므로, 구현이 폴링/롱폴링보다 복잡할 수 있다. (서버/클라이언트 모두 웹소켓 라이브러리 필요) 방화벽이나 프록시 설정에 따라 연결이 차단될 수 있는 가능성이 있다. 이 경우 WebSocket 프로토콜을 명시적으로 허용해야 한다.
온라인 게임, 실시간 채팅, 주식/암호화폐 거래 시스템, 실시간 협업 도구, 알림 서비스, IoT 기기 통신 등 초고도 실시간 양방향 통신이 필수적인 경우에 사용된다.
세 가지 방식 비교 요약
| 특징 | 폴링 (Polling) | 롱 폴링 (Long Polling) | 웹소켓 (WebSocket) |
|---|---|---|---|
| 통신 방식 | 단방향 (클라이언트 -> 서버) 주기적 요청 | 단방향 (서버 -> 클라이언트) 이벤트 응답 | 양방향 (클라이언트 <=> 서버) 영구 연결 |
| 연결 유지 | 매 요청마다 연결 수립/해제 | 새 이벤트마다 연결 수립/해제 (응답 보류) | 단일 연결 영구 유지 |
| 실시간성 | 낮음 (요청 주기에 따라) | 높음 (이벤트 발생 시 즉시) | 매우 높음 (즉각적) |
| 네트워크 효율 | 낮음 (불필요 요청 다수) | 보통 (이벤트 발생 시만 응답) | 매우 높음 (오버헤드 최소) |
| 서버 부하 | 높음 (반복적인 요청 처리) | 높음 (많은 열린 연결 유지) | 낮음 (한정된 연결 수, 효율적 처리) |
| 구현 복잡도 | 낮음 | 중간 | 높음 |
| HTTP 사용 | HTTP 요청-응답 | HTTP 요청-응답 (연결 유지) | HTTP 핸드셰이크 후 독립 프로토콜 |
그렇다면 웹소켓은 단일연결이 영구 유지되는데 왜 네트워크 효율이 높고 서버 부하가 낮을까? 이는 HTTP의 비효율성을 극복했기 때문이다. 핵심은 연결 유지와 프로토콜 오버헤드에 있다.
웹소켓이 네트워크 효율이 높고 서버 부하가 낮은 이유
- HTTP 요청/응답 헤더 오버헤드 제거
- HTTP (폴링/롱폴링) : 모든 HTTP 요청과 응답에는 상당히 많은 HTTP 헤더 정보가 포함된다. (예 : 쿠키, 인증 토큰, 사용자 에이전트, 캐시 제어 등) 비록 데이터 자체가 작더라도, 이 헤더 정보가 매번 주고 받아지면서 불필요한 네트워크 트래픽을 유발하고, 서버가 이 헤더를 매번 파싱하는데 자원을 소모한다.
- 웹소켓 : 한 번 연결이 수립되면, 초기 핸드셰이크 이후에는 HTTP 헤더 없이 최소한의 프레임(frame)만 주고 받는다. 이 프레임은 데이터 자체만을 담고 있어 오버헤드가 극히 적다.
- 연결 수립 및 해제 오버헤드 제거
- HTTP (폴링/롱폴링)
- 폴링 : 매 요청마다 TCP 연결을 새로 수립하고(3-way handshake), 데이터를 전송한 후 연결을 해제하는 과정을 반복한다. 이 과정 자체가 시간과 자원을 소모한다.
- 롱폴링 : 하나의 요청에 대해 서버가 응답을 보류하지만, 결국 데이터 전송 후 연결을 해제하고, 새로운 데이터가 필요하면 클라이언트가 다시 연결을 수립해야 한다.
- 웹소켓 : 단 한 번의 핸드셰이크를 통해 TCP 연결을 수립하고, 이 연결은 끊어지지 않고 영구적으로 유지된다. 따라서 매번 연결을 수립하고 해제하는데 드는 오버헤드가 없어진다.
- HTTP (폴링/롱폴링)
- 양방향(Full-duplex) 통신
- HTTP (폴링/롱폴링) : 기본적으로 클라이언트의 요청이 있어야 서버가 응답하는 단방향 통신 모델이다. 서버가 클라이언트에 데이터를 보내고 싶어도 클라이언트의 요청이 없으면 보낼 수 없다.
- 웹소켓 : 연결만 되어 있다면, 클라이언트와 서버가 서로에게 언제든지 독립적으로 데이터를 보낼 수 있다. 이는 서버가 특정 이벤트 발생 시 클라이언트의 요청 없이도 즉시 데이터를 푸시할 수 있음을 의미한다. 불필요한 요청-응답 주기를 없애 효율을 높인다.
- 낮은 서버 자원 소모 (특정 상황에서)
- 롱폴링의 문제점 : 롱폴링은 새로운 데이터가 올 때까지 연결을 열어두므로, 동시에 많은 클라이언트가 연결되어 있으면 서버의 열린 소켓 연결 수가 기하급수적으로 증가하여 서버 자원을 많이 소모할 수 있다.
- 웹소켓의 이점 : 웹소켓도 연결을 유지하지만, 한 번 수립된 연결은 매우 효율적으로 데이터를 주고 받도록 최적화 되어 있다. 또한 웹소켓 서버들은 보통 이벤트 기반(Event-driven) 방식으로 동작하여 동시에 수십만 개의 연결을 적은 자원으로도 효율적으로 처리할 수 있다. 각 연결당 HTTP 헤더를 계속 파싱하는 부담이 없기 때문에 더 많은 동시 연결을 감당할 수 잇다.
이처럼 웹소켓은 HTTP의 비연결성(stateless)과 요청-응답 모델에서 발생하는오버헤드를 줄여, 훨씬 더 적은 자원으로 빠르고 효율적인 실시간 양방향 통신을 가능하게 한다.
'CS' 카테고리의 다른 글
| [CS] 프로세스,스레드,멀티스레드 (1) | 2024.02.29 |
|---|---|
| [CS] HTTP Method 종류 (0) | 2023.08.30 |
| [CS] 운영체제 (5) 교착 상태 (0) | 2023.07.28 |
| [CS] 운영체제 (4) 동기화 (0) | 2023.07.27 |
| [CS] 운영체제 (3) CPU 스케줄링 (0) | 2023.07.20 |