웹 번들로 서브리소스 로딩하기

커뮤니티 그룹 초안 보고서,

이 버전:
https://wicg.github.io/webpackage/subresource-loading.html
이슈 트래킹:
GitHub
명세 내 인라인
편집자:
(Google Inc.)
(Google)

초록

UA가 웹 번들에서 서브리소스를 어떻게 로드하는지에 대해 설명합니다.

이 문서의 상태

이 명세는 웹 플랫폼 인큐베이터 커뮤니티 그룹에서 발행하였습니다. 이는 W3C 표준이 아니며 W3C 표준 트랙에도 포함되어 있지 않습니다. W3C 커뮤니티 기여자 라이선스 계약(CLA) 하에서는 제한적 옵트아웃과 기타 조건이 적용됩니다. W3C 커뮤니티와 비즈니스 그룹에 대해 더 알아보세요.

1. 소개

이 섹션은 비규범적입니다.

웹 번들로 서브리소스 로딩하기 명세는 여러 리소스를 하나의 번들로 묶을 수 있는 포맷(Web Bundles)을 사용하여 다수의 리소스를 효율적으로 로딩하는 방법을 설명합니다. 이 명세는 웹 브라우저가 이러한 리소스를 어떻게 로딩하는지 기술하며, 여기 정의된 알고리즘을 호출하는 [HTML], [FETCH], [CSP] 명세에 대한 여러 몽키패치(monkeypatches)로 구성되어 있습니다.

참고: 이 명세는 작성 중입니다. #708을 참고하세요.

2. 구조

가져온 웹 번들(fetched web bundle)은 [draft-ietf-wpack-bundled-responses-latest]에서 정의된 웹 번들 포맷의 표현입니다.

웹 번들 fetch 엔트리(web bundle fetch entry)는 다음 항목을 갖는 struct입니다.

웹 번들 fetch 엔트리의 더 나은 이름?

웹 번들 fetch 엔트리 entry 에 대해, 문서 document 의 웹 번들 등록 리스트 가 fetch 엔트리 가 entry 인 웹 번들 등록 을 포함 하면, 이 엔트리가 해당 문서에서 등록에 의해 사용됨 이라고 합니다.

번들 규칙(bundle rule)은 다음 항목을 갖는 struct입니다.

웹 번들 등록(web bundle registration)은 다음 항목을 갖는 struct입니다.

웹 번들 파싱 결과(web bundle parse result)는 다음 항목을 갖는 struct입니다.

각 환경 설정 객체(environment settings object)는, 웹 번들 등록 리스트 반환 알고리즘(web bundle registration list)을 가지게 되며, 웹 번들 등록 리스트를 반환합니다. 그 원소들은 웹 번들 등록입니다.

Document는 웹 번들 등록 리스트(web bundle registration list)를 가지며, 이는 웹 번들 등록 리스트이고, 그 원소들은 웹 번들 등록이며, 초기값은 빈 리스트입니다.

윈도우 환경 설정 객체를 설정할 때, settings object의 웹 번들 등록 리스트는 window의 문서의 웹 번들 등록 리스트를 반환합니다.

워커 환경 설정 객체를 설정할 때, settings object의 웹 번들 등록 리스트는 빈 리스트를 반환합니다.

Document는 웹 번들 fetch 엔트리 리스트(web bundle fetch entry list)를 가지며, 이는 웹 번들 fetch 엔트리 리스트이고, 초기값은 빈 리스트입니다.

list가 웹 번들 fetch 엔트리 리스트에 사용되지만, 순서는 중요하지 않을 수 있습니다.

워커(worker)에서는 지원되지 않습니다.

3. HTML 몽키패치

스크립트 요소 준비 알고리즘 (prepare the script element)에서 웹 번들을 기존 스크립트 타입(클래식, 모듈 타입 등)과 일관성 있게 처리하기 위해 다음과 같이 변경합니다.

참고: 웹 번들 결과를 script의 새로운 서브클래스로 정의하지 않으므로, 다른 스크립트 실행 관련 명세에는 영향을 주지 않습니다.

3.1. 스크립트 요소 준비

스크립트 요소 준비 알고리즘 내부에서 다음과 같이 변경합니다.

참고: CSP는 15단계(스크립트 요소 준비)에서 인라인 웹 번들에도 적용되며, 클래식/모듈 스크립트와 동일하게 적용됩니다.

