Spring SSE 성능 문제 — Thread.sleep과 emitter 덮어쓰기
실시간 진행률 SSE에서 이벤트 누락/지연을 일으키는 두 흔한 실수와 해결.
Spring SSE 성능 문제 — Thread.sleep과 emitter 덮어쓰기
Spring Boot의 SseEmitter 기반 실시간 진행률 전송에서 이벤트 누락/지연을 일으키는 두 가지 흔한 실수.
1. sendData마다 Thread.sleep
1
2
3
4
5
6
// BAD - 매 전송마다 200ms 블로킹, 100회 호출이면 20초 추가 지연
emitter.send(event);
Thread.sleep(200);
// GOOD - sleep 제거, InterruptedException catch도 불필요
emitter.send(event);
Worker 스레드에서 SSE를 보내는 구조라면 sleep이 전체 작업(비식별화, 엑셀 생성 등)을 직접 지연시킨다.
2. 재구독 시 기존 emitter 덮어쓰기
1
2
3
4
5
// BAD - 같은 키로 subscribe하면 기존 emitter 제거 → 진행 중인 이벤트 영구 누락
Map<String, SseEmitter> emitterMap;
// GOOD - Set으로 변경하여 같은 키에 여러 emitter 브로드캐스트
Map<String, Set<SseEmitter>> emitterMap;
마이페이지 팝업을 열거나 페이지 새로고침 시 subscribe() 재호출 → 기존 다운로드의 emitter가 제거되어 프론트가 이벤트를 영원히 못 받는 문제. Set<SseEmitter>로 바꾸고 개별 emitter의 onCompletion/onError에서 해당 emitter만 제거하면 해결.
디버깅 팁
SSE 느림의 원인을 찾을 때는 다운로드 흐름의 각 단계에 System.currentTimeMillis() 기반 로그를 넣고 [download] 같은 공통 태그로 grep하면 병목을 빠르게 찾을 수 있다. log.info 레벨 사용 — logback의 root level이 INFO인 환경에서 log.debug는 안 찍힌다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.