소프트 내비게이션과 상호작용 콘텐츠풀 페인트

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

이 버전:
https://wicg.github.io/soft-navigations/
테스트 스위트:
https://github.com/web-platform-tests/wpt/tree/master/soft-navigation-heuristics
이슈 추적:
GitHub
명세 내 인라인
편집자:
(Google)
(Google)
이전 편집자:
(Shopify)

초록

이 문서는 웹 페이지 작성자가 동일 문서("소프트") 내비게이션을 감지하고, 이후의 페이지 수정과 콘텐츠풀 페인트를 이를 트리거한 사용자 상호작용에 귀속시키는 데 사용할 수 있는 API 집합을 정의한다.

이 문서의 상태

이 명세는 Web Platform Incubator 커뮤니티 그룹에서 발행했다. 이는 W3C 표준이 아니며 W3C 표준화 트랙에 있지도 않다. 유의할 점은, W3C Community Contributor License Agreement (CLA)에 따라 제한된 옵트아웃 및 기타 조건이 적용된다는 것이다. W3C 커뮤니티 및 비즈니스 그룹에 대해 자세히 알아보라.

1. 소개

이 절은 비규범적입니다.

현대 웹 애플리케이션은 전체 페이지 내비게이션을 수행하지 않고도 사용자 상호작용에 응답하여 콘텐츠를 동적으로 업데이트하는 경우가 많습니다. 구조적 DOM 수정, 콘텐츠풀 페인트, 히스토리 상태 변경과 같은 이러한 상호작용으로 시작된 효과는 역사적으로 올바른 사용자 동작에 측정하고 귀속하기 어려웠습니다.

일반적인 단일 페이지 애플리케이션 패턴을 생각해 보십시오. 사용자가 제품 링크를 클릭하면, click 이벤트 핸들러가 트리거됩니다. 이 핸들러는 제품 세부 정보를 위해 네트워크 fetch()를 시작합니다. 응답이 도착하면 새 콘텐츠를 DOM에 동적으로 삽입하고 History 또는 Navigation API를 사용하여 URL을 업데이트하는 콜백이 실행됩니다. 이는 사용자에게 내비게이션처럼 보이지만, Largest Contentful Paint (LCP) ([LARGEST-CONTENTFUL-PAINT]) 같은 기존 지표는 초기 페이지 로드만 측정하고, Interaction to Next Paint (INP)는 클릭 자체의 즉각적인 시각적 피드백만 측정하므로, 그 뒤의 중요한 렌더링과 "소프트" 내비게이션은 포착되지 않습니다.

이 명세는 [EVENT-TIMING] API를 활용하여 상호작용을 정의하고, [ASYNC-CONTEXT] 제안을 활용하여 비동기 작업 경계를 가로지르는 인과관계를 추적함으로써, 수정된 DOM 노드를 상호작용에 매핑하고, 콘텐츠풀 페인트를 그것을 유발한 상호작용에 귀속할 수 있게 합니다. 이 명세는 브라우저가 "소프트 내비게이션"을 포함한 이러한 효과를 식별하고 보고할 수 있는 방법을 정의하며, [PAINT-TIMING][LARGEST-CONTENTFUL-PAINT]와 통합하여 렌더링 변경을 성능 타임라인에 귀속합니다.

2. 성능 타임라인 슬라이싱

이 절은 비규범적입니다.

성능 지표(예: 이벤트 타이밍, 레이아웃 이동, 리소스 로드 또는 긴 애니메이션 프레임)를 이를 시작한 탐색에 귀속시키기 위해, 성능 타임라인은 navigationId 속성을 PerformanceEntry에 사용하여 세그먼트로 슬라이스됩니다.

시간에 걸쳐 이어지는 전환의 정확한 슬라이스 지점을 결정하는 것은 복잡합니다. 일관된 귀속을 보장하기 위해, 이 명세는 모든 URL 수정 즉시 타임라인을 슬라이스하지 않는 모델을 채택합니다. 대신 전환은 소프트 탐색이 성능 타임라인에 내보낼 준비가 될 때까지 지연됩니다.

설계상의 절충점, 귀속 규칙 및 경계 사례에 대한 자세한 논의는 [PERFORMANCE-TIMELINE] 이슈 comment를 참조하십시오.

2.1. 탐색 ID

탐색 id전역 객체의 수명 동안 각 탐색(하드 및 소프트 모두)에 할당되는 고유한 식별자입니다.

Window는 다음을 가집니다.

참고: 초기 탐색 id 값탐색 id 증가량navigationId 값을 계산하는 데 사용됩니다( 현재 탐색 id 증가시키기 참조). 이는 개발자가 이를 정확한 탐색 횟수를 세는 데 의존하거나 0에서 시작한다고 가정하는 것을 막습니다. 사용자 에이전트는 교차 출처 누수를 방지하기 위해 서로 다른 Window 객체 간에 공유 전역 탐색 값을 사용하지 않을 것으로 기대됩니다.

Window window가 주어졌을 때 현재 탐색 id 증가시키기는 다음과 같습니다.
  1. window탐색 횟수window탐색 횟수에 1을 더한 값으로 설정합니다.

  2. newIdwindow초기 탐색 id 값 더하기 (window탐색 횟수 곱하기 window탐색 id 증가량)으로 둡니다.

  3. window현재 탐색 idnewId로 설정합니다.

