-
Server Sent Event란? - 이론편프로젝트/Server Sent Event 2023. 11. 23. 00:01
Server Sent Event란?
대게 요청은 클라이언트가 서버에게 요청을 먼저 수행하면 그에 대한 응답을 내려줍니다.
하지만 Server Sent Event를 활용하면 서버에서 필요할 때마다 데이터를 클라이언트로 푸시할 수 있습니다.
WebSocket vs Server Sent Event
데이터를 클라이언트로 푸시하는 방안으로는 WebSocket을 활용해볼수도 있습니다.
WebSocket은 양방향 전이중 통신을 위해 사용되고 실시간 업데이트와 클라이언트도 데이터를 전송할 때 활용할 수 있습니다.
즉, 양방향이 필요하다면 WebSocket 그렇지 않다면 SSE를 고려해볼 수 있습니다.
WebSocket을 활용하면 별도의 프로토콜을 사용하지만 SSE를 활용하면 전통적인 HTTP 프로토콜을 활용합니다.
SSE 동작 원리
Content-Type은 text/event-stream 이라는 타입을 받습니다.
Transfer-Encoding은 chuncked인데 서버에서 동적으로 생성된 콘텐츠의 크기를 미리 알 수 없기 때문입니다.
HTTP 1.1 프로토콜에서는 브라우저에서 1개당 최대 6개의 EventStream을 생성할 수 있으며, HTTP/2.0을 사용하면 최대 100개까지 가능합니다.
Client는 javascript를 활용하여 EventSource라는 인터페이스로 SSE 요청을 수행할 수 있습니다.
const sse = new EventSource("http://localhost:8080/connect");
Spring에서는 A와 B라는 요청이 SseEmitter객체로 서버에 저장되어야지 나중에 클라이언트에게 향후 이벤트가 발생했을 때 데이터를 전송할 수 있습니다.
이벤트가 발생했을 때 SseEmitter를 활용하여 클라이언트에게 데이터를 전송할 수 있습니다.
WAS가 여러대일때 SseEmitter가 잘 동기화되도록 redis나 kafka의 pub/sub을 활용해야 할 것 같습니다.
Spring Framework와 SSE
/** * A specialization of {@link ResponseBodyEmitter} for sending * <a href="https://www.w3.org/TR/eventsource/">Server-Sent Events</a>. * * @author Rossen Stoyanchev * @author Juergen Hoeller * @author Sam Brannen * @since 4.2 */ public class SseEmitter extends ResponseBodyEmitter {
Spring Framework 4.2부터 SSE 통신을 지원하는 SseEmitter 클래스가 생겼습니다.
ResponseBodyEmitter는 비동기 응답을 처리합니다, 해당 클래스를 상속받은 SseEmitter는 SSE의 추가적인 기능을 제공합니다.
SSE와 이벤트 유실
EventStream이 만료되어 다시 생성하는 경우 이 순간 클라이언트에서 EventSource 객체를 생성하기 전 서버에서 Event를 전송하는 경우 유실될 수 있습니다.
이에 대한 안정장치로 재생성 요청시엔 Last-Event-ID 헤더를 추가하여 누락된 데이터가 있으면 서버에서 체크 후 다시 보내줍니다.
관련이슈
구현시 주의사항
- 만료시간까지 아무런 데이터를 보내지 않으면 재연결 요청 또는 연결 요청에서 오류가 발생할 수 있음
- onCompletion, onTimeout 콜백은 별도의 스레드에서 호출되기 때문에 thread-safe 한 자료구조로 SSeEmitter 객체를 관리해주어야 한다.
- SseEmitter 객체는 메모리에 저장되기 때문에 서버 인스턴스를 여러 개 사용하는 경우 잘 동기화해주어야 한다.
- Last-Event-ID 헤더를 통해 이벤트 유실을 대비하자
참고자료
https://tecoble.techcourse.co.kr/post/2022-10-11-server-sent-events/
https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events