sse는 http스트리밍을 통해 서버에서 클라이언트로 단방향의 push Noti를 할 수 있는 HTML표준 기술이다.
전통적인 애플리케이션은 요청 단건에 대해 서버가 응답하는 방식이지만, SSE를 이용해 서버에서 클라이언트로 Real-Time Push Notification을 전송할 수 있다.
package com.temperature.stream.domain;
// @Getter 써도 private속성은 가져올 수 없음..
public class Temperature {
private final double value;
public Temperature(double value) {
this.value = value;
}
public double getValue() {
return value;
}
}
@RestController
public class TemperatureController {
private final Set<SseEmitter> clients = new CopyOnWriteArraySet<>();
@GetMapping(value = "/temperature-stream") // 요청 핸들러
public SseEmitter events(HttpServletRequest request){
SseEmitter emitter = new SseEmitter();
clients.add(emitter);
emitter.onTimeout(()->clients.remove(emitter));
emitter.onCompletion(()->clients.remove(emitter));
return emitter; // 클라이언트 요청 시 새로운 SseEmitter를 생성하여 클라이언트 목록에 등록과 동시에 이를 반환
}
@Async // 메서드를 비동기 실행한다. 별도로 구성된 스레드 풀에서 호출됨
@EventListener // 스프링으로부터 이벤트를 수신하기 위한 어노테이션. 온도 이벤트를 수신할 때 handleMsg 호출
public void handleMessage(Temperature temperature){
List<SseEmitter> deadEmitters = new ArrayList<>();
for (SseEmitter emitter : clients){
try{
emitter.send(temperature, MediaType.APPLICATION_JSON); // 각 이벤트들에게 병렬로 메시지 전송
}catch (Exception ignore){
deadEmitters.add(emitter);
}
}
clients.removeAll(deadEmitters); // 활성 클라이언트에서 전송 실패한 연결 제거
}
}