2.2. PerformanceEntry 확장

[Exposed=(Window,Worker)]
partial interface PerformanceEntry {
    readonly attribute unsigned long long navigationId;
};
PerformanceEntry에는 관련된 탐색 id가 있으며, 이는 64비트 부호 없는 정수이고 처음에는 0입니다.

navigationId 속성의 getter는 this탐색 id를 반환해야 합니다.

2.3. 성능 타임라인 통합

PerformanceEntry 큐에 넣기에서 1단계(엔트리 초기화) 이후 다음 단계를 추가합니다.

  1. newEntry탐색 id가 0인 경우:

    1. globalWindow 객체인 경우:

      1. newEntry탐색 idglobal현재 탐색 id로 설정합니다.

3. 상호작용 인프라

3.1. 상호작용 컨텍스트 소개

소프트 탐색 감지는 작업의 인과관계를 추적하고 특정 작업(예: DOM 노드 추가)이 특정 사용자 상호작용에 의해 트리거되었음을 관찰하는 기능에 의존합니다.

이 명세는 이러한 전파를 처리하기 위해 TC39 [ASYNC-CONTEXT] 제안을 활용합니다. 모든 새 사용자 상호작용(Event Timing에서 정의됨) 또는 관련 탐색 이벤트는 새 InteractionContext를 생성합니다. 이 컨텍스트는 숨겨진 내부 전용 AsyncContext.Variable ([[ActiveInteractionContext]]로 표시됨)에 저장됩니다.

웹 플랫폼과 AsyncContext의 통합은 이 변수가 비동기 연속(예: setTimeout, fetch, await)에 자동으로 연결되도록 하여, 브라우저가 이후의 효과를 원래 상호작용에 다시 귀속시킬 수 있게 합니다.

스크립트 전파에 더해, 이 명세는 DOM을 수정하는 사용자 상호작용이 DOM 수립하는 수정된 노드들의 집합을 정의하며, 해당 상호작용과 연결되게 하여, 콘텐츠풀 페인트와 같은 이후의 렌더링 효과를 현재 비동기 스크립트가 실행 중이 아니더라도 이를 시작한 상호작용 컨텍스트까지 거슬러 추적할 수 있게 한다.

3.2. InteractionContext 구조체

InteractionContext는 단일 상호작용으로부터 소프트 내비게이션을 감지하는 데 필요한 데이터를 유지하는 데 사용되는 구조체이다. 이는 다음 항목들을 가진다:

참고: 이 명세의 향후 버전은 탐색의 더 완전한 이력을 제공하기 위해 상호작용 컨텍스트 중 발생하는 모든 URL 업데이트를 추적할 수도 있습니다. 마지막 URL 값은 현재 PerformanceSoftNavigation의 name에 첫 URL 값만 노출되더라도, 효과를 상호작용의 최종 상태로 정확하게 다시 귀속시키기 위해 내부적으로 추적됩니다.

3.3. 인프라 알고리즘

현재 상호작용 컨텍스트를 가져온다, Document document가 주어졌을 때:
  1. context를 내부 AsyncContext.Variable [[ActiveInteractionContext]]의 값으로 둔다.

  2. context가 null이 아니고 context컨텍스트 문서document와 같지 않으면, null을 반환한다.

  3. context를 반환한다.

상호작용에 대한 컨텍스트를 가져오거나 생성한다, Document documentPerformanceEventTiming timing entry가 주어졌을 때:
  1. interaction idtiming entryinteractionId로 둔다.

  2. interaction id가 0보다 크다고 단언한다.

  3. document상호작용 id에서 상호작용 컨텍스트로[interaction id]가 존재하면, document상호작용 id에서 상호작용 컨텍스트로[interaction id]를 반환한다.

  4. interaction context를 새 InteractionContext로 둔다.

  5. interaction contextidinteraction id로 설정한다.

  6. interaction context컨텍스트 문서document로 설정한다.

  7. interaction context시작 시간timing entrystartTime으로 설정한다.

  8. document상호작용 id에서 상호작용 컨텍스트로[interaction id]를 interaction context설정한다.

  9. interaction context를 반환한다.

이벤트에 대한 상호작용 컨텍스트들을 갱신한다, Document documentEvent event가 주어졌을 때:
  1. timestampdocument관련 전역 객체가 주어졌을 때의 현재 고해상도 시간으로 둔다.

  2. is scrollevent의 타입이 "scroll"이면 true로, 그렇지 않으면 false로 둔다.

  3. is inputevent의 타입이 has dispatched input event를 트리거할 이벤트 타입이면 true로 두고([EVENT-TIMING]에 정의된 바와 같이), 그렇지 않으면 false로 둔다.

  4. is scroll이 false이고 is input이 false이면, 반환한다.

  5. document상호작용 id에서 상호작용 컨텍스트로의 값들 중 각 interaction context에 대해:

    1. is scroll이 true이고 interaction context첫 번째 스크롤 타임스탬프가 0이면:

      1. interaction context첫 번째 스크롤 타임스탬프timestamp로 설정한다.

    2. is input이 true이고 interaction context첫 번째 입력 타임스탬프가 0이면:

      1. interaction context첫 번째 입력 타임스탬프timestamp로 설정한다.

