<aside> 🔑
요약
React + Spring Boot 환경에서 SSE 기반 알림 기능을 구현했었다. 로컬에서는 정상 작동했지만, Docker + Nginx로 배포 후 Cloudflare 프록시 환경에서 ERR_QUIC_PROTOCOL_ERROR
가 발생했었 다. 이는 Cloudflare가 장시간 지속되는 연결을 차단하는 정책 때문이었다.
따라서 SSE URI(/api/v1/notification/subscribe) 에 대해 Cloudflare 캐시를 우회하도록 규칙을 설정했었다. 또한 Spring Boot에서 X-Accel-Buffering: no
헤더를 추가하여 NGINX 버퍼링을 비활성화했었다.
이 설정들은 SSE 지속 연결을 위한 기본 조치였으나, 완전한 해결에는 이르지 못했었다. 현재는 추가적인 원인 분석과 트러블슈팅이 필요한 상황이다.
</aside>
<aside> 💡
프로덕션 환경 Cloudflare(React) + EC2(Docker(Nignx + SpringBoot))
</aside>
React
+ Spring Boot
환경에서 SSE 를 연결하여 실시간 알림 기능을 구현하였다. 리액트에서는 event-source-polyfill
를 적용하여 인증헤더에 유저 식별을 위한 액세스 토큰을 담아서 보내고, 서버에서는 이를 기반으로 사용자 인증을 거친 후 SSE 연결을 거친다.Docker(Nginx + Spring Boot)
배포 이후에 초기 SSE 연결과 사용자 인증은 성공하지만, ERR_QUIC_PROTOCOL_ERROR 200
이 반환되고 있다.🧐 초기 연결 성공
🤔 이후 재연결 시도가 이루어지고 네트워크 에러 발생
해당 문제에 대해서 찾아보니 Cloudflare 의 경우 기본적으로 모든 경로에 대해 프록시 처리하며, 프록시되는 모든 경로에 대해서 웹 소켓 연결을 제외한 오랜 기간 연결되는 통신의 경우 일정 시간 후 차단하는 문제가 있을 수 있다고 한다. 이는 성능 최적화를 위한 정상적인 동작이지만, SSE 에 한해서는 그렇지 못하다.
따라서 SSE를 연결하는 경로에 대해서는 오랜 시간이 지나도 차단되지 않도록 해야 하는데, 이 방법 중 하나가 Cloudflare의 기본 규칙(Rule)을 변경해주는 것이다.
현재 SSE 요청의 경우 /api/v1/notification/subscribe
를 통해 구독을 수행하므로 이 경로는 캐싱에서 배제하는 규칙을 추가한다.