Spring Boot · 2026-01-30

SSE로 Spring Boot 실시간 업데이트 구현하기

Spring Boot에서 SSE를 이용해 서버에서 클라이언트로 실시간 이벤트를 푸시하는 개념과 구현 예제, 클라이언트 처리 및 주의사항 설명

작성일 : 2026-01-30 ㆍ 작성자 : 관리자
post
목차

개요: SSE란 무엇인가

Server-Sent Events(SSE)는 서버에서 클라이언트로 단방향 실시간 데이터를 푸시하는 표준 기술이다. 웹소켓과 달리 연결이 간단하고 HTTP 기반으로 작동한다. 간단한 실시간 알림, 로그 스트리밍, 주기적 상태 업데이트에 적합하다. 이 글은 spring boot sse 사용법을 중심으로 server sent events spring boot 구현 흐름과 sse spring boot 예제를 다룬다.

SSE의 장단점

장점

  • HTTP 기반으로 방화벽 우회가 용이하다.
  • 브라우저에서 EventSource API로 쉽게 수신 가능하다.
  • 구현이 비교적 단순하다.

단점

  • 단방향 통신만 지원한다.
  • 대량의 양방향 통신에는 적합하지 않다.

환경 설정

Spring Boot에서 SSE를 사용하려면 Spring Web(starter-web) 또는 WebFlux(starter-webflux)를 사용한다. 작은 예제는 MVC 기반의 SseEmitter로도 충분하다. 의존성은 다음과 같다.

pom.xml 의존성 예시

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

서버 구현: SseEmitter 예제

아래 코드는 MVC 환경에서 간단히 SSE를 구현한 컨트롤러이다. 클라이언트가 /stream 엔드포인트에 접속하면 서버는 주기적으로 이벤트를 전송한다.

package com.example.sse;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@RestController
public class SseController {

  @GetMapping("/stream")
  public SseEmitter stream() {
    SseEmitter emitter = new SseEmitter(0L); // timeout 없음

    Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
      try {
        emitter.send("data: 현재시간: " + System.currentTimeMillis() + "\n\n");
      } catch (IOException e) {
        emitter.completeWithError(e);
      }
    }, 0, 3, TimeUnit.SECONDS);

    return emitter;
  }
}

핵심 포인트

  • SseEmitter는 서버에서 클라이언트로 스트리밍을 제공한다.
  • 타임아웃을 0으로 설정하면 무한 대기 가능하다(자원 관리 유의).
  • 에러 발생 시 completeWithError 또는 complete 호출로 연결을 종료한다.

리액티브 스타일: WebFlux와 Flux 사용

WebFlux를 사용하면 Flux<ServerSentEvent<T>> 형태로 더 선언적이고 확장성 있는 스트리밍을 만들 수 있다. 대량 연결과 백프레셔 처리가 필요한 경우 WebFlux가 유리하다.

import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.time.LocalTime;

@RestController
public class FluxSseController {

  @GetMapping(value = "/flux-stream", produces = "text/event-stream")
  public Flux<ServerSentEvent<String>> streamFlux() {
    return Flux.interval(Duration.ofSeconds(2))
        .map(seq -> ServerSentEvent.builder("time: " + LocalTime.now()).id(String.valueOf(seq)).build());
  }
}

클라이언트 구현 (브라우저)

브라우저에서는 EventSource API로 간단히 수신할 수 있다. reconnect는 브라우저가 자동으로 시도한다.

<!doctype html>
<html>
<head><meta charset="utf-8"/><title>SSE Client</title></head>
<body>
<div id="log"></div>
<script>
  const evtSource = new EventSource('/stream');
  evtSource.onmessage = function(event) {
    const log = document.getElementById('log');
    log.innerHTML += '<p>' + event.data + '</p>';
  };
  evtSource.onerror = function(err) {
    console.error('SSE error', err);
  };
</script>
</body>
</html>

운영에서의 고려사항

  • 커넥션 수 제한과 스레드/리액터 자원 관리 계획 필요.
  • 프록시나 로드밸런서에서 HTTP 타임아웃을 적절히 설정.
  • 보안: 인증·인가 토큰을 헤더 또는 쿼리로 전달하고 만료 처리 필요.
  • 재연결 정책: 클라이언트 단에서 재시도 로직을 보완하면 안정성 향상.

디버깅 및 테스트

curl로 간단히 이벤트를 확인할 수 있다. 서버가 text/event-stream을 반환하는지, 이벤트 포맷(data:, id:, event:)이 올바른지 점검한다.

맺음말

SSE는 단방향 실시간 업데이트에 적합한 경량 기술이다. spring boot sse 사용법을 이해하면 간단한 알림 시스템이나 모니터링 대시보드에 빠르게 적용할 수 있다. 더 많은 연결과 복잡한 양방향 통신이 필요하면 WebSocket과의 비교 검토가 필요하다. 위 예제는 server sent events spring boot와 sse spring boot 예제 참고용으로 기본 흐름을 설명한 내용이다.

spring boot sse 사용법 server sent events spring boot sse spring boot 예제 SSE 구현 SseEmitter EventSource Spring WebFlux 실시간 업데이트