이벤트 디스패치를 위한 현재 상호작용 컨텍스트를 설정한다, null 또는 PerformanceEventTiming 객체 timing entry가 주어졌을 때:
  1. timing entry가 null이면, null을 반환한다.

  2. interaction idtiming entryinteractionId로 둔다.

  3. interaction id가 0이면, null을 반환한다.

  4. eventtiming entry연결된 이벤트로 둔다.

  5. documentevent관련 전역 객체연결된 Document로 둔다.

  6. documentevent가 주어졌을 때 이벤트에 대한 상호작용 컨텍스트들을 갱신한다.

  7. interaction contextdocumenttiming entry가 주어졌을 때 상호작용에 대한 컨텍스트를 가져오거나 생성한 결과로 둔다.

  8. 내부 AsyncContext.Variable [[ActiveInteractionContext]]의 값을 interaction context로 설정한다.

  9. interaction context를 반환한다.

이벤트 디스패치 후 현재 상호작용 컨텍스트를 해제한다:
  1. 내부 AsyncContext.Variable [[ActiveInteractionContext]]의 값을 null로 설정한다.

4. 상호작용 콘텐츠풀 페인트

4.1. InteractionContentfulPaint 인터페이스

[Exposed=Window]
interface InteractionContentfulPaint : PerformanceEntry {
    readonly attribute LargestContentfulPaint largestContentfulPaint;
    readonly attribute unsigned long long interactionId;

    object toJSON();
};

InteractionContentfulPaint includes PaintTimingMixin;

InteractionContentfulPaint에는 다음이 있습니다.

largestContentfulPaint 속성의 getter는 this가장 큰 콘텐츠풀 페인트를 반환해야 한다.

interactionId 속성의 getter는 this컨텍스트id를 반환해야 한다.

name 속성의 getter는 빈 문자열을 반환해야 한다.

entryType 속성의 getter는 "interaction-contentful-paint"를 반환해야 한다.

startTime 속성의 getter는 this컨텍스트시작 시간을 반환해야 한다.

duration 속성의 getter는 this페인트 타이밍 정보에 대한 기본 페인트 타임스탬프this컨텍스트시작 시간 사이의 차이를 반환해야 한다.

참고: 이 엔트리는 연결된 InteractionContext에서 정적 상호작용 속성(interactionIdstartTime 등)을 동적으로 질의하지만, 생성 시점의 페인트의 페인트 타이밍 정보와 후보 LargestContentfulPaint 엔트리의 정적 스냅샷을 캡처하여 이러한 메트릭이 해당 시각적 갱신의 정확한 상태를 반영하도록 보장한다.

4.2. 상호작용 콘텐츠풀 페인트 알고리즘

Window window, InteractionContext interaction context, LargestContentfulPaint lcpEntry, 그리고 페인트 타이밍 정보 paintTimingInfo가 주어졌을 때 상호작용 콘텐츠풀 페인트 엔트리 생성하기는 다음과 같습니다.
  1. entrywindowrealm 안의 새 InteractionContentfulPaint 객체로 둡니다.

  2. entry컨텍스트interaction context로 설정합니다.

  3. entry최대 콘텐츠풀 페인트lcpEntry로 설정합니다.

  4. entry의 연결된 페인트 타이밍 정보paintTimingInfo로 설정합니다.

  5. entry를 반환합니다.

새로 귀속된 콘텐츠풀 페인트 후보를 처리한다, 가장 큰 콘텐츠풀 페인트 후보 lcpCandidate, Document document, InteractionContext interaction context, 그리고 페인트 타이밍 정보 paintTimingInfo가 주어졌을 때:
  1. interaction context첫 번째 스크롤 타임스탬프가 0보다 크고 lcpEntryrenderTimeinteraction context첫 번째 스크롤 타임스탬프보다 크면, 반환한다.

  2. interaction context첫 번째 입력 타임스탬프가 0보다 크고 lcpEntryrenderTimeinteraction context첫 번째 입력 타임스탬프보다 크면, 반환한다.

  3. lcpEntrylcpCandidate, paintTimingInfo, 그리고 documentLargestContentfulPaint 엔트리를 생성한 결과로 둔다.

  4. globaldocument관련 전역 객체로 둔다.

  5. paint timing infolcpEntry의 연결된 페인트 타이밍 정보로 둔다.

  6. icpEntryglobal, interaction context, lcpEntry, 그리고 paint timing info가 주어졌을 때 상호작용 콘텐츠풀 페인트 엔트리를 생성한 결과로 둔다.

  7. icpEntry큐에 넣는다.

  8. icpEntryglobal성능 엔트리 버퍼에 추가한다.

  9. interaction context첫 번째 콘텐츠풀 페인트가 null이면:

    1. interaction context첫 번째 콘텐츠풀 페인트icpEntry로 설정한다.

  10. interaction context가장 큰 콘텐츠풀 페인트icpEntry로 설정한다.

  11. interaction context현재 가장 큰 콘텐츠풀 페인트 후보lcpCandidate로 설정한다.

참고: InteractionContentfulPaint 항목은 상호작용이 최종적으로 소프트 내비게이션으로 이어지는지 여부와는 독립적으로, 감지되는 대로 성능 타임라인에 방출된다. 이를 통해 개발자는 모든 상호작용에 대한 렌더링 업데이트를 모니터링할 수 있다.

