SSE는 text/event-stream 형식으로 HTTP 통신을 한다.
이때, content의 길이는 정해지면 안되고, transfer-encoding은 chunked가 되어야한다.
하지만 나의 경우, Request/Response에 대한 자세한 로깅을 위해 ContentCachingRequestWrapper 필터를 사용하고 있었는데, 여기서 Content Length를 구하는순간, Wrapping된 Request / Response의 Content-Length에 ~~한 값이 찍히게 된다 (이부분은 코드를 까봐야 알듯)
따라서 필터를 탈때 분기를 해야한다.
나는 필터내에서 처리해주었다.
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (request.getHeader("accept") != null && request.getHeader("accept").contains("text/event-stream")) {
filterChain.doFilter(request, response);
return;
}
ContentCachingRequestWrapper wrappingRequest = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper wrappingResponse = new ContentCachingResponseWrapper(response);
filterChain.doFilter(wrappingRequest, wrappingResponse);
wrappingResponse.copyBodyToResponse();
}
ALB 혹은 NGINX에서 타임아웃이 난것이다.
SSE는 웹소켓이 아닌 HTTP 프로토콜을 사용하므로,
ALB나 NGINX에서 HTTP프로토콜에 대해서 타임아웃 설정이 되어있다면
아무리 keep-alive나 어떠한 헤더를 추가한다 하더라도 타임아웃이 발생한다.
이 경우는 타임 아웃 제한시간을 늘려주면 되는데, 그렇게 해버리면 다른 SSE가 아닌 REST API에 대해서도 똑같이 적용되어 Content-Type에 따라 분리 해야한다.
근데 어차피 이 SSE통신을 받는 주체가 여러명의 사용자가 아닌, 1명의 사용자이므로 (백오피스 대시보드 알림용이라...) 1분마다 연결재요청을해도 대충 계산때려보니 한달에 2만원 +-정도의 요금이 발생하므로 그냥 그대로 두었고,
재연결시 유실된 이벤트를 받아오는 식으로 로직을 구현하려고 한다.