X-Accel-Buffering

오래전에 개인적으로 엔진엑스로 알아보는 리버스 프록시를 학습하면서 이벤트 스트림에 대한 프록시 구성 시 proxy_buffering 과 같은 버퍼링 옵션을 비활성화 해야한다고 정리하였습니다. HTTP/2 연결과 함께 SSE(Server Sent Event)를 활용하면 굳이 웹소켓 구현을 하지 않아도 서버 측에서 클라이언트로 원하는 데이터를 지속적으로 전달할 수 있습니다.

하지만, Nginx 측에서는 Nginx 구성에 대한 10가지 실수에서 Mistake 5: The proxy_buffering off Directive으로 버퍼링 옵션에 대한 비활성화에 대해서 이야기합니다.

Buffering can also be enabled or disabled by passing “yes” or “no” in the “X-Accel-Buffering” response header field. This capability can be disabled using the proxy_ignore_headers directive.

위와 같이 엔진엑스 공식 문서 상에는 프록시 버퍼링을 무시할 수 있는 헤더에 대한 설명을 해주고 있으며 회사 내 인프라 엔지니어 분의 의견에 따라서 프록시 구성 시 버퍼링 옵션을 일괄적으로 변경하기보다는 애플리케이션 서버에서 이벤트 스트림에 대한 응답을 수행할 때 X-Accel-Buffering 헤더를 응답하는 것으로 최종 결정했습니다.

X-Accel-Buffering 헤더 응답하기

스프링 프레임워크에서는 SseEmitter를 제공하므로 간단하게 SSE 연결을 구현할 수 있으며 이 클래스는 ResponseBodyEmitter를 확장하였기에 extendResponse 함수를 통해 응답하기 전 HTTP 상태코드 또는 응답 헤더를 변경할 수 있게 지원합니다. 따라서, 컨트롤러 핸들러 함수에서 HttpServletResponse를 인자로 받은 후 X-Accel-Buffering 헤더에 대한 값을 no로 설정하면 됩니다.

@Slf4j
@RestController
public class SseController {

    @GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter sse(HttpServletResponse response) {
        response.setHeader("X-Accel-Buffering", "no");
        return new SseEmitter();
    }
}

감사합니다.