웹 번들 준비(prepare a web bundle): HTMLScriptElement element, string sourceText, URL baseURL을 인자로 받음:

  1. parse result를 웹 번들 문자열 파싱(sourceText, baseURL 사용) 결과로 설정

  2. 예외가 발생한다면:

    1. 스크립트의 실행 결과를 웹 번들 결과(registration: null, error to rethrow: 예외값)로 설정

    2. 준비된 상태로 표시

    3. return

  3. document를 element의 node document로 설정

  4. fetch entry를 null로 설정

  5. document의 웹 번들 fetch 엔트리 리스트의 각 r에 대해:

    1. 만약 r의 source가 parse result의 source와 같고, r의 credentials가 parse result의 credentials와 같다면:

      1. 만약 r이 document에서 등록에 의해 사용됨이 아니라면, fetch entry를 r로 설정

        참고: 즉, 다른 스크립트 요소의 스크립트 결과 의 등록 의 fetch 엔트리 가 r 이었으며 그 스크립트 요소가 제거되었음을 뜻합니다. 동일한 웹 번들 source와 credentials로 HTMLScriptElement가 삭제되었다가 다시 추가되어도, fetch 엔트리가 파괴되었다가 다시 가져와지지 않도록 하기 위함입니다.

  6. fetch entry가 null이라면:

    1. fetch entry를 (source: parse result의 source, credentials: parse result의 credentials, state: "fetching", fetched bundle: null)로 새 웹 번들 fetch 엔트리 생성

    2. 추가 (document의 웹 번들 fetch 엔트리 리스트에 fetch entry)

    3. 병렬로 웹 번들 fetch 실행, fetch entry 인자로 전달

  7. registration을 (fetch entry: fetch entry, rule: parse result의 rule)로 새 웹 번들 등록 생성

  8. 추가 (document의 웹 번들 등록 리스트에 registration)

  9. 스크립트의 실행 결과를 (registration: registration, error to rethrow: null)로 새 웹 번들 결과로 설정

  10. 준비된 상태로 표시

3.2. 이벤트 발생

스크립트 요소 실행에서, Step 6에 다음 case를 추가합니다.

웹 번들 이벤트 처리 알고리즘, HTMLScriptElement element를 입력값으로 받음:

  1. result는 element의 스크립트 실행 결과로 설정.

  2. 단언: element의 스크립트 타입은 "webbundle"임.

  3. 단언: result는 웹 번들 결과임.

  4. 다음 조건 중 하나가 충족될 때까지 비동기로 대기:

    참고: 다른 스크립트 타입들과 달리, 여기서는 웹 번들 fetch를 기다린 뒤에 HTMLScriptElement에 load 이벤트를 발생시킵니다. (load 이벤트 딜레이는 사용하지 않음; 스크립트 요소 준비 단계에서 동기적으로 mark as ready가 호출되기 때문임) 이는 웹 번들 fetch가 preloading과 비슷한 성격임을 반영한 것입니다.

  5. 스크립트 실행 결과가 null이면 return.

    참고: element가 이전 단계 도중에 문서에서 제거된 경우 발생할 수 있습니다.

    참고: 이것은 whatwg/html#2673과 일관되게 지정됨. 현재 이 경우에는 error 이벤트를 발생시키지 않음. 만약 whatwg/html#2673에서 에러 이벤트를 발생시키도록 변경된다면 이 단계도 수정할 것.

  6. 단언: element의 node document가 element의 preparation-time document와 동일함.

  7. result의 error to rethrow가 null이 아니면:

    1. 예외 리포트 실행 (인자: result의 error to rethrow)

      script에 해당하는 값이 없음(웹 번들 결과는 script가 아님). 이 부분은 whatwg/html#958이 해결된 후에 변경 필요.

    2. Return.

  8. 단언: result의 registration이 null이 아님.

  9. result의 registration의 fetch entry의 state가 "failed"이면:

    1. error 이벤트 발생 (element 대상)

    2. Return.

  10. 단언: result의 registration의 fetch entry의 state가 "fetched".

  11. load 이벤트 발생 (element 대상)

3.3. 제거