Document document, paint timing info paintTimingInfo, ordered setpending image records paintedImages, 그리고 ordered setelements paintedTextNodes가 주어졌을 때 interaction contentful paints 및 soft navigations 보고를 수행하려면:
  1. contextToCandidateSets를 새 map으로 둔다.

  2. paintedImages의 각 record에 대해 반복한다:

    1. elementrecordelement로 둔다.

    2. interaction contextelement에 대해 paint attribution interaction context 가져오기를 수행한 결과로 둔다.

    3. interaction context가 null이 아니면:

      1. contextToCandidateSetsinteraction context포함하지 않으면, contextToCandidateSets[interaction context]를 « «», «» »로 설정한다.

      2. recordcontextToCandidateSets[interaction context][0]에 추가한다.

  3. paintedTextNodes의 각 element에 대해 반복한다:

    1. interaction contextelement에 대해 paint attribution interaction context 가져오기를 수행한 결과로 둔다.

    2. interaction context가 null이 아니면:

      1. contextToCandidateSetsinteraction context포함하지 않으면, contextToCandidateSets[interaction context]를 « «», «» »로 설정한다.

      2. elementcontextToCandidateSets[interaction context][1]에 추가한다.

  4. contextToCandidateSets 안의 각 interaction contextcandidateSets에 대해 반복한다:

    1. newCandidatedocument, candidateSets[0], candidateSets[1], 그리고 interaction contextcurrent largest contentful paint candidate가 주어졌을 때 새로운 largest contentful paint candidate 계산을 수행한 결과로 둔다.

    2. newCandidate가 null이 아니면:

      1. newCandidate, document, interaction context, 그리고 paintTimingInfo가 주어졌을 때 새로운 귀속된 contentful paint candidate 처리를 수행한다.

      2. documentinteraction context가 주어졌을 때 soft navigation emission 평가를 수행한다.

4.3. Interaction Contentful Paint Attribution

InteractionPaintTimingNodeState는 다음 항목을 가진 struct이다:


InteractionPaintTimingNodeState node stateInteractionPaintTimingNodeState 또는 null인 other node state보다 더 최근인지 판단하려면:
  1. other node state가 null이거나 node statemodification idother node statemodification id보다 크면 true를 반환하고, 그렇지 않으면 false를 반환한다.

주어진 Node node에 대해 paint attribution interaction context 가져오기를 수행하려면:
  1. documentnodenode document로 둔다.

  2. node statedocumentpropagated node state[node]로 두되, 기본값을 null로 하는 with default를 사용한다.

  3. node state가 null이면 null을 반환하고, 그렇지 않으면 node statecontext를 반환한다.

Node target node가 주어졌을 때 interaction paint timing을 위해 수정된 노드로 기록하려면:
  1. documentnodenode document로 둔다.

  2. target nodedocument가 주어졌을 때 exposed for paint timing이 아니면, 반환한다.

  3. interaction contextdocument가 주어졌을 때 current interaction context 가져오기를 수행한 결과로 둔다.

  4. interaction context가 null이면 반환한다.

  5. documentlast modification contextinteraction context와 같지 않으면:

    1. documentlast modification contextinteraction context로 설정한다.

    2. documentcurrent modification generation id를 1 증가시킨다.

  6. previous node statedocumentmarked node state[target node]로 두되, 기본값을 null로 하는 with default를 사용한다.

  7. previous node state가 null이 아니고 previous node statemodification iddocumentcurrent modification generation id와 같으면, 반환한다.

  8. node state를 새로운 InteractionPaintTimingNodeState로 둔다.

  9. node statecontextinteraction context로 설정한다.

  10. node statemodification iddocumentcurrent modification generation id로 설정한다.

  11. documentmarked node state[node]를 node state설정한다.

  12. documentis interaction paint timing dirty를 true로 설정한다.

Document document가 주어졌을 때 document 및 그 자손에 대한 interaction context 갱신을 수행하려면:
  1. documentis interaction paint timing dirty가 false이면, 반환한다.

  2. document와 null이 주어졌을 때 node 및 그 자손에 대한 interaction context 갱신을 수행한다.

  3. documentis interaction paint timing dirty를 false로 설정한다.

Node nodeInteractionPaintTimingNodeState inherited node state 또는 null이 주어졌을 때 node 및 그 자손에 대한 interaction context 갱신을 수행하려면:
  1. documentnodenode document로 둔다.

  2. node statedocumentmarked node state[node]로 두되, 기본값을 null로 하는 with default를 사용한다.

  3. node state가 null이 아니면:

    1. node stateinherited node state보다 더 최근이면:

      1. inherited node statenode state로 설정한다.

      2. nodeText node이면, documentmarked node state[node]를 제거한다.

    2. 그렇지 않으면, documentmarked node state[node]를 제거한다.

  4. inherited node state가 null이 아니고 nodetiming-eligible이면:

    1. attribution elementnode에 대해 attribution element 가져오기를 수행한 결과로 둔다.

    2. previous propagated statepropagated node state[attribution element]로 두되, 기본값을 null로 하는 with default를 사용한다.

    3. inherited node stateprevious propagated state보다 더 최근이면:

      1. propagated node state[attribution element]를 inherited node state로 설정한다.

      2. previous propagated state가 null이거나 previous propagated statecontextinherited node statecontext와 같지 않으면, attribution element에 대해 paint tracking 재설정을 수행한다.

  5. node의 각 자식 child node에 대해 반복하여, child nodeinherited node state가 주어졌을 때 node 및 그 자손에 대한 interaction context 갱신을 수행한다.

