핵심 요약
LLM 응답을 토큰 단위로 흘리는 게 표준이 되면서 SSE가 다시 주목받는다. WebSocket이 "당연한 답"이던 시대는 끝났다. 3가지 통신 방식의 적합 영역 정리.
1. 기본 비교
| 지표 | SSE | WebSocket | Long-poll |
|---|---|---|---|
| 방향 | 서버→클라 단방향 | 양방향 | 요청-응답 |
| 프로토콜 | HTTP/1.1 / HTTP/2 | 업그레이드 후 별도 | HTTP |
| 프록시·LB 호환 | 매우 좋음 | 설정 필요 | 완벽 |
| 자동 재연결 | O (브라우저) | X (직접 구현) | X |
| HTTP 캐시·CDN | 가능 | 불가 | 가능 |
| 인증 | HTTP 헤더·쿠키 | 핸드셰이크만 | HTTP |
| 구현 복잡도 | 낮음 | 중간 | 낮음 |
2. AI 스트리밍은 왜 SSE인가
거의 모든 LLM API(OpenAI·Anthropic·Google)가 SSE로 응답. 양방향이 필요 없는 단방향 토큰 스트림에 최적.
// 서버 (Express)
app.get('/chat', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
res.setHeader('Connection', 'keep-alive')
llm.streamChat(req.query.q).on('token', t => {
res.write(`data: ${JSON.stringify({ t })}\n\n`)
})
})
// 클라
const es = new EventSource('/chat?q=hello')
es.onmessage = e => render(JSON.parse(e.data).t)
3. WebSocket이 여전히 답인 곳
- 실시간 협업 (양방향 빈도 높음)
- 게임
- 음성·영상 신호 (별도 미디어 채널)
- 저지연 + 양방향 인터랙션 (트레이딩 등)
4. Long-poll이 답인 곳
- 레거시 프록시·기업망에서 SSE/WS 막힌 환경
- 매우 드문 이벤트 (시간당 1회 미만)
- 모바일 푸시 보조 채널
5. 인프라 함정
① 프록시 타임아웃
Nginx 기본 60초. 스트림이 끊김.
proxy_read_timeout 3600s;
proxy_buffering off; # 핵심! 버퍼링 끄지 않으면 청크가 한 번에 도착
② HTTP/2와 SSE
HTTP/2 위에선 동시 SSE 연결 제한이 풀린다(브라우저당 6개 제약 회피). 운영 장점.
③ Cloudflare·CDN
SSE 대부분 통과. WebSocket은 플랜·라우팅 설정 필요.
④ 서버리스 함수
Lambda·Vercel Functions는 stream 지원이 늘었지만 max duration 제약. 장기 SSE는 별도 워커가 안전.
6. 재연결 — 가장 자주 빠뜨림
SSE는 Last-Event-ID 헤더로 끊긴 곳부터 재전송 가능. 서버 측에서 id 발급 + 버퍼링 필요.
res.write(`id: ${seq}\ndata: ...\n\n`)
// 끊기면 클라가 자동으로 Last-Event-ID 헤더에 직전 id 담아 재요청
const lastId = req.headers['last-event-id']
resumeFrom(lastId)
7. 비용·확장
| 지표 | SSE | WebSocket |
|---|---|---|
| RAM/연결 | ~6KB | ~12KB |
| 1만 연결 서버 | 1코어 | 1.5코어 |
| LB 분산 | HTTP LB 그대로 | sticky/L4 |
8. 양방향이 약간 필요할 때
"클라→서버는 가끔, 서버→클라는 빈번"의 흔한 패턴. SSE + POST 조합.
// 다운: SSE
// 업: 별도 POST /chat/send
fetch('/chat/send', { method: 'POST', body: JSON.stringify(msg) })
9. 결정 트리
| 요구 | 선택 |
|---|---|
| LLM 응답 스트림 | SSE |
| 알림 푸시·실시간 피드 | SSE |
| 주식·코인 시세 | SSE 또는 WS |
| 채팅 (방·타이핑 표시) | WS |
| 협업 에디터 | WS |
| 게임·VoIP | WS / WebRTC |
| 레거시 프록시 환경 | Long-poll |
10. 흔한 함정
- SSE에서 application/json 보냄: 안 됨. text/event-stream + data: 줄.
- EventSource는 헤더 추가 못 함: 인증은 쿠키나 URL token으로 (또는 fetch + ReadableStream)
- WS 인증 토큰 만료: 핸드셰이크 후엔 갱신 어렵다. 토큰 정기 갱신·재연결 정책
- flush 안 됨: 일부 환경(Node/Express)에선
res.flush()필요. Bun은 자동
참고
- html.spec.whatwg.org/multipage/server-sent-events.html
- developer.mozilla.org/Web_APIs/Server-sent_events

댓글 0