9.8 KiB
title, source_type, url, archive_url, related_branches, related_projects, tags, created
| title | source_type | url | archive_url | related_branches | related_projects | tags | created | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| MDN — HTTP Range requests / Fetch 취소·스트림 소비 | official-doc | https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Range_requests |
|
|
|
2026-07-28 |
MDN — HTTP Range requests / Fetch 취소·스트림 소비
Layer:
raw/— 외부 자료의 원문 발췌·출처 기록.
활용 branch (필수, 최소 1개+)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
[[raw/branch-notes/feature-frontend-large-object-transfer-contract]] |
StreamingDownloadPort 의 재개 프로토콜(D4), part 재시도가 stream 재사용이 아니라 재slice 여야 하는 이유(D6), 취소의 error 매핑(D7) |
출처
- 원본 URL: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Range_requests
- 보조 URL: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
- 아카이브 URL:
- 저자 / 조직: MDN Web Docs (Mozilla)
- 발행일: (문서 지속 갱신)
- 마지막 확인일: 2026-07-28
왜 저장했는지
branch 의 resumeStrategy: range 와 "part 재시도 상한 2회" 가 어떤 프로토콜 사실 위에 서 있는지 확인하지 않은 상태였다. 특히 세 가지가 필요했다. (a) 재개가 서버 지원에 의존한다면 미지원을 어떻게 감지하는가, (b) 재개 중 원본이 바뀌면 무엇이 깨지는가, (c) 실패한 part 를 재시도할 때 이미 소비한 body 를 다시 쓸 수 있는가. (c) 는 재시도 구현이 조용히 빈 body 를 보내는 고전적 버그의 원인이다.
핵심 인용
[§Checking if a server supports partial requests] "If an HTTP response includes the
Accept-Rangesheader with any value other thannone, the server supports range requests."
[§Checking if a server supports partial requests] "If responses omit the
Accept-Rangesheader, it indicates the server doesn't support partial requests."
[§Requesting a specific range from a server] "If the server supports range requests, you can specify which part (or parts) of the document you want the server to return by including the
Rangeheader in a HTTP request."
[§Single part ranges] "The
Content-Rangeresponse header indicates where this partial message belongs within the full resource."
[§Partial request responses] "A range request that is out of bounds will result in a
416Requested Range Not Satisfiablestatus, meaning that none of the range values overlap the extent of the resource."
[§Partial request responses] "If range requests are not supported, an
200OKstatus is sent back and the entire response body is transmitted."
[§Conditional range requests] "When resuming to request more parts of a resource, you need to guarantee that the stored resource has not been modified since the last fragment has been received."
[§Conditional range requests] "The
If-RangeHTTP request header makes a range request conditional: if the condition is fulfilled, the range request will be issued and the server sends back a206Partial Contentanswer with the appropriate body. If the condition is not fulfilled, the full resource is sent back, with a200OKstatus."
[§Using Fetch — Canceling a request] "To make a request cancelable, create an
AbortController, and assign itsAbortSignalto the request'ssignalproperty."
[§Using Fetch — Canceling a request] "To cancel the request, call the controller's
abort()method. Thefetch()call will reject the promise with anAbortErrorexception."
[§Using Fetch — Canceling a request] "If the request is aborted after the
fetch()call has been fulfilled but before the response body has been read, then attempting to read the response body will reject with anAbortErrorexception."
[§Using Fetch — Streaming the response body] "Request and response bodies are actually
ReadableStreamobjects, and whenever you read them, you're streaming the content."
[§Using Fetch — Locked and disturbed streams] "This means it's not possible to read the same response (or request) body more than once"
[§Using Fetch — Locked and disturbed streams] "if any content has been read from the stream, then the stream is disturbed, and nothing else can read from the stream."
추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| C1 | 서버의 range 지원 여부는 Accept-Ranges 헤더로 판별하며 none 또는 헤더 부재는 미지원을 뜻한다 |
[§Checking] "with any value other than none, the server supports range requests" / "If responses omit the Accept-Ranges header, it indicates the server doesn't support partial requests." |
official-reference |
모든 HTTP 응답 | 특정 스토리지 vendor 가 이 헤더를 보내는지 |
| C2 | 부분 응답의 위치는 Content-Range 가 알려주며 상태 코드는 206 이다 |
[§Single part ranges] "The Content-Range response header indicates where this partial message belongs within the full resource." |
official-reference |
206 응답 |
클라이언트가 요청한 범위와 서버가 준 범위가 항상 같다는 것 |
| C3 | 범위가 리소스 밖이면 416 Requested Range Not Satisfiable 이 온다 |
[§Partial request responses] "will result in a 416 Requested Range Not Satisfiable status" |
official-reference |
잘못된 재개 위치 | 416 이 재시도로 회복 가능한지 |
| C4 | range 를 지원하지 않으면 200 OK 와 전체 본문이 온다 — 조용히 성공한 것처럼 보인다 |
[§Partial request responses] "an 200 OK status is sent back and the entire response body is transmitted." |
official-reference |
재개 시도 | 200 응답을 받은 클라이언트가 자동으로 이를 알아챈다는 것 — 상태 코드를 검사해야만 안다 |
| C5 | 재개 시에는 마지막 조각 수신 이후 원본이 변경되지 않았음을 보장해야 한다 | [§Conditional range requests] "you need to guarantee that the stored resource has not been modified since the last fragment has been received." | official-reference |
모든 이어받기 | 어떤 validator(ETag vs Last-Modified)를 써야 하는지 |
| C6 | If-Range 는 조건 충족 시 206, 불충족 시 200 과 전체 리소스를 돌려준다 |
[§Conditional range requests] "If the condition is not fulfilled, the full resource is sent back, with a 200 OK status." |
official-reference |
조건부 재개 | 불충족을 오류로 취급해야 하는지 — 프로토콜상 정상 응답이다 |
| C7 | AbortController 의 signal 로 요청을 취소하며 fetch() 는 AbortError 로 reject 된다 |
[§Canceling a request] "The fetch() call will reject the promise with an AbortError exception." |
official-reference |
모든 fetch 요청 | 이미 전송된 바이트가 서버에서 취소된다는 것 |
| C8 | 응답 수신 후 body 읽기 전에 취소하면 body 읽기가 AbortError 로 reject 된다 |
[§Canceling a request] "attempting to read the response body will reject with an AbortError exception." |
official-reference |
취소 타이밍이 늦은 경우 | 두 경로의 error 를 구분해야 하는지 |
| C9 | request·response body 는 ReadableStream 이며 읽는 순간 스트리밍된다 |
[§Streaming the response body] "Request and response bodies are actually ReadableStream objects" |
official-reference |
fetch body | 요청 body 로 스트림을 넘길 때의 추가 요구사항(duplex 등) — 이 페이지는 다루지 않음 |
| C10 | 같은 body 를 두 번 읽을 수 없다. 한 번 읽힌 스트림은 disturbed 상태가 되어 누구도 다시 읽지 못한다 | [§Locked and disturbed streams] "it's not possible to read the same response (or request) body more than once" / "the stream is disturbed, and nothing else can read from the stream." | official-reference |
모든 fetch body | 재시도가 불가능하다는 뜻은 아님 — 새 body 를 만들면 가능하다 |
적용 경계
- 이 자료가 직접 증명하는 것:
C1~C6: 이어받기의 지원 판별·위치 표현·실패 코드·조건부 재개C7·C8: 취소의 오류 표면C9·C10: body 스트림의 1회 소비 제약
- 이 자료가 증명하지 않는 것:
- 업로드 스트리밍(요청 body 를
ReadableStream으로 주는 경우)의 요구사항 —duplex옵션과 HTTP/2 요구를 이 페이지는 언급하지 않는다 - part 재시도 횟수의 적정값 — 프로토콜은 횟수를 말하지 않는다
- 어떤 validator(
ETag/Last-Modified)를If-Range에 써야 하는지
- 업로드 스트리밍(요청 body 를
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- 선택할 object storage 가
Accept-Ranges와If-Range를 실제로 지원하는지(FE-Q-012) - 스트리밍 업로드가 필요한지, 필요하다면
duplex지원 매트릭스
- 선택할 object storage 가
메모
- 인용 1 해석 후보 (미검증):
C4는 조용한 실패의 원천이다. 이어받기를 요청했는데200이 오면 클라이언트는 처음부터 다시 받고 있는 중인데도 "재개 성공" 으로 착각하기 쉽다. adapter 는206을 명시적으로 확인해야 한다. - 인용 2 해석 후보 (미검증):
C10때문에 part 재시도는 원본Blob을 다시 slice 해야 한다. 첫 시도에서 만든 body 를 보관했다가 재사용하면 disturbed 스트림을 보내게 된다. - 추가로 봐야 할 동일 출처 페이지:
Request.duplex,If-Range,Accept-Ranges,AbortSignal.timeout()
관련
- 같은 주제 다른 official-doc:
[[raw/official-docs/aws-s3-multipart-upload-limits]],[[raw/official-docs/mdn-referrer-policy]] - 이 자료를 인용한 wiki 요약: 생성 전