참고: 단순화를 위해, 이 알고리즘은 전파된 상태를 다시 처리해야 할 때마다 전체 DOM을 순회한다. 이는 페인트 가능한 DOM의 일부만 처리하도록 최적화할 수 있으며, 예를 들어 보이지 않는 것으로 알려진 하위 트리나 content-visibility 또는 CSS containment 같은 기존 메커니즘에 의해 건너뛰어진 하위 트리도 이 과정에서 건너뛸 수 있다. 단, 다음에 페인트되기 전에 업데이트되어야 한다. 또한 관련 상태가 페인트 전에 업데이트되기만 한다면, 이 단계들은 다른(pre-paint) 트리 순회와 병합하여 추가로 최적화할 수 있다.

참고: [CONTAINER-TIMING] API는 공통 DOM 조상별로 렌더링 효과를 그룹화하고 집계된 paint 정보를 성능 타임라인에 보고하는 메커니즘을 제공한다. 이 명세의 향후 버전에서는 단일 container에 대한 여러 client (즉, 전역 "containertiming" 속성과 per-interaction timing)를 지원하도록 Container Timing을 확장하여 Container Timing의 관점에서 interaction paint timing을 구현할 수 있게 할 계획이다. 기록된 각 node는 그것을 수정한 interaction에 대한 container로 간주되어, 각 interaction이 container 집합과 연결되도록 할 것이다. 그러면 이 명세는 각 interaction에 대해 표시된 container에서 발생하는 largest contentful paint를 추적하게 된다. 나아가, Container Timing이 추적하는 다른 유용한 정보, 예를 들어 각 interaction에 대한 container의 집계된 총 페인트 면적도 노출할 수 있다.

5. 소프트 내비게이션

5.1. PerformanceSoftNavigation 인터페이스

[Exposed=Window]
interface PerformanceSoftNavigation : PerformanceEntry {
    readonly attribute NavigationType navigationType;
    readonly attribute unsigned long long interactionId;
    InteractionContentfulPaint? getLargestInteractionContentfulPaint();
};

PerformanceSoftNavigation includes PaintTimingMixin;

PerformanceSoftNavigation은 다음을 가진다:

navigationType 속성의 getter는 this컨텍스트내비게이션 타입을 반환해야 한다.

interactionId 속성의 getter는 this컨텍스트id를 반환해야 한다.

getLargestInteractionContentfulPaint() 메서드는 this컨텍스트가장 큰 콘텐츠풀 페인트를 반환해야 한다.

name 속성의 getter는 this컨텍스트첫 번째 URL 값을 반환해야 한다.

entryType 속성의 getter는 "soft-navigation"을 반환해야 한다.

startTime 속성의 getter는 this컨텍스트시작 시간을 반환해야 한다.

duration 속성의 getter는 방출 시점의 thispresentationTimethis컨텍스트시작 시간 사이의 차이를 반환해야 한다.

참고: 실제로는 getLargestInteractionContentfulPaint()가 null이 아닌 항목을 반환할 것으로 기대된다. 확정된 소프트 내비게이션은 그 방출을 트리거하려면 적어도 하나의 감지된 interaction contentful paint가 필요하기 때문이다.

그러나 향후 반복에서는 첫 페인트 이전, URL 수정 즉시 소프트 내비게이션을 커밋된 것으로 간주할 수 있는지 평가할 수 있다. 이러한 모델에서는 이 메서드가 방출 시점에 null을 반환할 수도 있다.

이 타이밍의 주요 설계 고려 사항은 URL 수정과 첫 페인트 사이의 구간에 발생하는 다른 타임라인 항목 (예: LayoutShift, PerformanceResourceTiming, LongAnimationFrameTiming 등)의 귀속이다. 많은 사이트는 예를 들어 fetch 요청을 시작하는 즉시 새 URL을 커밋하지만, 그동안 현재 페이지는 여전히 이전 내비게이션 상태에 남아 있다. 일관된 타임라인 슬라이싱을 보장하기 위해, 이 명세는 첫 페인트가 전환을 확인할 때까지 이러한 모든 항목을 이전 navigation identifier에 귀속한다.

5.2. 소프트 내비게이션 알고리즘

소프트 내비게이션은 다음 조건을 만족하는 same-document navigation이다:

소프트 내비게이션 방출을 평가한다, Document documentInteractionContext interaction context가 주어졌을 때:
  1. interaction context방출됨이 true이면, 반환한다.

  2. document활성 소프트 내비게이션 후보interaction context가 아니면, 반환한다.

  3. interaction context첫 번째 URL 값이 null이면, 반환한다.

  4. interaction context첫 번째 콘텐츠풀 페인트가 null이면, 반환한다.

  5. windowdocument관련 전역 객체로 둔다.

  6. entrywindowinteraction context가 주어졌을 때 소프트 내비게이션 엔트리를 생성한 결과로 둔다.

  7. windowentry가 주어졌을 때 소프트 내비게이션 엔트리를 방출한다.

  8. interaction context방출됨을 true로 설정한다.