script 요소가 문서에서 제거될 때, user agent는 다음 알고리즘을 실행해야 합니다.

  1. 스크립트 타입이 "webbundle"이 아니면 return.

  2. 스크립트 실행 결과가 null이면 return.

  3. 스크립트 실행 결과는 웹 번들 결과여야 함.

  4. registration을 스크립트 실행 결과의 registration으로 설정.

  5. 스크립트 실행 결과를 null로 설정.

  6. registration이 null이면 return.

  7. document를 node document로 설정.

  8. 단언: document의 웹 번들 등록 리스트에 registration이 포함됨.

  9. 웹 번들 등록 리스트에서 registration 제거.

  10. 마이크로태스크 큐에 다음 단계를 수행하도록 큐잉:

    1. fetch entry를 registration의 fetch entry로 설정

    2. fetch entry가 document 내 다른 등록(registration)에 의해 사용 중이면 return.

    3. fetch entry 리스트에서 fetch entry 제거.

      참고: fetch entry가 여러 script 요소의 웹 번들 등록에서 공유되어 해당 script들이 제거되었을 때, 이 단계 전에도 document의 웹 번들 fetch 엔트리 리스트가 fetch entry를 포함하지 않을 수 있습니다.

      참고: 이 시점에서 fetch entry는 추가 fetch나 웹 번들 준비에 사용될 수 없으나, 가져온 번들(fetched bundle)은 여전히 진행 중인 fetch에서 활용될 수 있음.

4. Fetch 몽키패치

4.1. Fetch 몽키패치

fetch 알고리즘에서,

  1. Let taskDestination be null.

이 전에 다음 단계를 추가합니다.

  1. find a matching web bundle registration 결과가 null이면 request의 service-workers mode를 "none"으로 설정.

참고: 이는 웹번들 서브리소스 요청은 서비스워커에서 이벤트를 받지 않는다는 의미입니다.

4.2. Fetch scheme 몽키패치

fetch scheme에 "uuid-in-package"를 추가합니다.

참고: 이렇게 하면 navigate 알고리즘이 uuid-in-package: URL에 대해 process a navigate fetch 알고리즘을 사용하도록 보장합니다.

참고: "uuid-in-package" 스킴의 URL origin은 opaque origin입니다.

4.3. HTTP-network-or-cache fetch 몽키패치

HTTP-network-or-cache fetch에서,

8.22. Set httpCache to the result of determining the HTTP cache partition, given httpRequest.

이전에 다음 단계를 추가합니다.

  1. response를 웹 번들에서 서브리소스 fetch 결과로 설정 (httpRequest 인자)

    1. response가 네트워크 에러면, network error 반환

    2. response가 null이 아니면, 8.22~8.24 단계를 건너뛰고 step 9로 이동

      참고: 즉, 웹번들에서의 서브리소스는 HttpCache와 상호작용하지 않습니다. 향후 HttpCache 관련 기능은 계획 중입니다.

5. CSP 몽키패치

5.1. 요청이 소스 목록과 일치하는지 몽키패치

Does request match source list?를 다음 단계로 재정의:

  1. url을 request의 current url로 설정

  2. url의 scheme이 "uuid-in-package"이면:

    1. registration을 find a matching web bundle registration 결과로 설정 (request 인자)

    2. registration이 null이 아니면 url을 registration의 fetch entry의 source로 설정

  3. Does url match source list in origin with redirect count?를 url, source list, policy의 self-origin, request의 redirect count로 실행한 결과를 반환

참고: CSP는 uuid-in-package: URL이 아니라 번들의 URL을 기준으로 평가됩니다. 동기는 #651 참고.

5.2. 응답이 소스 목록과 일치하는지 몽키패치

Does response to request match source list?를 다음 단계로 재정의:

  1. url을 response의 url로 설정

  2. url의 scheme이 "uuid-in-package"이면:

    1. registration을 find a matching web bundle registration 결과(request 인자)를 저장

    2. registration이 null이 아니면 url을 registration의 fetch entry의 source로 설정

  3. Does url match source list in origin with redirect count?를 url, source list, policy의 self-origin, request의 redirect count로 실행한 결과 반환

참고: CSP는 uuid-in-package: URL이 아니라 번들의 URL로 평가됩니다. 동기는 #651 참고.

6. 알고리즘

6.1. 파싱

