...
SSE - Server Sent Events 란?
SSE는 서버의 데이터를 실시간으로, 지속적으로 Streaming 하는 기술 이다.
SSE는 웹 표준으로써 IE를 제외한 모든 브라우저에서 지원되며, IE역시 polyfill을 통해 지원이 가능하다.
기존에는 서버의 변경된 데이터를 가져오기 위해서 페이지 새로고침, 지속적으로 request를 보내는 ajax 폴링, 외부 플러그인 이용등을 사용해야만 했었다. 이외에도 websocket을 사용할 수 있지만 HTTP 통신을 이용하는 것이 아닌 웹소켓만을 위한 별도의 서버와 프로토콜로 통신하기 때문에 구현하는 비용이 많이 든다는 단점이 있다.
하지만 SSE는 기존 HTTP 웹 서버에서 HTTP API 만으로 동작되며 구현도 간단하기 때문에 서버와 프론트엔드 양측 모두 매우 쉽게 개발이 가능하다.
Server Sent Event 특징
- 브라우저는 서버가 생성 한 Stream 을 계속 받음(Server 에서 보내는 Stream 으로 Read Only)
- Connection 유지를 위해 HTTP protocol 을 사용, HTTP/2를 통한 multiplexing 사용 가능
- 연결이 끊어지면 EventSource가 오류 이벤트를 발생시키고 자동으로 다시 연결을 시도(error recovery)
- 표준 기술로 IE 를 제외한 브라우저 대부분을 지원(Pollyfill로 IE 사용 가능)
Server Sent Event 사용 시점
- 효율적인 단방향 통신이 필요한 경우
- 실시간 데이터 스트림밍에 HTTP 를 사용하려는 경우(RestFul 의 GET method 와 유사)
- 사용 되는 예 (클라이언트는 수신만 받으면 된다)
- 암호 화폐 또는 주가 피드 구독
- Twitter 피드 구독
- 라이브 스포츠 점수 받기
- 뉴스 업데이트 또는 알림
WebSocket vs Server Sent Events
이 둘의 대표적인 차이점으로는, Socket은 양방향(bidirectional)으로 데이터를 주고 받을 수 있지만, SSE(Server-Sent-Event)를 사용하게 되면 클라이언트는 데이터를 받을 수만(mono-directional) 있다는 점이다.
Socket | Server-Sent-Event | |
브라우저 지원 | 대부분 브라우저에서 지원 | 대부분 모던 브라우저 지원(polyfills 가능) |
통신 방향 | 양방향 | 일방향(서버 -> 클라이언트) |
리얼타임 | Yes | Yes |
데이터 형태 | Binary, UTF-8 | UTF-8 |
자동 재접속 | No | Yes(3초마다 재시도) |
최대 동시 접속 수 | 브라우저 연결 한도는 없지만 서버 셋업에 따라 다름 | HTTP를 통해서 할 때는 브라우저당 6개 까지 가능 / HTTP2로는 100개가 기본 |
프로토콜 | websocket | HTTP |
베터리 소모량 | 큼 | 작음 |
Firewall 친화적 | Nope | Yes |
솔직하게 말해서, SSE 알 필요도 없이 Socket 하나만 알고있어도 구현하는데 문제는 없다. Socket은 양방향 통신이기 때문에 당연하게도 SSE역할도 문제없이 해내기 때문이다.
그러나 위에서 보는 것처럼 websocket과 SSE의 스펙 차이점(배터리,재접속 등) 때문에 사용처에 따라 선택적으로 사용되는 편이다.
예를들어 웹소켓은 주로 리얼타임이 필요한 곳에서 많이 사용된다.
- 카카오톡 쳇(SSE와 HTTP로도 만들 수는 있음)
- 주식 트레이딩 데이터
- 크립토 실시간 차트
SSE는 많이 사용되는 곳이 알람을 줄 때 많이 사용된다.
- Twitter에서 피드를 받을 때
- 페북에서 친추 요청을 받았을 때
왜냐하면 클라이언트에서는 데이터를 받기만 하면 되고 완전히 실시간일 필요는 없기 때문이다.
앞서 말했듯이 웹소켓으로도 충분히 구현할수도 있지만, SSE만의 장점이 있기때문에 나뉘어 쓰인다.
SSE는 전통적인 HTTP를 통해 전송되어 즉, 작동하려면 특별한 프로토콜이나 서버 구현이 필요하지 않다.
반면 WebSockets는 프로토콜을 처리하기 위해 전이중 연결과 새로운 웹 소켓 서버가 필요하다.
그리고 위의 표에서 알수있듯이, 자동 재연결 기능이라던지, 배터리 소모량이라던지 여러모로 다른 특징 때문에 나뉘어 사용되는 편이다.
Node.js SSE 구현 해보기
클라이언트 - SSE
왠만한 브라우저는 SSE를 쉽게 사용할 수 있도록 기본적으로 EventSource API를 제공한다.
서버에서 업데이트된 내용이 푸시되면 onmessage 함수가 실행되고 et.data 속성에서 데이터를 사용할 수 있다.
// 이벤트를 전달 받기 위해서 서버로 접속을 시작하려면 우선, 이벤트를 생성하는 서버측 스크립트를 URI로 지정하여 새로운 EventSource 객체를 생성한다
// EventSource 생성자에 전달 된 URL이 절대 URL 인 경우 해당 출처 (scheme, domain, port)가 호출 페이지의 출처와 일치해야 한다.
const eventSource = new EventSource(`/subscribe`); // sse코드가 있는 서버단 파일
// 서버로부터 데이터가 오면
eventSource.addEventListener('message', function(e) {
console.log(e.data);
});
// connection되면
eventSource.addEventListener('open', function(e) {
// Connection was opened.
});
// error 나면
eventSource.addEventListener('error', function(e) {
if (e.readyState == EventSource.CLOSED) {
// Connection was closed.
}
});
이벤트를 생성하는 스크립트가 다른 도메인에 존재할 경우엔 URI와 옵션 딕셔너리를 모두 지정하여 새로운 EventSource 객체를 생성한다.
클라이언트 스크립트가 example.com에 있는 경우라면,
const evtSource = new EventSource("//api.example.com/ssedemo.php", { withCredentials: true } );
IE 브라우저 지원
브라우저가 SSE를 지원하는지 안 하는지 알아보는 방법도 있다.
if ('EventSource' in window) {
// use polyfills
}
var source = new EventSource('URL');
다음 라이브러리를 쓰면 SSE를 지원안하는 브라우저(IE)에서도 SSE를 사용할 수 있게 된다. (Polyfill)
<script src="https://unpkg.com/event-source-polyfill/src/eventsource.min.js"></script>
서버 - SSE
SSE 모듈을 이용하면 간단하게 구현이 가능하다
$ npm i sse
/* subscribe.js */
/* 클라이언트에서 지정한 sse경로와 맞춰준다. new EventSource(`/subscribe`) */
const SSE = require('sse');
// ...
const server = app.listen(7777, () => {
console.log('7777번 포트에서 대기중');
});
const sse = new SSE(server);
// new EventSource('/subscribe') 하는 순간 클라이언트와 연결
sse.on('connection', (client) => {
setInterval(() => { // 1초마다 클라이언트에 데이터 전송
client.send(Date.now().toString()); // 문자열만 보낼 수 있음
}, 1000);
});
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.