소프트 내비게이션 엔트리를 생성한다, Window windowInteractionContext interaction context가 주어졌을 때:
  1. entrywindow렐름 안에 있는 새 PerformanceSoftNavigation 객체로 둔다.

  2. entry컨텍스트interaction context로 설정한다.

  3. first paintinteraction context첫 번째 콘텐츠풀 페인트로 둔다.

  4. first paint가 null이 아니라고 단언한다.

  5. entry의 연결된 페인트 타이밍 정보first paint의 연결된 페인트 타이밍 정보로 설정한다.

  6. entry를 반환한다.

소프트 내비게이션 엔트리를 방출한다, Window windowPerformanceSoftNavigation entry가 주어졌을 때:
  1. window가 주어졌을 때 현재 내비게이션 id를 증가시킨다.

  2. entry큐에 넣는다.

  3. entrywindow성능 엔트리 버퍼에 추가한다.

참고:navigationId는 이 PerformanceSoftNavigation 엔트리를 성능 타임라인에 큐에 넣는 과정의 일부로 자동 설정되며, 다른 PerformanceEntry 타입의 동작과 일치한다.

동일 문서 커밋을 처리한다, Document document, 문자열 url, 그리고 NavigationType navigation type이 주어졌을 때:
  1. urldocumenturl과 같으면, 반환한다.

  2. interaction contextdocument가 주어졌을 때 현재 상호작용 컨텍스트를 가져온 결과로 둔다.

  3. interaction context가 null이면, 반환한다.

  4. interaction context마지막 URL 값url로 설정한다.

  5. interaction context첫 번째 URL 갱신 타임스탬프가 null이면:

    1. interaction context첫 번째 URL 갱신 타임스탬프document관련 전역 객체가 주어졌을 때의 현재 고해상도 시간으로 설정한다.

    2. interaction context첫 번째 URL 값url로 설정한다.

    3. interaction context내비게이션 타입navigation type으로 설정한다.

  6. document활성 소프트 내비게이션 후보interaction context로 설정한다.

  7. documentinteraction context가 주어졌을 때 소프트 내비게이션 방출을 평가한다.

6. 명세 통합

6.1. DOM 통합

6.1.1. Document

문서상호작용 id에서 상호작용 컨텍스트로, 즉 을 가지며, 초깃값은 비어 있다.

문서활성 소프트 내비게이션 후보, 즉 InteractionContext 또는 null을 가지며, 초깃값은 null이다.

문서현재 수정 생성 id, 즉 64비트 부호 없는 정수를 가지며, 0으로 초기화된다.

참고: 현재 수정 생성 id는 관련 DOM 수정이 이전 수정과 다른 InteractionContext로 발생할 때 변경된다. 이는 관련 수정들을 함께 그룹화할 수 있게 하며, 이를 통해 InteractionPaintTimingNodeState 객체들을 최신성 측면에서 비교하고 추적해야 하는 노드를 최적화할 수 있다.

문서마지막 수정 컨텍스트, 즉 InteractionContext 또는 null을 가지며, 초깃값은 null이다.

문서표시된 노드 상태, 즉 을 가지며, 이는 Node에서 InteractionPaintTimingNodeState로의 맵이고, 초깃값은 비어 있다.

문서전파된 노드 상태, 즉 을 가지며, 이는 Node에서 InteractionPaintTimingNodeState로의 맵이고, 초깃값은 비어 있다.

문서상호작용 페인트 타이밍이 더티인지, 즉 불리언을 가지며, 초깃값은 false이다.

6.1.2. Node

node insert 시, 또는 node node가 다음 방식 중 하나로 수정될 때:

다음 단계를 실행한다:

  1. node가 주어졌을 때 interaction paint timing을 위해 수정된 노드로 기록한다.

6.2. HTML 통합

6.2.1. History

히스토리 단계 적용을 위해 문서를 갱신할 때, 5.5.1 이전에(documentsEntryChanged가 true이고 documentIsNew가 false인 경우), 동일 문서 커밋을 처리한다. 이때 Document, 대상 엔트리의 url, 그리고 "traverse"가 주어진다.

공유 히스토리 push/replace 단계 ([HTML]에 정의된 바와 같이)에서, URL이 갱신된 후, 동일 문서 커밋을 처리한다. 이때 Document, 새 URL, 그리고 작업 타입("push" 또는 "replace" 중 하나)이 주어진다.

6.2.2. 하드 내비게이션

Window가 생성될 때(예: "hard" 내비게이션 중), 그 current navigation id§ 2.1 Navigation ID에 명시된 대로 초기화된다.

[NAVIGATION-TIMING]에서, 초기 내비게이션을 위한 PerformanceNavigationTiming entry를 생성할 때, 사용자 에이전트는 그 navigationIdWindowcurrent navigation id로 설정해야 한다.

6.3. Event Timing 통합

이 명세는 최신 웹 애플리케이션 및 단일 페이지 애플리케이션과 관련된 추가 이벤트 타입을 포함하도록 [EVENT-TIMING]의 상호작용 정의를 확장한다.