웹 번들 문자열을 파싱하려면, 문자열 sourceText와 URL baseURL이 주어졌을 때:

  1. parsed를 JSON을 Infra 값으로 파싱하는 결과로 한다. 입력은 sourceText이다.

  2. parsed가 맵이 아니라면, TypeError 예외를 던진다. 최상위 값은 JSON 객체이어야 한다고 알린다.

  3. parsed["source"]가 존재하지 않으면 TypeError를 던진다.

  4. parsed["source"]가 문자열이 아니라면, TypeError를 던진다.

  5. source를 파싱 (parsed["source"]와 baseURL을 기준으로)

  6. source가 null이면, TypeError를 던진다.

  7. credentials를 "same-origin"으로 한다.

  8. parsed["credentials"]가 존재하면:

    1. parsed["credentials"]가 "omit"이면 credentials를 "omit"로 설정한다.

    2. 아니고 parsed["credentials"]가 "include"이면 credentials를 "include"로 설정한다.

  9. resources를 빈 리스트로 한다.

  10. parsed["resources"]가 존재하면:

    1. parsed["resources"]가 리스트가 아니면, TypeError를 던진다.

    2. resources를 URL 리스트 파싱 결과로 덮어쓴다. 입력값은 parsed["resources"], source이다.

  11. scopes를 빈 리스트로 한다.

  12. parsed["scopes"]가 존재하면:

    1. parsed["scopes"]가 리스트가 아니면, TypeError를 던진다.

    2. scopes를 URL 리스트 파싱 결과로 덮어쓴다. 입력값은 parsed["scopes"], source이다.

  13. parsed의 키들이 "source", "credentials", "resources", "scopes" 외의 항목을 포함 하면, 웹 번들 문자열에 유효하지 않은 최상위 키가 있었음을 콘솔에 경고로 보고한다.

    참고: 오타 감지에 도움이 된다. 오류로 간주하지 않는 이유는, 추후 확장성과의 호환을 막지 않기 위함이다.

  14. rule을 번들 규칙으로 한다. 리소스는 resources, 스코프는 scopes이다.

  15. 웹 번들 파싱 결과를 반환한다. source는 source, credentials는 credentials, rule은 rule이다.

URL 리스트 파싱을 하려면, 리스트 originalList와 URL baseURL이 주어졌을 때:

  1. parsed URL list를 빈 리스트로 한다.

  2. 각 item을 originalList에서 반복하여,

    1. item이 문자열이면

      1. URL을 파싱 결과로 한다. 입력값은 item, baseURL이다.

      2. URL이 null이 아니면, URL을 parsed URL list에 추가한다.

  3. parsed URL list를 반환한다.

6.2. 웹 번들 가져오기

웹 번들 가져오기를 하려면, 웹 번들 fetch 엔트리 fetch entry와 fetch 파라미터 fetch params가 주어졌을 때:

  1. 단언: fetch entry의 state는 "fetching"이다.

  2. request를 fetch params의 request로 한다.

  3. request의 url을 fetch entry의 source로 설정한다.

    참고: 소스 URL은 문서의 base URL을 기준으로 결정된다.

  4. request의 destination을 "webbundle"로 설정한다,

  5. request의 mode를 "cors"로 설정한다,

  6. request의 credentials mode를 fetch entry의 credentials로 설정한다.

  7. request의 service-workers mode를 "none"으로 설정한다.

  8. 헤더("Accept", "application/webbundle;v=b2")를 request의 header list에 추가한다.

    참고: 최종 [draft-ietf-wpack-bundled-responses-latest]는 1 버전을 사용하지만, 현재 명세는 브라우저 구현에서 실제 사용 중인 draft 버전을 기준으로 한다.

  9. Fetch request를 하고, processResponse 알고리즘을 process web bundle response로 적용, 이때 fetch entry를 인자로 준다.

    참고: 크로미움의 현재 구현에서는 중첩 번들을 허용하지 않는다. 웹 번들은 다른 웹 번들에서 가져오지 않는다.

6.3. 웹 번들 응답 처리

웹 번들 응답 처리를 하려면 웹 번들 fetch entry fetch entry와 response response가 주어졌을 때:

  1. response의 status가 ok status이면,

    1. response의 body를 웹 번들로 파싱한다 ([draft-ietf-wpack-bundled-responses-latest]).

      참고: response의 body는 이 시점에 완전히 사용 가능하지 않을 수 있다. UA가 body를 점진적으로 비동기적으로 읽으며 일부 서브리소스를 빠르게 서비스할 수 있다.

      참고: 파싱 시 크로미움의 실험적 구현은 "b2"만 웹 번들 포맷 버전으로 허용한다 ([draft-ietf-wpack-bundled-responses-latest]).

    2. 파싱 알고리즘이 비동기적으로 완료되면 fetch entry의 fetched bundle에 파싱 결과를 넣고, fetch entry의 state를 "fetched"로 한다. 파싱 실패나 조건 불충족시 fetched bundle은 null로, state는 "failed"로 한다.

  2. 그 외의 경우, fetch entry의 state를 "failed"로 한다.

6.4. 웹 번들에서 서브리소스 가져오기

