Files
llm-wiki/raw/official-docs/spring-streaming-response-body.md
T

116 lines
13 KiB
Markdown

---
title: Spring Framework — StreamingResponseBody / ResponseBodyEmitter / SseEmitter (official-vendor-doc)
source_type: official-doc
url: https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-ann-async.html
archive_url:
status: raw
confidence: high
tags: [spring-framework, spring-mvc, async, streaming, sse, file-download, file-resource-handling-contract]
related_projects: []
related_branches: [feature-file-resource-handling-contract, feature-streaming-response-contract]
created: 2026-05-27
last_reviewed: 2026-06-02
---
# Spring Framework — StreamingResponseBody / ResponseBodyEmitter / SseEmitter (공식)
> Layer: `raw/official-docs/` — Spring Framework reference 의 **원문 발췌·출처 기록**.
> Strength 분류: `official-vendor-doc` — Spring 의 공식 reference manual (`docs.spring.io/spring-framework/reference/...`).
> 검증된 요약은 `/ingest` 후 `wiki/concepts/` 에 별도 작성.
## Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-file-resource-handling-contract]] | **D8 (streaming download mechanism)** 의 근거 — Spring 이 공식 제공하는 streaming response 3가지(`StreamingResponseBody`, `ResponseBodyEmitter`, `SseEmitter`) 의 명세 + threading 모델. 대용량 파일 다운로드 시 message conversion bypass + OutputStream 직접 쓰기 패턴의 외부 근거. |
| [[raw/branch-notes/feature-streaming-response-contract]] | **streaming mechanism 선택** 의 Spring 구현 표면 근거 — `SseEmitter` (SSE), `ResponseBodyEmitter` (객체 stream), `StreamingResponseBody` (binary stream) 의 역할 분리 + threading 모델 + timeout 정책. 별도 전용 context 파일: [[raw/official-docs/spring-mvc-async-streaming]] |
## 컨텍스트
`feature-file-resource-handling-contract` 의 D8 은 "대용량 파일 응답은 메모리 전체 적재 없이 streaming 으로 처리한다" 는 contract 를 다룬다. Spring MVC 의 async 챕터는 3가지 streaming abstraction 을 직접 정의하며, 그 중 `StreamingResponseBody` 는 "bypass message conversion and stream directly to the response OutputStream (for example, for a file download)" 를 명시한다. 본 raw 는 D8 의 외부 근거로 보관.
`feature-streaming-response-contract` 를 위한 더 상세한 streaming mechanism 비교 컨텍스트는 [[raw/official-docs/spring-mvc-async-streaming]] 에 별도 아카이빙됨.
## 출처 / Source
- 원본 URL: https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-ann-async.html
- 검색 anchor: `mvc-ann-async-http-streaming` (HTTP Streaming section)
- 아카이브 URL: (미수집 — 추후 archive.org 스냅샷 추가)
- 저자 / 조직: Spring (Broadcom) — Spring Framework reference (current branch)
- 발행일: rolling docs (Spring Framework 6.x current)
- 마지막 확인일: 2026-05-27
## 핵심 인용 / 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."
> [§Processing] "The call to `request.startAsync()` returns `AsyncContext`, which you can use for further control over asynchronous processing."
> [§DeferredResult Processing] "The controller returns a `DeferredResult` and saves it in some in-memory queue or list where it can be accessed."
> [§Callable Processing] "Spring MVC calls `request.startAsync()` and submits the `Callable` to an `AsyncTaskExecutor` for processing in a separate thread."
> [§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 — StreamingResponseBody] "You can use the `StreamingResponseBody` return value type to do so, as the following example shows"
> [§HTTP Streaming — StreamingResponseBody] "You can use `StreamingResponseBody` as the body in a `ResponseEntity` to customize the status and headers of the response."
> [§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 — ResponseBodyEmitter] "You can also use `ResponseBodyEmitter` as the body in a `ResponseEntity`, letting you customize the status and headers of the response."
> [§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-STREAM-RB-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 컨테이너 환경 | WebFlux (reactive stack) 에서도 동일 메커니즘이라는 뜻은 아님 — 본 챕터는 spring-webmvc 한정 |
| SPRING-STREAM-RB-C2 | `Callable` 반환 시 Spring MVC 는 `request.startAsync()` 호출 + `Callable``AsyncTaskExecutor` 에 submit 하여 별도 thread 에서 처리 | [§Callable Processing] "Spring MVC calls `request.startAsync()` and submits the `Callable` to an `AsyncTaskExecutor` for processing in a separate thread." | `official-vendor-doc` | `@Controller` 메서드가 `Callable<T>` 반환 시나리오 | `AsyncTaskExecutor` 의 default 구현이 production-ready 라는 뜻은 아님 — 별도 설정 권고 (본 챕터 elsewhere 에 명시) |
| SPRING-STREAM-RB-C3 | **`StreamingResponseBody` 의 핵심 용도**: message conversion 을 우회하고 response `OutputStream` 에 직접 write — **file download 가 명시된 use case** | [§HTTP Streaming — StreamingResponseBody] "Sometimes, it is useful to 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 (`Flux`) 경로 한정 (`C7`) |
| SPRING-STREAM-RB-C4 | `StreamingResponseBody``ResponseEntity` 의 body 로 사용 가능 (status/header 커스터마이즈) | [§HTTP Streaming] "You can use `StreamingResponseBody` as the body in a `ResponseEntity` to customize the status and headers of the response." | `official-vendor-doc` | streaming 응답에 custom HTTP status / Content-Disposition 등 헤더 부여 | 헤더 부여 시점이 first byte write 이전에 보장된다는 명시는 본 인용에 없음 (구현 의존) |
| SPRING-STREAM-RB-C5 | `ResponseBodyEmitter`**객체 stream** 을 생성, 각 객체는 `HttpMessageConverter` 로 직렬화되어 response 에 write | [§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" | `official-vendor-doc` | application/json-stream 등 객체 다발 응답 | binary stream (파일 다운로드) 에는 부적합 — message conversion 을 거치므로. 파일은 `StreamingResponseBody` 사용 (`C3`) |
| SPRING-STREAM-RB-C6 | `SseEmitter``ResponseBodyEmitter` 의 subclass 이며, W3C **Server-Sent Events** 사양에 따라 event 포맷팅 | [§HTTP Streaming — SseEmitter] "`SseEmitter` (a subclass of `ResponseBodyEmitter`) provides support for Server-Sent Events…" | `official-vendor-doc` | SSE 기반 server push 시나리오 | WebSocket / gRPC streaming 의 대체라는 뜻은 아님 — 단방향 server→client only |
| SPRING-STREAM-RB-C7 | reactive type (`Flux` 등) 응답 stream 처리 시 reactive backpressure 는 지원되나, response 에 대한 **실제 write 는 blocking** 이며 별도 `AsyncTaskExecutor` thread 에서 수행 (upstream 차단 회피 목적) | [§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 such as a `Flux` returned from `WebClient`." | `official-vendor-doc` | Spring MVC 에서 `Flux<T>` 반환 시 동작 (WebFlux 가 아닌 spring-webmvc 한정) | "fully non-blocking" 이라는 뜻이 아님 — write 자체는 blocking. fully non-blocking 은 WebFlux 사용 필요 |
| SPRING-STREAM-RB-C8 | 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/Undertow 의 구체적 default 값은 본 인용 범위 밖 — 각 컨테이너 문서 참조 |
| SPRING-STREAM-RB-C9 | timeout 은 `DeferredResult`, `ResponseBodyEmitter`, `SseEmitter` 각 인스턴스에 개별 설정 가능. `Callable` 의 경우 `WebAsyncTask` 사용 | [§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." | `official-vendor-doc` | per-request timeout 정책 | timeout 초과 시 동작 (callback / exception) 의 정확한 명세는 본 인용 범위 밖 — 각 type 별 javadoc 참조 |
## Usage Boundaries / 적용 경계
- **이 자료가 직접 증명하는 것**:
- `SPRING-STREAM-RB-C3`, `C4`: 파일 다운로드는 `StreamingResponseBody` 가 공식 권장 패턴 (message conversion bypass + OutputStream 직접 write)
- `SPRING-STREAM-RB-C5`, `C6`: 객체 stream → `ResponseBodyEmitter`, SSE → `SseEmitter` 의 역할 분리
- `SPRING-STREAM-RB-C7`: spring-webmvc 에서 `Flux` 반환 시 write 가 **blocking** 임 (fully reactive 가 아님)
- `SPRING-STREAM-RB-C8`, `C9`: timeout 메커니즘
- **이 자료가 증명하지 않는 것**:
- **`StreamingResponseBody` 가 OOM (OutOfMemory) 을 항상 방지한다는 점** — application 코드에서 buffer 를 무한 누적하면 OOM 발생 가능. 본 raw 는 "OutputStream 에 직접 write 할 수 있다" 만 진술
- **chunked transfer encoding 자동 사용** — 본 인용 범위에 명시 없음 (Servlet 컨테이너 동작 의존)
- **`StreamingResponseBody``ResponseEntity<InputStreamResource>` 보다 항상 우수** 라는 비교 결론
- **WebFlux 의 동등 abstraction** — 본 챕터는 spring-webmvc 한정. WebFlux 는 별도 챕터
- **내 프로젝트에 적용하려면 추가 확인이 필요한 것**:
- `feature-file-resource-handling-contract` 의 파일 다운로드 endpoint 가 `StreamingResponseBody` 채택 시, write loop 의 buffer size 정책 — 본 raw 는 size 권장값 진술 안 함
- `AsyncTaskExecutor` 의 thread pool 설정 — `C2`, `C7` 모두 별도 thread 사용 명시이나, default executor 의 pool size 는 별도 설정 필요 (production 에서 default `SimpleAsyncTaskExecutor` 는 thread 무제한 생성 위험 — 별도 출처 확인)
## 메모 / Notes
- **URL 확인 이력**: `mvc-controller/ann-async.html` (지정 URL) 은 2026-05-27 시점 404 → `mvc-ann-async.html` 로 path 가 변경된 것으로 보임. 동일 reference manual 의 동일 챕터로 판단되어 후자 URL 로 인용. wiki 추출 시 URL 검증 재수행.
- `C7`**흔한 오해 방지 핵심 인용** — "Spring MVC + Flux = fully reactive" 가 아님을 명시.
- `C3` 의 "for example, for a file download" 는 D8 의 가장 직접적 근거.
- 2026-06-02: `feature-streaming-response-contract` 의 streaming mechanism 선택 컨텍스트로 `related_branches` 에 추가 + Parent 표 갱신. streaming-response-contract 전용 더 상세한 버전은 [[raw/official-docs/spring-mvc-async-streaming]].
## Related / 관련
- 같은 주제 다른 raw 자료: [[raw/official-docs/spring-mvc-async-streaming]] (streaming-response-contract 전용 컨텍스트 버전)
- 같은 주제 다른 raw 자료: [[raw/official-docs/whatwg-html-server-sent-events]] (SSE 프로토콜 표준 — C6 와 연결)
- 이 자료를 인용한 wiki 요약: (미작성)
- 이 자료를 인용하는 branch: [[raw/branch-notes/feature-file-resource-handling-contract]]
- 이 자료를 인용하는 branch: [[raw/branch-notes/feature-streaming-response-contract]]
- 인용하는 project: [[raw/project-notes/ca-skeleton-operational-contract]]