본문 바로가기
Java

[Spring Boot] SSE(Server-Sent-Event) 설정, 사용법을 알아보자!

by parkjp 2023. 8. 10.

 

 

1. Dependency 추가하기

 

우선 필요한 dependency를 추가해 줍시다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
}

 

 

 

 

2. SSE 설정 및 사용법

 

클라이언트에서 Sse 이벤트를 구독 등록 하는 컨트롤러 메소드는 text/event-stream으로 해야한다.

간단하게 예시로 알아보자. 설명은 주석으로 달아놓았다.

 

// Controller Class Method

@RequestMapping(value = "/test/{token}", method = RequestMethod.GET, produces = "text/event-stream")
public SseEmitter subscribe(@PathVariable("token") String token) {
    return this.service.subscribe(token);
}


// Service Class Methods

private final SseEmitters sseEmitters;

public SseEmitter subscribe(String token) {
    String uuid = UUID.randomUUID().toString().toLowerCase();
    return sseEmitters.add(token, uuid);
}

// 이벤트 보내는 예시 메소드
public void doSomething() { 
    if (sseEmitters.hasKey(uuid)) {
        SseEmitter emitter = sseEmitters.get(uuid);
        emitter.send(SseEmitter.event().id(uuid).data(something));
        emitter.complete();
    }
}


// SseEmitters Class

public class SseEmitters {
	// sse 이벤트 연결 서버 타임아웃 시간.
    public static final long TIMEOUT = 60L * 1000;
    private final ConcurrentHashMap<String, SseEmitter> emitters = new ConcurrentHashMap<>();


    public SseEmitter add(String token, String uuid) throws IOException {
        SseEmitter emitter = new SseEmitter(TIMEOUT);
        emitters.put(uuid, emitter);

		// complete 메소드가 호출되었거나 타임아웃, 에러나면 emitter를 삭제한다.
        emitter.onCompletion(() -> this.emitters.remove(uuid));
        emitter.onTimeout(() -> this.emitters.remove(uuid));
        emitter.onError((callback) -> this.emitters.remove(uuid));
        
		// 첫 구독 시 이벤트를 한번 보내줘야한다.
        // 연결되었다는 응답으로 보내는 것인데 안보내면 503에러가 난다.
        emitter.send(SseEmitter.event().id(token).data(uuid));

        return emitter;
    }

    public boolean hasKey(String uuid) {
        return this.emitters.containsKey(uuid);
    }

    public SseEmitter get(String uuid) {
        return this.emitters.get(uuid);
    }
}

 

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.html

 

3. 결론

 

간단하게 spring boot에서 sse(Server-Sent-Event)를 사용하는 법을 알아보았다.

예시로 짠 것이라 심플하게 어떻게 쓰는지만 보고 실제 구현은 각자 플로우에 맞춰서 하면된다.

websocket과 sse이벤트를 잘 비교해서 용도에 맞게 써야하고 요즘 QR코드 로그인 같은 경우에는 SSE보다는 polling 방식으로 많이 하는 것 같다.

 

반응형