Server-Sent Events의 기본 개념과 연결 원리 정리
HTTP 기반 지속 연결과 자동 재연결 동작 요약
ext/event-stream 포맷과 event/data/id/retry 필드 규칙 설명
백엔드(res.write)·프론트(EventSource) 예제 코드 포함으로 실무 적용 가이드 제공
목차
- SSE의 개요
- SSE의 연결
- SSE의 구조
- SSE의 송수신 데이터
- SSE의 예시코드
SSE
개요
정의
- 온라인 통신을 위한 “서버 → 클라이언트 스트림”
- 서버가 클라이언트에게 계속 소식을 보내는 통신
- 의미 : 서버가 클라이언트에게 데이터를 계속 “밀어주는” 방식
연결
- 기반 프로토콜 : HTTP ( 보통 HTTP/1.1 또는 HTTP/2)
연결 원리
- HTTP 범위 내에서 연결 일어남
- 통신 과정
- 클라이언트가 EventSourse로 HTTP 요청
- 서버가 연결을 끊지 않음
- 서버가 이벤트를 텍스트 스트림으로 지속 전송
- 클라이언트는 실시간으로 수신만 수행
- 연결 끊기면 자동 재연결
- 방송형 온라인 통신
구조
전체 구조
[브라우저]
EventSource
↓ (HTTP 연결 유지)
[백엔드 서버]
res.write() 로 이벤트 스트림 전송
백엔드에서 연결
[실시간 체결 데이터]
↓
[백엔드]
↓ SSE
[프론트]
- 위의 구조가 흔함
- 이유 보안 | WS는 노출 위험 큼 단방향 충분 | 서버→클라이언트면 SSE로 충분 안정성 | SSE 자동 재연결 인프라 | HTTP 기반이 운영 편함
송수신 데이터
- text Stream : event : / data : 형태
- 이벤트 단위 : 줄 단위 텍스트
- 단순 이벤트 스트림에 적합
SEE 데이터 포맷 규칙
| 필드 |
설명 |
| event |
이벤트 이름 (선택) |
| data |
실제 데이터 (필수) |
| id |
이벤트 ID (재연결 시 사용) |
| retry |
재연결 간격(ms) |
event: trade
data: {"price":71200,"volume":3}
id: 10291
예시 코드
백엔드 예시
import express from 'express';
const app = express();
app.get('/sse', (req, res) => {
// SSE 필수 헤더
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// 최초 연결 확인용 이벤트
res.write(`event: connected\\n`);
res.write(`data: connected\\n\\n`);
let count = 0;
const interval = setInterval(() => {
count++;
res.write(`event: tick\\n`);
res.write(`data: ${JSON.stringify({ value: count, time: Date.now() })}\\n\\n`);
}, 1000);
// 클라이언트 연결 종료 처리
req.on('close', () => {
clearInterval(interval);
console.log('SSE client disconnected');
});
});
app.listen(3000, () => {
console.log('SSE server running on port 3000');
});
| 포인트 |
의미 |
| text/event-stream |
SSE 전용 MIME 타입 |
| res.write |
연결을 끊지 않고 데이터 전송 |
| \n\n |
이벤트 단위 종료 표시 |
| req.on('close') |
클라이언트 이탈 감지 |
프론트엔드 예시 (브라우저)
- 기본 EventSource 사용
const es = new EventSource('/sse');
es.onopen = () => {
console.log('SSE connected');
};
es.onmessage = (event) => {
console.log('message', event.data);
};
es.onerror = (err) => {
console.error('SSE error', err);
};
- 이벤트 타입 별로 받기
const es = new EventSource('/sse');
es.onopen = () => {
console.log('SSE connected');
};
es.onmessage = (event) => {
console.log('message', event.data);
};
es.onerror = (err) => {
console.error('SSE error', err);
};
SSE 의 장점이 코드에서 드러나는 부분
- 자동 재연결 : 네트워크 끊기면 브라우저가 자동 재 시도
- 단순성 : WebSocket 보다 코드 단순
- HTTP 기반 : 프록시/보안 설정 유
실무에서 자주 쓰이는 패턴
event: execution
data: { price, volume, time }
event: notification
data: { title, body }
devTool
| 항목 |
모습 |
| Network |
Fetch/XHR |
| Status |
200 |
| 상태 |
Pending 유지 |
| Response |
텍스트가 계속 누적 |
| Messages 탭 |
없음 |