웹 번들에서 서브리소스를 가져오기를 하려면 요청 httpRequest가 주어졌을 때:

  1. registration을 적합한 웹 번들 등록 찾기를 httpRequest에 대해 실행 결과로 한다.

  2. registration이 null이 아니면:

    1. response를 웹 번들 fetch entry에서 응답 얻기 실행 결과로 한다. 입력값은 httpRequest의 url 및 registration의 fetch entry이다.

    2. response가 null이면 네트워크 에러를 반환한다.

      참고: 브라우저는 서브리소스를 네트워크로 가져오는 fallback을 수행하지 않음을 의미한다.

    3. 그렇지 않으면 response를 반환한다.

  3. null을 반환한다.

참고: 여기서 null을 반환하면 HTTP 캐시 및 일반 네트워크 패치로 fallback 처리 가능. 위의 네트워크 에러 반환과는 다르다.

웹 번들 fetch entry에서 응답 얻기를 하려면 url url과 웹 번들 fetch entry fetch entry가 주어졌을 때:

  1. fetch entry의 state가 "fetching"이면 state가 "fetched" 또는 "failed"가 될 때까지 비동기적으로 대기한다.

  2. fetch entry의 state가 "failed"이면 null을 반환한다.

  3. 단언: fetch entry의 fetched bundle은 null이 아니다.

  4. response를 fetch entry의 fetched bundle에서 url로 가져와 반환한다 ([draft-ietf-wpack-bundled-responses-latest]). url에 해당하는 표현이 fetched bundle에 없으면 null을 반환한다.

6.5. 적합한 등록 찾기

적합한 웹 번들 등록 찾기를 하려면 요청 httpRequest가 주어졌을 때:

  1. url을 httpRequest의 url로 한다.

  2. 각 registration을 httpRequest의 클라이언트의 웹 번들 등록 리스트에서 반복한다:

    1. rule을 registration의 rule로 한다.

    2. url의 scheme이 "uuid-in-package"가 아니라면,

      1. url의 origin과 registration의 fetch entry의 source의 origin이 동일 출처가 아니면 계속한다.

      2. allowed path를 단축(registration의 fetch entry의 source의 path)로 한다.

      3. url의 path가 allowed path로 시작하지 않으면 계속한다.

    3. rule의 resources가 url을 포함하면 registration을 반환한다.

    4. url이 rule의 scopes 중 하나로 시작하면 registration을 반환한다.

  3. null을 반환한다.

적합성

문서 규약

적합성 요구사항은 설명적 단언과 RFC 2119 용어의 조합으로 표현됩니다. 본 문서의 규범 부분에 나타나는 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 등 주요 단어들은 RFC 2119에 설명된 대로 해석되어야 합니다. 다만 가독성을 위해 이 명세서에서는 이 단어들을 모두 대문자로 표기하지 않습니다.

명시적으로 비규범 섹션, 예시, 참고로 표시된 부분을 제외한 명세서의 모든 텍스트는 규범적입니다. [RFC2119]

본 명세서에 등장하는 예시는 “예를 들어”라는 서두나, 규범적인 텍스트와 구분되는 class="example" 특성으로 도입됩니다. 예시:

이것은 참고용 예시입니다.

참고(Informative) 표기는 “참고”라는 단어로 시작하며, 규범 본문과 class="note" 특성으로 구분됩니다. 예시:

참고, 이것은 참고용 안내문입니다.

색인

이 명세서에서 정의된 용어

참조에 의해 정의된 용어

참조

규범적 참조

[CONSOLE]
Dominic Farolino; Robert Kowalski; Terin Stock. Console Standard. Living Standard. URL: https://console.spec.whatwg.org/
[CSP]
Mike West; Antonio Sartori. Content Security Policy Level 3. URL: https://w3c.github.io/webappsec-csp/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

참고용 참조

[DRAFT-IETF-WPACK-BUNDLED-RESPONSES-LATEST]
Web Bundles. URL: https://wpack-wg.github.io/bundled-responses/draft-ietf-wpack-bundled-responses.html

이슈 색인

web bundle fetch entry에 더 적합한 이름이 있을까요? ↵
list는 web bundle fetch entry list에 사용되지만, 순서는 중요하지 않아야 합니다. ↵
워커에서는 지원되지 않습니다. ↵
관련 script가 존재하지 않습니다. web bundle result는 script가 아니기 때문입니다. 이는 whatwg/html#958이 해결될 때까지 대기해야 합니다. ↵