다음 이벤트 타입은 상호작용의 일부로 간주된다([EVENT-TIMING]에 정의된 바와 같이):

이러한 이벤트가 사용자 상호작용의 결과로 디스패치될 때, 사용자 에이전트는 문서의 관련 전역 객체에 대해 다음 interactionId를 가져와 얻은 고유한 interactionId를 이 이벤트들에 할당해야 한다. 이벤트가 이미 할당된 interactionId를 가진 이전 상호작용에 의해 트리거된 경우, 사용자 에이전트는 동일한 식별자를 재사용해야 한다.

참고: 이러한 이벤트는 사용자 동작에서 시작된 이벤트인 경우에만 기본 상호작용으로 보고된다 (예: 브라우저 UI의 뒤로 버튼 클릭). 대부분의 다른 시나리오—예를 들어 click 핸들러가 history를 수동으로 조작하는 경우—에서는 이후의 popstate 또는 navigate 이벤트가 독립적인 사용자 상호작용으로 간주되지 않는다.

이러한 프로그래밍 방식으로 트리거된 이벤트에 isTrusted 플래그가 설정되어 있지 않을 수도 있지만, history 및 navigation API가 시작 작업의 비동기 연속으로 처리되므로, [ASYNC-CONTEXT]를 통해 원래 상호작용에 올바르게 귀속된다.

참고: navigate, popstate, 그리고 hashchange 이벤트는 소프트 내비게이션을 추적하고 interactionId를 할당하기 위한 내부 신호로 사용된다. 이 명세는 이러한 이벤트 유형이 PerformanceEventTiming entry로 성능 타임라인에 노출될 것을 요구하지 않으며, 그 결정은 [EVENT-TIMING] 명세에 맡긴다.

참고: [EVENT-TIMING] 명세는 processingStartprocessingEnd 훅을 명시적으로 정의하고, 이 통합에 충분히 이른 시점에 interactionId 할당이 발생하도록 업데이트될 것으로 예상된다. 현재는 interactionId 할당이 일반적으로 이벤트 처리의 끝까지 지연된다.

이 명세는 안전한 전역 카운터를 보장하기 위해 interactionIdunsigned long long을 사용하는 반면, [EVENT-TIMING]은 현재 이를 unsigned long으로 정의한다. 이 불일치는 두 명세의 향후 버전에서 해결될 것으로 예상된다.

Window window에 대해 다음 interactionId 가져오기를 수행하려면:
  1. windowinteraction countwindowinteraction count에 1을 더한 값으로 설정한다.

  2. windowinitial interactionId value에 (windowinteraction countwindowinteractionId increment를 곱한 값)을 더한 값을 반환한다.

[EVENT-TIMING]에 정의된 DOM 명세의 event dispatch 알고리즘에 대한 수정에서:
  1. timingEntryevent timing processing start 초기화 및 기록의 결과로 설정하는 단계 직후에 다음 단계를 실행한다:

    1. timingEntry가 주어졌을 때 event dispatch에 대한 현재 interaction context 설정을 수행한다.

  2. event timing processing end 기록을 호출하는 단계 직전에 다음 단계를 실행한다:

    1. event dispatch 이후 현재 interaction context 해제를 수행한다.

6.4. Paint Timing 통합

이 명세는 [PAINT-TIMING] 명세를 확장하여 상호작용에 의해 수정된 요소에 대한 paint tracking을 재설정하고 렌더링된 문서에 대한 paint attribution을 트리거한다.

mark paint timing을 변경하여, Document document가 주어졌을 때 1단계 이후 다음 단계를 추가한다:
  1. document가 주어졌을 때 document 및 그 자손에 대한 interaction context 갱신을 수행한다.

