ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Server Sent Event란? - 이론편
    프로젝트/Server Sent Event 2023. 11. 23. 00:01
    728x90

    Server Sent Event란?

    대게 요청은 클라이언트가 서버에게 요청을 먼저 수행하면 그에 대한 응답을 내려줍니다.

    하지만 Server Sent Event를 활용하면 서버에서 필요할 때마다 데이터를 클라이언트로 푸시할 수 있습니다.

     

    WebSocket vs Server Sent Event

    데이터를 클라이언트로 푸시하는 방안으로는 WebSocket을 활용해볼수도 있습니다.

    WebSocket은 양방향 전이중 통신을 위해 사용되고 실시간 업데이트와 클라이언트도 데이터를 전송할 때 활용할 수 있습니다.

    즉, 양방향이 필요하다면 WebSocket 그렇지 않다면 SSE를 고려해볼 수 있습니다.

     

    WebSocket을 활용하면 별도의 프로토콜을 사용하지만 SSE를 활용하면 전통적인 HTTP 프로토콜을 활용합니다.

     

    SSE 동작 원리

    https://sothoughtful.dev/posts/sse/

     

    Content-Type은 text/event-stream 이라는 타입을 받습니다.

    Transfer-Encoding은 chuncked인데 서버에서 동적으로 생성된 콘텐츠의 크기를 미리 알 수 없기 때문입니다.

     

    HTTP 1.1 프로토콜에서는 브라우저에서 1개당 최대 6개의 EventStream을 생성할 수 있으며, HTTP/2.0을 사용하면 최대 100개까지 가능합니다.

     

     

    https://tecoble.techcourse.co.kr/post/2022-10-11-server-sent-events/

    Client는 javascript를 활용하여 EventSource라는 인터페이스로 SSE 요청을 수행할 수 있습니다.

    const sse = new EventSource("http://localhost:8080/connect");

     

    Spring에서는 A와 B라는 요청이 SseEmitter객체로 서버에 저장되어야지 나중에 클라이언트에게 향후 이벤트가 발생했을 때 데이터를 전송할 수 있습니다.

     

    https://tecoble.techcourse.co.kr/post/2022-10-11-server-sent-events/

    이벤트가 발생했을 때 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 헤더를 추가하여 누락된 데이터가 있으면 서버에서 체크 후 다시 보내줍니다.

     

    관련이슈

    https://stackoverflow.com/questions/58335110/some-of-server-sent-events-lost-while-eventsource-reconnecting/58374643#58374643

     

    구현시 주의사항

    • 만료시간까지 아무런 데이터를 보내지 않으면 재연결 요청 또는 연결 요청에서 오류가 발생할 수 있음
    • 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

    https://www.baeldung.com/spring-mvc-sse-streams

    댓글

Designed by Tistory.