본문 바로가기

개발일지/TIL

[230821] 서버에서 클라이언트로 SSE 예외 전달하기

서버에서 클라이언트로 SSE 예외 전달하기

💬 Jmeter에서 데이터가 수신이 되는 것까지 확인되었습니다. 이후 테스트에서 실패 케이스를 잡아내야 하기 때문에 에러까지 수신이 되는지 확인해야 했습니다.

 

✔ 서버에서 예외를 던졌을 경우 문제

💢 서버에서 SSE 연결이 끊어져 Throw를 던질 경우 프로젝트에서 클라이언트로 데이터를 전송하는 For문에서 벗어나게 됩니다. 이것 때문에 받아야 할 다른 클라이언트는 데이터를 전송받지 못하는 문제가 발생했습니다. 이것을 Jmeter로 여러 번의 요청을 테스트하다가 발견했습니다.

for(CustomSseEmitter sendEmitter : sendEmitters) {
    try {
        sendEmitter.sseEmitter()
                .send(SseEmitter.event()
                        .name(event.toString())
                        .data(data));
    } catch (IOException | IllegalStateException e) {
        sendEmitter.sseEmitter().completeWithError(e);
        throw new RuntimeException(e);
    }
}


✅  SSE에 에러와 함께 완료하는 메서드가 있다는 것을 확인이 되었습니다. 그것을 사용하여 별도의 예외 처리 대신 클라이언트에 예외를 던져주기로 했습니다.

throw new RuntimeException(e); -> sendEmitter.sseEmitter().completeWithError(e);

 

✔ 첫 연결이 실패하거나 에러가 생겼을 때 문제

💢 데이터를 전송할 때의 예외는 클라이언트에서 받아지는 것을 확인했습니다. 그 이후 테스트를 더 하다 보니 전송 예외가 아닌 것은 또 받아지지 않는다는 것을 발견하게 되었습니다.

✅ SSE에 에러가 발생했을 때 수행할 로직을 부여할 수 있습니다. 수행 로직에 에러와 함께 완료하는 메서드를 사용해서 해결했습니다. 초기 메시지 보내는 곳에도 동일하게 적용했습니다.

emitter.onError(e -> {
    emitter.completeWithError(e);
    currentEmitters.remove(customSseEmitter);
});

try {
    emitter.send(initMessage);
} catch (IOException e) {
    customSseEmitter.sseEmitter().completeWithError(e);
    currentEmitters.remove(customSseEmitter);
}​