Mark paint time은 UA가 문서를 페인트하기 전과 후에 와야 하는 단계들을 함께 섞고 있다. 여기서 추가된 단계는 페인트 전에 발생할 것으로 예상된다. [w3c/paint-timing Issue #126]

mark paint timing을 변경하여, Document document, paint timing info paintTimingInfo, ordered setpending image records paintedImages, 그리고 ordered setelements paintedTextNodes가 주어졌을 때, 10.3단계(largest contentful paint 보고) 이후 다음 단계를 추가한다:
  1. document, paintTimingInfo, paintedImages, 그리고 paintedTextNodes가 주어졌을 때 interaction contentful paints 및 soft navigations 보고를 수행한다.

다음 알고리즘을 추가한다:

Node node에 대해 paint tracking 재설정을 수행하려면:
  1. node에 대한 text element tracking을 재설정한다.

  2. node에 대한 image element tracking을 재설정한다.

이는 자리표시자 알고리즘이다. 관련 요소에 대한 repaint를 허용해야 하지만, repaint가 Element Timing 또는 LCP에 영향을 주어서는 안 된다. 텍스트와 이미지는 관련 paint가 발생했는지 감지하는 메커니즘이 다르며, 둘 다 repaint를 지원하도록 업데이트되어야 한다.

다음 알고리즘을 추가한다:

Node node에 대해 attribution element 가져오기를 수행하려면:
  1. nodeText node이면, nodecontaining block을 결정하는 Element를 반환한다.

  2. 그렇지 않으면, node를 반환한다.

6.5. Largest Contentful Paint (LCP) 통합

7. 보안 및 개인정보 보호 고려사항

Soft Navigations를 성능 타임라인에 노출하는 것은 그 자체로 보안 및 개인정보 보호상 영향을 가지지 않습니다. 그러나 감지된 soft navigation의 결과로 다양한 페인트 타이밍 항목을 재설정하는 것은 영향을 가질 수 있으며, 특히 방문한 링크가 분할되기 전에는 더욱 그렇습니다. 따라서 :visited 캐시를 분할하지 않은 상태에서 이러한 페인트 작업을 노출하는 일은, 문제가 되는 페인트 작업이 출처 간에 사용자의 기록을 노출하지 않는지 확인하기 위한 신중한 분석 후에만 이루어져야 합니다.

마찬가지로, 자세한 페인트 타이밍 정보(예: Interaction Contentful Paint를 통해)를 노출하면 맞춤법 또는 문법 오류 장식(::spelling-error 또는 ::grammar-error을 통해)이 적용될 때 페인트 업데이트를 관찰하는 데 잠재적으로 사용될 수 있습니다. 완화 조치가 없는 경우, 이는 공격자가 텍스트 필드의 단어를 프로그래밍 방식으로 순환하며 해당 단어가 사용자의 사전에 존재하는지 확인할 수 있게 할 수 있습니다. 그러나 브라우저는 맞춤법 및 문법 검사가 사용자 상호작용(예: 키 누름 또는 클릭)당 한 번만 발생하도록 제한하여 이를 완화함으로써 사용자 사전 누수를 방지합니다. 타이밍 및 페인트 정보는 다른 표준 API를 통해 이미 개발자가 관찰할 수 있으므로, 이러한 타이밍 항목을 노출한다고 해서 브라우저의 맞춤법/문법 강조 표시 속도 제한에 의해 이미 제약되는 것 이상의 새로운 정보 누수가 도입되지는 않습니다.

8. 부록: 중첩되는 상호작용과 경합 조건

이 절은 비규범적입니다.

웹 애플리케이션은 여러 사용자 상호작용을 빠르게 연속해서 처리하는 경우가 많습니다. 이 명세는 다음 모델을 통해 이러한 중첩되는 상호작용을 처리합니다:

색인

이 명세에서 정의된 용어

참조로 정의된 용어

참조

규범적 참조

[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 4. URL: https://drafts.csswg.org/css-display-4/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[EVENT-TIMING]
Michal Mocny. Event Timing API. URL: https://w3c.github.io/event-timing/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. URL: https://w3c.github.io/hr-time/
[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/
[LARGEST-CONTENTFUL-PAINT]
Yoav Weiss. Largest Contentful Paint. URL: https://w3c.github.io/largest-contentful-paint/
[NAVIGATION-TIMING-2]
Yoav Weiss; Noam Rosenthal. Navigation Timing Level 2. URL: https://w3c.github.io/navigation-timing/
[PAINT-TIMING]
Ian Clelland; Noam Rosenthal. Paint Timing. URL: https://w3c.github.io/paint-timing/
[PERFORMANCE-TIMELINE]
Nicolas Pena Moreno. Performance Timeline. URL: https://w3c.github.io/performance-timeline/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

비규범적 참조

[ASYNC-CONTEXT]
AsyncContext. URL: https://github.com/tc39/proposal-async-context
[CONTAINER-TIMING]
Container Timing API. URL: https://github.com/WICG/container-timing
[NAVIGATION-TIMING]
Zhiheng Wang. Navigation Timing. 2012년 12월 17일. REC. URL: https://www.w3.org/TR/navigation-timing/

IDL 색인

[Exposed=(Window,Worker)]
partial interface PerformanceEntry {
    readonly attribute unsigned long long navigationId;
};

[Exposed=Window]
interface InteractionContentfulPaint : PerformanceEntry {
    readonly attribute LargestContentfulPaint largestContentfulPaint;
    readonly attribute unsigned long long interactionId;

    object toJSON();
};

InteractionContentfulPaint includes PaintTimingMixin;

[Exposed=Window]
interface PerformanceSoftNavigation : PerformanceEntry {
    readonly attribute NavigationType navigationType;
    readonly attribute unsigned long long interactionId;
    InteractionContentfulPaint? getLargestInteractionContentfulPaint();
};

PerformanceSoftNavigation includes PaintTimingMixin;

이슈 색인

이 명세는 안전한 전역 카운터를 보장하기 위해 interactionIdunsigned long long을 사용하는 반면, [EVENT-TIMING]은 현재 이를 unsigned long으로 정의합니다. 이 불일치는 두 명세의 향후 버전에서 해결될 것으로 예상됩니다.
paint 시간 표시는 UA가 문서를 페인트하기 전과 후에 와야 하는 단계들을 함께 섞고 있습니다. 여기서 추가된 단계는 페인트 전에 발생할 것으로 예상됩니다. [w3c/paint-timing Issue #126]
이는 자리표시자 알고리즘입니다. 관련 요소에 대한 repaint를 허용해야 하지만, repaint가 Element Timing 또는 LCP에 영향을 주어서는 안 됩니다. 텍스트와 이미지는 관련 paint가 발생했는지 감지하는 서로 다른 메커니즘을 가지고 있으며, 둘 다 repaint를 지원하도록 업데이트되어야 합니다.