반응형

Server Sent Event(SSE)란?

  • HTTP 스트리밍을 통해 서버에서 클라이언트로 단방향의 Push Notification을 전송할 수 있는 HTML5 표준 기술.
  • HTTP 프로토콜을 기반으로 서버에서 클라이언트로 Real-Time Push Notification을 전송할 수 있다.
  • EventStream의 최대 개수는 HTTP/1.1 사용시 6개, HTTP/2 사용시 최대 100개까지 유지 가능하다.
  • JavaScript의 EventSource를 이용하여 사용 가능하고, 접속에 문제가 있으면 자동으로 연결을 재시도하는 특징을 갖고 있다.
  • IE에서는 EventSource를 기본 제공하지 않지만 polyfill을 통해 사용 가능하다.
  • Server To Client로의 단방향 연결만 지원하기 때문에 서버에서 데이터를 프론트로 일방적으로 내려주는 케이스에서 적절하다.
  • 양방향 연결을 사용해야할 경우 WebSocket이 적절하다.

Server

@Slf4j
@RestController
public class SseController {
    private static final Map<String, SseEmitter> CLIENTS = new ConcurrentHashMap<>();

    @GetMapping("/api/subscribe")
    public SseEmitter subscribe(String id) {
        SseEmitter emitter = new SseEmitter();
        CLIENTS.put(id, emitter);

        emitter.onTimeout(() -> CLIENTS.remove(id));
        emitter.onCompletion(() -> CLIENTS.remove(id));
        return emitter;
    }

    @GetMapping("/api/publish")
    public void publish(String message) {
        Set<String> deadIds = new HashSet<>();

        CLIENTS.forEach((id, emitter) -> {
            try {
                emitter.send(message, MediaType.APPLICATION_JSON);
            } catch (Exception e) {
                deadIds.add(id);
                log.warn("disconnected id : {}", id);
            }
        });

        deadIds.forEach(CLIENTS::remove);
    }
}

Client

경로 : ~/src/main/resources/static/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input id="input"/>
<button id="send">send</button>
<pre id="messages"></pre>
<script>
    const eventSource = new EventSource(`/api/subscribe?id=${Math.random()}`);

    eventSource.onopen = (e) => {
        console.log(e);
    };

    eventSource.onerror = (e) => {
        console.log(e);
    };

    eventSource.onmessage = (e) => {
        document.querySelector("#messages").appendChild(document.createTextNode(e.data + "\n"));
    };

    document.querySelector("#send").addEventListener("click", () => {
        fetch(`/api/publish?message=${document.querySelector("#input").value}`);
    });
</script>
</body>
</html>

참고

반응형

'Development > Spring' 카테고리의 다른 글

[Spring] DataSource  (0) 2021.05.19
[Spring] Testcontainers  (0) 2021.04.15
[Spring] H2 Database  (0) 2021.02.27
[Spring] Spring Cloud Feign  (0) 2020.12.27
[Spring] Spring Cloud Gateway  (0) 2020.12.27

+ Recent posts