[Network] Realtime 전송 비교: Polling / SSE / WebSocket / WebRTC
realtime comparison, long polling, polling, SSE vs WebSocket, WebRTC DataChannel, push notification
정의
실시간 (서버 → 클라이언트) 데이터 전송 의 7가지 패턴 비교.
결정 트리
flowchart TD
Q1{양방향 필요?}
Q1 -->|아니오| Q2{영속 연결 OK?}
Q1 -->|예| Q3{브라우저 / 네이티브?}
Q2 -->|예| SSE[SSE]
Q2 -->|아니오| Q4{레거시 호환?}
Q4 -->|예| LP[Long Polling]
Q4 -->|아니오| Poll[Polling]
Q3 -->|브라우저| WS[WebSocket]
Q3 -->|P2P 미디어| RTC[WebRTC]
7가지 비교
| 패턴 | 방향 | 영속 | 프로토콜 | 사용 |
|---|---|---|---|---|
| Short Polling | C → S | 짧음 | HTTP | 단순 / legacy |
| Long Polling | C → S | 짧음 (hold) | HTTP | legacy fallback |
| HTTP/2 server push | S → C | (폐기) | HTTP/2 | (deprecated) |
| SSE | S → C | 영속 | HTTP | 알림, 라이브 피드 |
| WebSocket | 양방향 | 영속 | RFC 6455 | 채팅, 게임 |
| WebTransport | 양방향 (datagrams) | 영속 | HTTP/3 + QUIC | 차세대 (실험적) |
| WebRTC DataChannel | 양방향 (P2P) | 영속 | DTLS + SCTP | 게임 P2P, 파일 |
Polling
sequenceDiagram
loop 5초마다
C->>S: GET /new
S-->>C: 200 [] (변화 없음)
end
Note over C,S: 5초 후
C->>S: GET /new
S-->>C: 200 [msg1]
- 가장 단순. 가장 비효율적.
- 평균 지연 = polling 간격 / 2.
- 메시지 없어도 매 요청 발생 → 서버 부담.
CAUTION
자주 polling = 서버 부담. 드물게 polling = 지연 큼. 둘 다 안 좋음.
Long Polling
sequenceDiagram
C->>S: GET /new (대기 30s)
Note over S: 이벤트 없음, hold
Note over S: 메시지 도착!
S-->>C: 200 [msg1]
C->>S: GET /new (즉시 다음 요청)
Note over S: timeout 30s
S-->>C: 200 [] (timeout)
C->>S: GET /new (재시도)
- 적은 빈도, 낮은 지연.
- legacy 환경 (옛 IE, 일부 프록시) 의 fallback.
- connection 점유 가 polling 보다 길다 → 서버 connection pool 압박.
SSE (단방향 영속)
자세한 건 SSE 참고.
sequenceDiagram
C->>S: GET /stream
S-->>C: 200 (영속)
S-->>C: data: msg1\n\n
S-->>C: data: msg2\n\n
Note over C: 끊김 시 자동 재연결
S-->>C: data: msg3\n\n
- 서버 → 클라이언트 일방향 충분하면 제일 단순.
- 자동 재연결 + Last-Event-ID 재개.
- 프록시 / 방화벽 친화 (HTTP).
WebSocket (양방향 영속)
자세한 건 WebSocket 참고.
sequenceDiagram
C->>S: HTTP Upgrade (handshake)
S-->>C: 101 Switching Protocols
C-->>S: WS frame
S-->>C: WS frame
- 양방향 + 영속. 채팅 / 게임 / 협업 / 트레이딩.
- HTTP 위에서 시작하지만 별도 프레임 프로토콜.
WebTransport (실험적, 차세대)
HTTP/3 (QUIC) 위 양방향 + unreliable datagram + bidirectional streams. WebSocket + UDP datagram 의 결합.
- 2026 시점 모던 브라우저 지원 진입.
- 게임 + 라이브 영상 + AR/VR.
- 아직 대중적 도입 전.
WebRTC DataChannel (P2P)
- 클라이언트 ↔ 클라이언트 직접. 서버는 signaling 만.
- DTLS + SCTP 위.
- P2P 게임, 파일 전송, 영상통화 보조.
- NAT traversal (STUN/TURN) 복잡도.
처리량 vs 지연 vs 복잡도
실시간 패턴: 처리량 vs 지연 (가상 직관)
WebSocket / WebTransport 가 처리량+지연 모두 우수. SSE 는 단방향이지만 그만큼 단순.
WebRTC 시그널링: STUN / TURN
P2P 연결 수립을 위한 시그널링 서버 + NAT traversal.
sequenceDiagram
participant A as Client A
participant Sig as Signaling Server
participant ST as STUN/TURN
participant B as Client B
A->>Sig: SDP Offer
Sig->>B: SDP Offer
B->>Sig: SDP Answer
Sig->>A: SDP Answer
A->>ST: STUN Binding Request
ST-->>A: Public IP:Port
B->>ST: STUN Binding Request
ST-->>B: Public IP:Port
A-->>B: ICE Candidates 교환
Note over A,B: P2P 연결 수립
| 컴포넌트 | 역할 |
|---|---|
| STUN | 공인 IP:Port 탐색 (cheap, UDP) |
| TURN | NAT 뒤 relay (expensive, 모든 트래픽 경유) |
| ICE | STUN + TURN 조합으로 최적 경로 탐색 |
| SDP | 미디어 능력 / 코덱 협상 |
CAUTION
TURN 서버 없으면 Symmetric NAT (기업 방화벽) 뒤 클라이언트 연결 불가. 실서비스는 TURN 필수. TURN 비용 = 전체 트래픽 relay.
스케일링 전략
각 패턴별 서버 사이드 스케일링 고려사항:
flowchart TD
LB[L7 Load Balancer]
LB -->|"SSE / WebSocket"| Sticky["Sticky Session 필요"]
LB -->|"Polling"| Stateless["완전 Stateless 분산"]
Sticky --> Redis["Redis Pub/Sub<br/>노드 간 메시지 팬아웃"]
Redis --> N1[Node 1]
Redis --> N2[Node 2]
Redis --> N3[Node 3]
| 패턴 | 스케일링 방식 | 핵심 도구 |
|---|---|---|
| Polling | Stateless, 그냥 확장 | 없음 |
| Long Polling | Connection 수 관리 | Nginx keep-alive 튜닝 |
| SSE | Sticky session + 팬아웃 | Redis Pub/Sub |
| WebSocket | Sticky session + 팬아웃 | Redis Pub/Sub, Socket.IO |
| WebRTC | 시그널링 서버 분리 | STUN/TURN 별도 |
자세히는 redis-pubsub-vs-streams, sticky-session.
구현 패턴 비교
| 기술 | Node.js 서버 | 브라우저 클라이언트 |
|---|---|---|
| SSE | res.write('data: ...\n\n') | new EventSource('/stream') |
| WebSocket | ws, socket.io, uWebSockets.js | new WebSocket('wss://...') |
| Long Polling | 일반 HTTP, timeout 30s | fetch + 재시도 루프 |
| WebRTC | node-webrtc, Mediasoup | RTCPeerConnection API |
SSE 연결 한계: HTTP/1.1 = 브라우저당 도메인 6 연결 제한. HTTP/2 에서는 다중 SSE 가능.
브라우저 지원 & 제약
| 기능 | Chrome | Firefox | Safari | IE/Edge legacy |
|---|---|---|---|---|
| SSE | 지원 | 지원 | 지원 | SSE 없음 |
| WebSocket | 지원 | 지원 | 지원 | IE11 지원 |
| WebRTC | 지원 | 지원 | 지원 (iOS 제한) | 미지원 |
| WebTransport | 지원 (실험) | 지원 (실험) | 미지원 | 미지원 |
NOTE
iOS Safari 는 SSE 응답 버퍼링 문제 가 있음 (iOS 14 이전). text/event-stream + 작은 청크 크기로 완화. iOS WebRTC 는 Audio 백그라운드 제한 있음.
흔한 함정
WARNING
- SSE + nginx 버퍼링 = 기본 response buffering 으로 메시지 지연.
X-Accel-Buffering: no+proxy_buffering off필수. - WebSocket + ALB 60s idle timeout = heartbeat ping/pong 으로 연결 유지.
- WebRTC + CORS = 시그널링 서버 CORS 설정 + TURN 서버 credential 보호.
- Long Polling 서버 연결 수 = 클라이언트 N명 = 서버 N개 연결 점유. non-blocking I/O (Node.js, async Python) 필수.
- SSE 재연결 폭풍 = 서버 재시작 시 모든 클라이언트 동시 재연결.
Last-Event-ID+ jitter 로 분산.
관련 위키
이 글의 용어 (6개)
- [Django] Channels: WebSocket, Consumer, Groupdjango
- 정의 Django Channels는 Django에 WebSocket, 비동기 프로토콜, 백그라운드 작업을 추가하는 공식 확장. 기본 Django는 HTTP만, Channels는 …
- [Network] HTTP/2: multiplexing, HPACK, server push의 종말network
- 정의 HTTP/2 (2015, RFC 9113) 는 HTTP/1.1 의 문법은 유지하되 전송을 바이너리 + 멀티플렉싱 으로 바꾼다. Head-of-Line Blocking (HT…
- [Network] HTTP/3: QUIC 위의 HTTP, 0-RTT, connection migrationnetwork
- 정의 HTTP/3 (2022, RFC 9114)는 HTTP의 전송 레이어를 TCP 에서 QUIC 으로 교체한 버전이다. UDP 위에 QUIC, QUIC 위에 HTTP 구조다. 핵…
- [Redis] Pub/Sub vs Streams: 휘발 신호 vs 영속 로그database-internals
- 정의 - Pub/Sub ( / ): 지금 듣고 있는 구독자 에게만 메시지가 전달되는 휘발성 신호. 영속 없음, ACK 없음. fan-out. - Streams ( / / / ):…
- SIMDalgorithm
- 정의 SIMD (Single Instruction Multiple Data) 는 한 명령어로 여러 데이터 를 병렬 처리하는 CPU 기능. x86 의 SSE / AVX / AVX2…
- Sticky Sessionconcurrency
- 정의 Sticky Session (= Session Affinity)은 로드밸런서가 같은 클라이언트의 요청을 항상 같은 백엔드 서버로 라우팅하도록 하는 동작이다. 서버, 즉 세션…
💬 댓글