Files
llm-wiki/raw/official-docs/spring-mvc-async-streaming.md

94 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "official-doc / Spring MVC — Async HTTP Streaming (SseEmitter / ResponseBodyEmitter / StreamingResponseBody) — streaming-response-contract context"
source_type: official-doc
url: https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-ann-async.html
archive_url:
related_branches: [feature-streaming-response-contract, feature-file-resource-handling-contract]
related_projects: [ca-skeleton]
tags: [spring-framework, spring-mvc, async, streaming, sse, ssemitter, responsebodyemitter, streamingrequestbody, http-streaming, threading, official-vendor-doc]
created: 2026-06-02
last_reviewed: 2026-06-02
---
# Spring MVC — Async HTTP Streaming (SseEmitter / ResponseBodyEmitter / StreamingResponseBody)
> Layer: `raw/official-docs/` — Spring Framework reference manual (6.x current) "Web on Servlet Stack > Spring MVC > Annotated Controllers > Async Requests" 챕터 발췌.
> Strength 분류: `official-vendor-doc` — Spring (Broadcom) 공식 reference manual.
> 이 파일은 `feature-streaming-response-contract` 컨텍스트 — ca-skeleton 의 streaming mechanism 선택을 위한 Spring 구현 표면 근거. `feature-file-resource-handling-contract` 컨텍스트는 [[raw/official-docs/spring-streaming-response-body]] 가 별도 커버.
## Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-streaming-response-contract]] | Spring 이 공식 제공하는 streaming response abstraction 3종 (`SseEmitter`, `ResponseBodyEmitter`, `StreamingResponseBody`) 의 역할 분리 + threading model + timeout 정책 — ca-skeleton 에서 streaming 을 도입한다면 어떤 Spring API 표면을 사용하는지 결정의 근거 |
| [[raw/branch-notes/feature-file-resource-handling-contract]] | D8 streaming download mechanism — 대용량 파일 다운로드 시 `StreamingResponseBody` 사용 결정 (이미 `raw/official-docs/spring-streaming-response-body` 에서 커버, 본 파일은 추가 context) |
## 출처 / Source
- 원본 URL: https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-ann-async.html
- Javadoc (SseEmitter): https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.html
- Javadoc (ResponseBodyEmitter): https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitter.html
- 아카이브 URL: (미수집)
- 저자 / 조직: Spring (Broadcom) — Spring Framework reference (6.x current branch)
- 발행일: rolling docs (Spring Framework 6.x)
- 마지막 확인일: 2026-06-02
## 왜 저장했는지 / Why archived
ca-skeleton 이 streaming 을 지원하기로 결정했을 때 어떤 Spring API 를 사용해야 하는지의 공식 근거. Spring MVC 의 async streaming abstraction 3종 (`SseEmitter`, `ResponseBodyEmitter`, `StreamingResponseBody`) 의 역할 분리, threading 모델 (별도 `AsyncTaskExecutor` thread), timeout 설정 방식, reactive type (`Flux`) 사용 시 주의사항을 claim 수준으로 정리. 특히 `SseEmitter` 가 WHATWG SSE spec (`C6` in `whatwg-html-server-sent-events`) 포맷을 따른다는 vendor confirmation 이 핵심.
## 핵심 인용 / Key quotes (verbatim)
> [§Processing] "A ServletRequest can be put in asynchronous mode by calling request.startAsync(). The main effect of doing so is that the Servlet (as well as any filters) can exit, but the response remains open to let processing complete later."
> [§HTTP Streaming — StreamingResponseBody] "Sometimes, it is useful to bypass message conversion and stream directly to the response OutputStream (for example, for a file download)."
> [§HTTP Streaming — ResponseBodyEmitter] "You can use the ResponseBodyEmitter return value to produce a stream of objects, where each object is serialized with an HttpMessageConverter and written to the response, as the following example shows"
> [§HTTP Streaming — SseEmitter] "SseEmitter (a subclass of ResponseBodyEmitter) provides support for Server-Sent Events, where events sent from the server are formatted according to the W3C SSE specification."
> [§HTTP Streaming — Reactive types] "For streaming to the response, reactive back pressure is supported, but writes to the response are still blocking and are run on a separate thread through the configured AsyncTaskExecutor, to avoid blocking the upstream source such as a Flux returned from WebClient."
> [§Configuration] "The default timeout value for async requests depends on the underlying Servlet container, unless it is set explicitly."
> [§Configuration] "Note that you can also set the default timeout value on a DeferredResult, a ResponseBodyEmitter, and an SseEmitter. For a Callable, you can use WebAsyncTask to provide a timeout value."
## Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| SPRING-ASYNC-C1 | Spring MVC async 처리의 기반: `request.startAsync()` 호출 → Servlet/filter 는 exit, response 는 열린 상태로 유지 | [§Processing] "the Servlet (as well as any filters) can exit, but the response remains open to let processing complete later." | `official-vendor-doc` | Spring MVC + Servlet 컨테이너 (spring-webmvc 한정) | WebFlux (reactive stack) 에서도 동일 메커니즘이라는 뜻 아님 |
| SPRING-ASYNC-C2 | `StreamingResponseBody` 는 message conversion 을 우회하고 response `OutputStream` 에 직접 write — file download 가 명시된 use case | [§HTTP Streaming — StreamingResponseBody] "bypass message conversion and stream directly to the response OutputStream (for example, for a file download)." | `official-vendor-doc` | 대용량 파일 다운로드 / binary stream 응답 | `StreamingResponseBody` 가 backpressure 를 지원한다는 뜻 아님 — backpressure 는 reactive type 경로 한정 (`C5`) |
| SPRING-ASYNC-C3 | `ResponseBodyEmitter` 는 객체 stream 을 생성, 각 객체는 `HttpMessageConverter` 로 직렬화되어 response 에 write | [§HTTP Streaming — ResponseBodyEmitter] "produce a stream of objects, where each object is serialized with an HttpMessageConverter and written to the response" | `official-vendor-doc` | application/json-stream 등 객체 다발 응답 | Binary stream 에는 부적합 (message conversion 거침). 파일은 `StreamingResponseBody` |
| SPRING-ASYNC-C4 | `SseEmitter``ResponseBodyEmitter` 의 subclass 이며, **W3C SSE specification** 에 따라 event 포맷팅 | [§HTTP Streaming — SseEmitter] "SseEmitter (a subclass of ResponseBodyEmitter) provides support for Server-Sent Events, where events sent from the server are formatted according to the W3C SSE specification." | `official-vendor-doc` | SSE 기반 server push 시나리오 | Spring `SseEmitter``Last-Event-ID` replay 를 자동으로 지원한다는 뜻 아님 — 서버 측 event store 별도 구현 필요 |
| SPRING-ASYNC-C5 | Spring MVC 에서 `Flux<T>` 반환 시 reactive backpressure 는 지원되나, response write 는 **blocking** 이며 별도 `AsyncTaskExecutor` thread 에서 수행 | [§HTTP Streaming — Reactive types] "writes to the response are still blocking and are run on a separate thread through the configured AsyncTaskExecutor, to avoid blocking the upstream source" | `official-vendor-doc` | Spring MVC (spring-webmvc) 에서 `Flux<T>` 반환 시 | "fully non-blocking" 이라는 뜻 아님 — fully non-blocking 은 WebFlux 필요 |
| SPRING-ASYNC-C6 | async request 의 default timeout 은 underlying Servlet 컨테이너 에 의존 (명시 설정 없으면) | [§Configuration] "The default timeout value for async requests depends on the underlying Servlet container, unless it is set explicitly." | `official-vendor-doc` | Spring MVC 의 모든 async 반환 타입 | Tomcat/Jetty 의 구체적 default 값은 본 인용 범위 밖 |
| SPRING-ASYNC-C7 | `DeferredResult`, `ResponseBodyEmitter`, `SseEmitter` 각 인스턴스에 개별 timeout 값 설정 가능 | [§Configuration] "you can also set the default timeout value on a DeferredResult, a ResponseBodyEmitter, and an SseEmitter." | `official-vendor-doc` | per-request timeout 정책 (heartbeat 정책과 연계) | timeout 초과 시 동작(callback / exception)의 상세 명세는 각 type javadoc 참조 |
## Usage Boundaries / 적용 경계
- **이 자료가 직접 증명하는 것**:
- `C4`: Spring `SseEmitter` 는 W3C SSE spec 을 따름 — WHATWG `text/event-stream` 포맷 공식 구현
- `C2`: `StreamingResponseBody` 는 message conversion bypass + OutputStream 직접 write
- `C5`: spring-webmvc 에서 `Flux` 반환은 **blocking write** — fully reactive 하지 않음
- `C6`, `C7`: timeout 은 명시 설정 필요 — 컨테이너 default 에만 의존 금지
- **이 자료가 증명하지 않는 것**:
- Spring `SseEmitter` 가 heartbeat ping 을 자동으로 보낸다는 주장 — heartbeat 는 애플리케이션 코드로 구현 필요
- `AsyncTaskExecutor` 의 default 구현(`SimpleAsyncTaskExecutor`)이 production-ready 라는 주장 — 별도 thread pool 설정 권고
- chunked transfer encoding 이 자동 적용된다는 주장 — Servlet 컨테이너 동작 의존
- **내 프로젝트에 적용하려면 추가 확인이 필요한 것**:
- ca-skeleton 에서 `SseEmitter` 채택 시 `AsyncTaskExecutor` thread pool 을 별도 구성해야 하는지 (`SimpleAsyncTaskExecutor` 는 thread 무제한 생성 위험)
- `SseEmitter` timeout 을 `heartbeat interval × N` 으로 설정하는 패턴 — Spring 이 권고하는 값 없음, 운영 경험 기반 설정 필요
## 메모 / Notes
- `C4` 의 "W3C SSE specification" 참조는 WHATWG Living Standard (`whatwg-html-server-sent-events.md`) 와 연결됨
- `C5` 는 "Spring MVC + reactive Flux = fully non-blocking" 오해 방지 핵심 인용
- 기존 `raw/official-docs/spring-streaming-response-body.md` 와 동일 reference (Spring MVC async doc) 에서 발췌했으나, 이 파일은 streaming-response-contract 의 mechanism 비교 컨텍스트 전용이고 저 파일은 file-resource-handling-contract 의 D8 컨텍스트 전용.
## Related / 관련
- 같은 출처 다른 컨텍스트: [[raw/official-docs/spring-streaming-response-body]] (D8 file download 컨텍스트)
- 같은 주제 다른 raw 자료: [[raw/official-docs/whatwg-html-server-sent-events]] (SSE 프로토콜 표준 — C4 와 연결)
- 인용하는 branch: [[raw/branch-notes/feature-streaming-response-contract]]