보고 API

W3C 작업 초안,

이 문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2025/WD-reporting-1-20250611/
최신 게시 버전:
https://www.w3.org/TR/reporting-1/
편집자 초안:
https://w3c.github.io/reporting/
이전 버전:
히스토리:
https://www.w3.org/standards/history/reporting-1/
피드백:
GitHub
사양 내 인라인
편집자:
(GitHub)
(Google Inc.)
(Google Inc.)
이전 편집자:
(Google Inc.)
(Google Inc.)

요약

이 문서는 웹 개발자가 오리진에 명명된 보고 엔드포인트 집합을 연결할 수 있도록 하는 범용 보고 프레임워크를 정의합니다. 다양한 플랫폼 기능들이 이러한 엔드포인트를 사용하여 기능별 보고서를 일관된 방식으로 전달할 수 있습니다.

이 문서의 상태

이 섹션은 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인 https://www.w3.org/TR/에서 확인할 수 있습니다.

이 문서는 웹 성능 워킹 그룹에서 작업 초안으로 발행되었으며, 권고안 경로를 따릅니다. 작업 초안으로 발행되었다고 해서 W3C 및 그 회원의 지지를 의미하지는 않습니다.

이 문서는 초안이며 언제든지 업데이트, 대체 또는 다른 문서로 폐기될 수 있습니다. 이 문서를 진행 중인 작업 외의 용도로 인용하는 것은 적절하지 않습니다.

GitHub 이슈에서 이 명세에 대한 논의가 권장됩니다.

이 문서는 2023년 11월 3일 W3C 프로세스 문서에 의해 관리됩니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C는 해당 그룹의 결과물과 관련하여 공개 특허 공개 목록을 유지하며, 해당 페이지에는 특허 공개 방법도 안내되어 있습니다. 실제로 필수 청구권(Essential Claim(s))을 포함한다고 판단되는 특허를 아는 개인은 W3C 특허 정책 6장에 따라 정보를 공개해야 합니다.

1. 소개

이 문서는 범용 보고를 위한 세 가지 인프라를 제공하며, 이는 다른 명세에서 사용하거나 확장할 수 있습니다:

  1. 보고서 유형과 보고 엔드포인트를 정의하는 범용 프레임워크, 그리고 HTTP를 통해 엔드포인트로 보고서를 전송하는 문서 형식.

  2. 문서 또는 워커 내에서 보고 엔드포인트를 구성하고, 해당 문서 또는 워커의 생명주기에 연결된 보고서를 전달할 수 있는 구체적인 메커니즘.

  3. 문서 또는 워커 내에서 생성된 보고서를 관찰하는 JavaScript 인터페이스.

다른 명세들은 예를 들어 구체적인 보고서 유형을 정의하거나, 문서 기반이 아닌 보고서를 위한 대체 구성 또는 전달 메커니즘을 정의하는 방식으로 이 인프라를 확장하거나 활용할 수 있습니다.

1.1. 보장 사항

이 명세는 웹사이트 활동과 분리되어 실행되는 최선의 보고서 전달 시스템을 제공하는 것을 목표로 합니다. 사용자 에이전트는 개별 웹사이트에서는 알 수 없는 크로스 오리진 활동을 파악할 수 있으므로, 보고서 전달의 우선순위와 일정을 더 잘 조정할 수 있고, 웹사이트 자체가 처음부터 로딩되지 못하게 하는 오류 조건에 따라 보고서를 전달할 수 있습니다.

그러나 보고서의 전달은 어떠한 방식으로도 보장되지 않으며, 보고는 신뢰할 수 있는 통신 채널로 사용되어서는 안 됩니다. 네트워크 환경에 따라 보고서가 목적지에 도달하지 못할 수 있으며, 사용자 에이전트는 어떠한 이유로든 보고서를 거부하고 전달하지 않을 수 있습니다.

1.2. 예시

MegaCorp Inc.는 콘텐츠 보안 정책(CSP) 및 키 핀 위반 보고서를 수집하고 싶어 합니다. 이를 위해 다음과 같은 헤더를 전달하여 "endpoint-1"이라는 이름의 보고 엔드포인트 집합을 정의할 수 있습니다:
Reporting-Endpoints: endpoint-1="https://example.com/reports"

그리고 다음 헤더들은 CSP와 HPKP 보고서를 해당 엔드포인트로 보내도록 지시합니다:

Content-Security-Policy: ...; report-to endpoint-1
Public-Key-Pins: ...; report-to=endpoint-1
일정 기간 보고서를 처리한 후, MegaCorp Inc.는 두 종류의 보고서 처리를 각각의 별도 엔드포인트로 분리하여 처리 스크립트를 더 간단하게 만들기로 결정합니다. 이를 위해 두 개의 보고 엔드포인트를 정의하는 다음 헤더를 전달할 수 있습니다:
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports",
                     hpkp-endpoint="https://example.com/hpkp-reports"

그리고 다음 헤더들은 CSP와 HPKP 보고서를 각각의 엔드포인트로 보내도록 지시합니다:

Content-Security-Policy: ...; report-to csp-endpoint
Public-Key-Pins: ...; report-to=hpkp-endpoint

2. 범용 보고 프레임워크

이 섹션에서는 보고서와 엔드포인트의 일반적인 개념, 그리고 보고서를 application/reports+json 형식으로 직렬화하는 방법을 정의합니다.

2.1. 개념

2.1.1. 엔드포인트

엔드포인트는 특정 보고서가 특정 오리진으로 전송될 수 있는 위치입니다.

엔드포인트는 ASCII 문자열인 name을 가집니다.

엔드포인트URLurl을 가집니다.

엔드포인트는 요청에 응답하지 못한 연속 횟수를 나타내는 0 이상의 정수 failures를 가집니다.

2.1.2. 보고서 유형

보고서 유형보고서 본문에 포함된 데이터 집합을 지정하는 비어 있지 않은 문자열입니다.

보고서 유형이 정의될 때(이 명세나 다른 명세에서), ReportingObserver에 표시됨으로 지정할 수 있습니다. 이는 해당 유형의 보고서보고 옵저버가 관찰할 수 있음을 의미합니다. 기본적으로 보고서 유형ReportingObserver에 표시되지 않음 상태입니다.

2.1.3. 보고서

보고서는 사용자 에이전트가 지정된 엔드포인트로 전달해야 하는 임의의 데이터 집합입니다.

보고서본문을 가지며, 이는 null이거나 JSON 텍스트로 직렬화할 수 있는 객체입니다. 보고서본문에 포함되는 필드는 보고서유형에 따라 결정됩니다.

보고서url을 가지며, 이는 일반적으로 보고서가 생성된 Document 또는 Worker의 주소입니다.

참고: 직렬화된 URL에서 사용자명, 비밀번호, 프래그먼트는 제거됩니다. § 8.1 Capability URLs 참고.

보고서user agent 값을 가지며, 이는 보고서가 생성된 요청User-Agent 헤더 값입니다.

참고: 보고서의 user agent는 보고서를 생성한 페이지에서 브라우저가 보낸 User-Agent를 나타냅니다. 이는 보고서를 수집기에 업로드할 때 HTTP 헤더로 전송되는 User-Agent와 다를 수 있습니다. 예를 들어, 브라우저가 "데스크톱 사이트 요청" 기능처럼 기본값이 아닌 User-Agent 문자열을 선택한 경우입니다.

보고서destination을 가지며, 이는 보고서가 전송될 엔드포인트name을 나타내는 문자열입니다.

보고서type을 가지며, 이는 보고서 유형입니다.

보고서timestamp 값을 가지며, 이는 보고서가 생성된 시간을 유닉스 에포크 이후 밀리초 단위로 기록합니다.

보고서attempts 카운터를 가지며, 이는 사용자 에이전트가 보고서 전달을 시도한 횟수를 나타내는 0 이상의 정수입니다.

2.2. 미디어 타입

보고서를 지정된 엔드포인트로 POST할 때 사용하는 미디어 타입은 application/reports+json입니다.

2.3. datatype으로 destination에 큐잉

직렬화 가능한 객체(data), 문자열(type), 또 다른 문자열(destination), 선택적 environment settings object(settings), 선택적 URL(url)을 받아 보고서를 생성하려면:

  1. report를 새 보고서 객체로 만들고, 각 값을 다음과 같이 초기화합니다:

    body

    data

    user agent

    현재 navigator.userAgent

    destination

    destination

    type

    type

    timestamp

    현재 타임스탬프

    attempts

    0

  2. url이 호출자에 의해 제공되지 않았다면, urlsettingscreation URL로 설정합니다.

  3. urlusername을 빈 문자열로, passwordnull로 설정합니다.

  4. reporturlurl에 대해 URL serializer를 프래그먼트 제외 플래그를 켜고 실행한 결과로 설정합니다.

  5. report를 반환합니다.

참고: 보고 옵저버는 동일한 environment settings object에서만 보고서를 관찰할 수 있습니다.

참고: 보고서의 직렬화된 URL에서는 사용자명, 비밀번호, 프래그먼트가 제거됩니다. § 8.1 Capability URLs 참고.

참고: 사용자 에이전트는 어떠한 이유로든 보고서를 거부할 수 있습니다. 이 API는 예를 들어 임의의 양의 데이터 전달을 보장하지 않습니다.

참고: JavaScript 엔진이 없는 비 사용자 에이전트 클라이언트는 보고 옵저버와 상호작용하지 않아야 하며, 따라서 6단계에서 반환해야 합니다.

2.4. 보고서 직렬화

reports 목록을 JSON으로 직렬화하려면,

  1. collection을 빈 리스트로 초기화합니다.

  2. reports의 각 report에 대해:

    1. 다음 키/값 쌍으로 data 맵을 만듭니다:

      age

      reporttimestamp와 현재 시간 간의 밀리초 차이

      type

      reporttype

      url

      reporturl

      user_agent

      reportuser agent

      body

      reportbody

      참고: 클라이언트의 시계는 신뢰할 수 없으며 스큐가 존재할 수 있습니다. 따라서 절대 타임스탬프 대신 age 속성을 제공합니다. § 9.2 클록 스큐도 참고하세요.

    2. reportattempts를 증가시킵니다.

    3. datacollection에 추가합니다.

  3. collection에 대해 바이트 시퀀스를 반환합니다. 이때 Infra 값을 JSON 바이트로 직렬화를 실행합니다.

3. 문서 중심 보고

이 섹션은 문서(또는 워커 스크립트) 내 동작으로 생성된 보고서에 대한 보고 엔드포인트를 구성하는 메커니즘을 정의합니다. 해당 보고서는 생성된 문서 또는 워커의 생명주기에 연결되어 있습니다.

3.1. 문서 구성

WindowOrWorkerGlobalScope를 구현하는 각 객체는 endpoints 리스트를 가지며, 이는 엔드포인트들의 리스트이고, 각 엔드포인트는 반드시 고유한 name을 가져야 합니다. (고유성은 § 3.3 응답에 대한 보고 엔드포인트 처리 알고리즘에서 보장됩니다.)

WindowOrWorkerGlobalScope를 구현하는 각 객체는 reports 리스트를 가지며, 이는 보고서들의 리스트입니다.

글로벌의 엔드포인트 리스트 초기화를 위해 WindowOrWorkerGlobalScope (scope)와 response (response)가 주어지면, scopeendpointsresponse에 대해 § 3.3 응답에 대한 보고 엔드포인트 처리를 실행한 결과로 설정합니다.

서버는 반환하는 문서 또는 워커 스크립트 리소스에 대해 Reporting-Endpoints HTTP 응답 헤더 필드를 통해 보고 엔드포인트 집합을 정의할 수 있습니다. 이 메커니즘은 § 3.2 Reporting-Endpoints HTTP 응답 헤더 필드에서 정의되며, 처리 방식은 § 3.3 응답에 대한 보고 엔드포인트 처리에서 설명합니다.

Reporting-Endpoints HTTP 응답 헤더 필드의 값은 리소스의 보고 구성 생성에 사용됩니다.

Reporting-Endpoints는 Dictionary Structured Field [STRUCTURED-FIELDS]입니다. 딕셔너리의 각 항목은 보고서가 전달될 수 있는 엔드포인트를 정의합니다. 각 항목의 값은 반드시 문자열이어야 합니다.

엔드포인트는 String Item으로 정의되며 URI 참조로 해석됩니다. 값이 유효한 URI 참조가 아니면 해당 엔드포인트 멤버는 무시해야 합니다.

또한 해당 멤버가 나타내는 URL은 잠재적으로 신뢰할 수 있어야 합니다 [SECURE-CONTEXTS]. 비보안 엔드포인트는 무시됩니다.

엔드포인트에 대해 정의된 파라미터는 없으며, 지정된 파라미터는 무시됩니다.

헤더는 아래 ABNF 문법으로 표현됩니다 [RFC5234]:

Reporting-Endpoints = sf-dictionary

3.3. 응답에 대한 보고 엔드포인트 처리

response (response)가 주어지면, 이 알고리즘은 엔드포인트들의 리스트를 추출하여 반환합니다.

  1. responseHTTPS state가 "modern"이 아니고, responseurlorigin신뢰할 수 없음이면, 이 절차를 중단합니다.

  2. parsed headerresponseheader list에서 "Reporting-Endpoints"와 "dictionary"로 get a structured field value를 실행한 결과로 설정합니다.

  3. parsed header가 null이면, 이 절차를 중단합니다.

  4. endpoints를 빈 리스트로 설정합니다.

  5. parsed header의 각 namevalue_and_parameters에 대해:

    1. endpoint url string을 튜플 value_and_parameters의 첫 번째 요소로 설정합니다. endpoint url string이 문자열이 아니면, 다음으로 진행합니다.

    2. endpoint urlendpoint url string에 대해 URL 파서responseurl을 기준(base URL)으로 실행한 결과로 설정합니다. endpoint url이 실패이면, 다음으로 진행합니다.

    3. endpoint urlorigin신뢰할 수 없음이면, 다음으로 진행합니다.

    4. endpoint를 새로운 엔드포인트로 생성하고, 속성을 다음과 같이 설정합니다:

      name

      name

      url

      endpoint url

      failures

      0

    5. endpointendpoints에 추가합니다.

  6. endpoints를 반환합니다.

3.4. 보고서 생성

3.4.1. typedata로 보고서 생성

사용자 에이전트가 Document 또는 WorkerGlobalScope 객체(context)에 대해, 문자열(type), 문자열(destination), 직렬화 가능한 객체(data)가 주어지면, 아래 절차를 실행해야 합니다:

  1. settingscontextrelevant settings object로 설정합니다.

  2. report보고서 생성data, type, destination, settings으로 실행한 결과로 설정합니다.

  3. settings가 주어졌다면,

    1. scopesettingsglobal object로 설정합니다.

    2. scopeWindowOrWorkerGlobalScope를 구현하는 객체라면, § 4.2 scope 및 report로 보고 옵저버 알림scopereport로 실행합니다.

  4. reportcontextreports에 추가합니다.

3.5. 보고서 전달

시간이 지나면서 다양한 기능들이 문서와 워커에 보고서 리스트를 큐에 쌓게 됩니다. 사용자 에이전트는 주기적으로 현재 큐에 있는 보고서 리스트를 가져와 연관된 엔드포인트로 전달합니다. 이 문서는 사용자 에이전트가 따라야 할 일정을 정의하지 않으며, 사용자 에이전트가 보고서를 적절한 시기에 전달할 만큼 충분한 컨텍스트 정보를 가지고 있다고 가정합니다. 이는 사용자의 경험에 영향을 주지 않도록 균형을 맞춰야 합니다.

그렇지만, 사용자 에이전트는 큐잉 직후 가능한 빠르게 보고서를 전달해야 하며, 보고서의 데이터는 생성 직후 기간 내에 훨씬 더 유용할 수 있습니다.

3.5.1. 보고서 전송

사용자 에이전트는 WindowOrWorkerGlobalScope 객체(context)에 대해 보고서 리스트(reports)를 아래 절차로 전송합니다:

  1. endpoint map엔드포인트 객체를 키로 하고 보고서 객체 리스트를 값으로 하는 빈 맵으로 설정합니다.

  2. reports의 각 report에 대해:

    1. contextendpoints 리스트 중 namereportdestination과 같은 엔드포인트(endpoint)가 존재한다면:

      1. reportendpoint mapendpoint에 대한 보고서 리스트에 추가합니다.

      2. 그렇지 않으면 reportreports에서 제거합니다.

  3. endpoint map의 각 (endpoint, report list) 쌍에 대해:

    1. origin maporigin을 키로 하고 보고서 객체 리스트를 값으로 하는 빈 맵으로 설정합니다.

    2. report list의 각 report에 대해:

      1. originreportorigin으로, url에서 추출합니다.

      2. reportorigin maporigin에 대한 보고서 리스트에 추가합니다.

    3. origin map의 각 (origin, per-origin reports) 쌍에 대해, 아래 절차를 비동기적으로 실행합니다:

      1. result§ 3.5.2 보고서를 엔드포인트로 전달 시도endpoint, origin, per-origin reports로 실행한 결과로 설정합니다.

      2. result가 "Failure"이면:

        1. endpointfailures를 증가시킵니다.

      3. result가 "Remove Endpoint"이면:

        1. contextendpoints 리스트에서 endpoint를 제거합니다.

      4. reportreports에서 제거합니다.

      실패한 보고서에 대한 재전송 메커니즘은 명시되어 있지 않습니다. 여기에 추가하거나, 전달 실패를 나타내는 방법을 제공할 필요가 있습니다.

참고: 사용자 에이전트는 수집된 보고서 또는 엔드포인트의 일부만 전달을 시도하기로 결정할 수 있습니다(예: 모든 보고서를 한 번에 전송하면 과도한 대역폭이 소모될 경우 등). 보고서는 전달 시도가 완료된 후에만 캐시에서 제거되므로, 건너뛴 보고서는 이후에 전달됩니다.

3.5.2. reportsendpoint에 전달 시도

엔드포인트 (endpoint), origin (origin), 보고서 리스트(reports)가 주어지면, 이 알고리즘은 request를 생성하여 endpoint로 전달을 시도합니다. 전달이 성공하면 "Success"를 반환하고, 엔드포인트가 410 응답으로 스스로를 보고 엔드포인트에서 제거하면 "Remove Endpoint"를 반환하며, 그 외에는 "Failure"를 반환합니다.

  1. bodyreports에 대해 보고서 리스트를 JSON으로 직렬화를 실행한 결과로 설정합니다.

  2. request를 아래 속성으로 새로운 request로 생성합니다 [FETCH]:

    method

    "POST"

    url

    endpointurl

    origin

    origin

    header list

    header list를 새로 생성하고, header 이름은 `Content-Type`, 값은 `application/reports+json`로 설정합니다.

    client

    null

    window

    "no-window"

    service-workers mode

    "none"

    initiator

    ""

    destination

    "report"

    mode

    "cors"

    unsafe-request flag

    설정됨

    credentials

    "same-origin"

    body

    body이며, sourcebody입니다.

    참고: 보고서는 credentials가 same-origin으로 설정되어 전송됩니다. 이는 보고 페이지와 동일 오리진의 보고 엔드포인트가 보고서의 성격에 대한 추가 정보를 얻을 수 있게 하며, 예를 들어 특정 사용자의 계정이 지속적으로 오류를 발생시키는지, 또는 다른 페이지에서 특정 행동이 이 페이지의 보고서를 트리거하는지를 파악할 수 있습니다. 이는 보고 엔드포인트가 다른 방법으로도 얻을 수 있는 정보를 누설하지 않습니다. 크로스 오리진 보고 엔드포인트는 credentials를 받지 않습니다.

  3. 작업 큐에 추가하여 fetch request를 실행합니다.

  4. 응답 대기(response).

  5. responsestatusOK 상태 (200-299)이면, "Success" 반환.

  6. responsestatus410 Gone [RFC9110]이면, "Remove Endpoint" 반환.

  7. "Failure" 반환.

3.6. 보고서에 사용할 URL 스트립

보고서에 사용할 URL 스트립을 위해 URL url이 주어지면, 아래 절차를 수행합니다. 결과는 보고서에 사용할 URL을 나타내는 문자열입니다.
  1. urlschemeHTTP(S) scheme이 아니면, urlscheme을 반환합니다.

  2. urlfragment를 빈 문자열로 설정합니다.

  3. urlusername을 빈 문자열로 설정합니다.

  4. urlpassword를 빈 문자열로 설정합니다.

  5. url에 대해 URL serializer를 실행한 결과를 반환합니다.

4. 보고 옵저버

보고 옵저버는 자바스크립트에서 일부 보고서 유형을 관찰하며, 자바스크립트에서는 ReportingObserver 객체로 표현됩니다.

WindowOrWorkerGlobalScope를 구현하는 각 객체는 등록된 보고 옵저버 리스트를 가지며, 이는 순서가 지정된 집합 형태의 보고 옵저버 집합입니다.

보고 옵저버등록된 보고 옵저버 리스트에 포함되어 있으면 등록됨으로 간주됩니다.

WindowOrWorkerGlobalScope를 구현하는 각 객체는 보고 버퍼를 가지며, 이는 해당 WindowOrWorkerGlobalScope에서 생성된 보고서 리스트입니다. 이 리스트는 처음에는 비어 있으며, 보고서가 생성된 순서대로 저장됩니다.

참고: 보고 버퍼의 목적은 보고 옵저버가 나중에 생성될 때, 그 이전에 생성된 보고서를 buffered 옵션을 통해 관찰할 수 있도록 하기 위함입니다. 예를 들어, 일부 보고서는 페이지 로딩의 초기 단계에서 생성될 수 있는데, 이때 옵저버가 처음 생성될 수 있거나, 보고서를 관찰하고자 하는 자바스크립트 라이브러리가 로드되기 전에 생성될 수 있습니다.

참고: 보고 옵저버는 자바스크립트 엔진이 있는 사용자 에이전트에서만 관련이 있습니다.

4.1. 인터페이스 ReportingObserver

dictionary ReportBody {
};

dictionary Report {
  DOMString type;
  DOMString url;
  ReportBody? body;
};

[Exposed=(Window,Worker)]
interface ReportingObserver {
  constructor(ReportingObserverCallback callback, optional ReportingObserverOptions options = {});
  undefined observe();
  undefined disconnect();
  ReportList takeRecords();
};

callback ReportingObserverCallback = undefined (sequence<Report> reports, ReportingObserver observer);

dictionary ReportingObserverOptions {
  sequence<DOMString> types;
  boolean buffered = false;
};

typedef sequence<Report> ReportList;

Report보고서의 응용프로그램 노출 표현입니다.

ReportBody는 구체적인 보고서 유형이 상속해야 하는 추상 dictionary 타입입니다.

ReportingObserver 객체는 다음과 같은 연관된 개념을 가집니다:

ReportListReport들의 시퀀스를 나타내며, 개발자에게 자바스크립트 배열의 모든 편의 메서드를 제공합니다.

ReportingObserver(callback, options) 생성자가 호출되면, 아래 절차를 실행합니다:

  1. ReportingObserver 객체 observer를 생성합니다.

  2. observercallbackcallback으로 설정합니다.

  3. observeroptionsoptions로 설정합니다.

  4. observer를 반환합니다.

observe() 메서드가 호출되면, 아래 절차를 실행합니다:

  1. global관련 글로벌 객체로 설정합니다.

  2. thisglobal등록된 보고 옵저버 리스트에 추가합니다.

  3. thisbuffered 옵션이 false이면 반환합니다.

  4. thisbuffered 옵션을 false로 설정합니다.

  5. global보고 버퍼의 각 report에 대해 작업 큐에 추가하여 § 4.3 보고서를 옵저버에 추가reportthis로 실행합니다.

disconnect() 메서드가 호출되면, 아래 절차를 실행합니다:

  1. this등록됨이 아니면 반환합니다.

  2. global관련 글로벌 객체로 설정합니다.

  3. thisglobal등록된 보고 옵저버 리스트에서 제거합니다.

takeRecords() 메서드가 호출되면, 아래 절차를 실행합니다:

  1. reportsthis보고서 큐의 복사본으로 설정합니다.

  2. this보고서 큐를 비웁니다.

  3. reports를 반환합니다.

4.2. scopereport로 보고 옵저버 알림

이 알고리즘은 지정된 WindowOrWorkerGlobalScope등록된 보고 옵저버들에게 report의 내용을 제공합니다.

  1. scope에 등록된 각 ReportingObserver observer에 대해 § 4.3 보고서를 옵저버에 추가reportobserver로 실행합니다.

  2. reportscope보고 버퍼에 추가합니다.

  3. typereporttype으로 설정합니다.

  4. scope보고 버퍼typetype인 보고서가 100개를 초과하면, typetype인 가장 오래된 항목을 보고 버퍼에서 제거합니다.

4.3. reportobserver에 추가

report reportReportingObserver observer가 주어지면, reporttypeobserver에서 관찰 가능한 경우에만 observer보고서 큐report를 추가합니다.

  1. reporttypeReportingObserver에 표시됨이 아니면 반환합니다.

  2. observeroptionstypes 멤버가 비어 있지 않고, reporttype을 포함하지 않으면 반환합니다.

  3. Report r을 생성하고, typereporttype, urlreporturl, bodyreportbody로 초기화합니다.

body를 다형적으로 어떻게 초기화할지?

  1. robserver보고서 큐에 추가합니다.

  2. observer보고서 큐의 크기가 1이면:

    1. globalobserver관련 글로벌 객체로 설정합니다.

    2. 작업 큐에 추가하여 § 4.4 notify list로 보고 옵저버 호출global등록된 보고 옵저버 리스트 복사본으로 실행합니다.

4.4. notify list로 보고 옵저버 호출

이 알고리즘은 이전에 관찰된 행동의 보고서에 대해 옵저버 콜백 함수를 호출합니다.

  1. notify list의 각 ReportingObserver observer에 대해:

    1. observer보고서 큐가 비어 있으면, 다음으로 진행합니다.

    2. reportsobserver보고서 큐의 복사본으로 설정합니다.

    3. observer보고서 큐를 비웁니다.

    4. 콜백 함수 호출observercallback에 대해 « reports, observer » 및 "report"와 함께, observer콜백 this 값으로 실행합니다.

5. 구현 고려 사항

5.1. 전달

사용자 에이전트는 개발자에게 가능한 빠르게 피드백을 제공하기 위해 보고서를 최대한 신속히 전달하려고 시도해야 합니다(SHOULD). 그러나 이러한 요구가 사용자의 경험에 영향을 미칠 때는 사용자의 경험이 우선입니다. 이를 고려하여, 사용자 에이전트는 사용자의 활동 및 상황에 따라 보고서 전달을 지연할 수 있습니다(MAY).

예를 들어, 사용자 에이전트는 보고 데이터의 전송 우선순위를 다른 네트워크 트래픽보다 낮게 설정해야 합니다(SHOULD). 사용자가 웹사이트에서 수행하는 명시적 활동이 보고 트래픽보다 우선해야 합니다.

사용자 에이전트는 불필요한 데이터 비용을 방지하기 위해 사용자가 빠르고 저렴한 네트워크에 있을 때까지 보고서 전달을 완전히 보류할 수 있습니다(MAY).

사용자 에이전트는 특정 오리진(예: 사용자가 자주 방문하는 오리진)의 보고서를 다른 오리진보다 우선적으로 전달할 수 있습니다(MAY).

5.2. 가비지 컬렉션

사용자 에이전트는 주기적으로 캐시에 저장된 보고서엔드포인트를 점검하여, 더 이상 관련 없는 항목을 폐기해야 합니다(SHOULD). 해당 항목에는 다음이 포함됩니다:

폐기된 보고서보고서 리스트뿐만 아니라, 모든 보고 버퍼보고 옵저버에서도 제거해야 합니다.

6. 샘플 보고서

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

이 예시는 사용자 에이전트가 보고 엔드포인트로 보고서를 전송할 때의 형식을 보여줍니다. 샘플 제출에는 세 개의 보고서가 함께 묶여 하나의 HTTP 요청으로 전송됩니다. (보고서 유형과 본문 자체는 실제 기능을 나타내지 않으며, 이 명세의 범위 밖입니다).

POST / HTTP/1.1
Host: example.com
...
Content-Type: application/reports+json

[{
  "type": "security-violation",
  "age": 10,
  "url": "https://example.com/vulnerable-page/",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "body": {
    "blocked": "https://evil.com/evil.js",
    "policy": "bad-behavior 'none'",
    "status": 200,
    "referrer": "https://evil.com/"
  }
}, {
  "type": "certificate-issue",
  "age": 32,
  "url": "https://www.example.com/",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "body": {
    "date-time": "2014-04-06T13:00:50Z",
    "hostname": "www.example.com",
    "port": 443,
    "effective-expiration-date": "2014-05-01T12:40:50Z",
    "served-certificate-chain": [
      "-----BEGIN CERTIFICATE-----\n
      MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\n
      ...
      HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto\n
      WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6\n
      yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx\n
      -----END CERTIFICATE-----",
      ...
    ]
  }
}, {
  "type": "cpu-on-fire",
  "age": 29,
  "url": "https://example.com/thing.js",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "body": {
    "temperature": 614.0
  }
}]

7. 자동화

사용자 에이전트 자동화 및 애플리케이션 테스트 목적을 위해, 이 문서는 확장 명령[WebDriver] 명세에 정의합니다.

7.1. 테스트 보고서 생성

테스트 보고서 생성 확장 명령은 테스트 목적을 위해 보고서 생성을 시뮬레이션합니다. 이 보고서는 모든 등록된 보고 옵저버에서 관찰됩니다.

확장 명령은 다음과 같이 정의됩니다:

dictionary GenerateTestReportParameters {
  required DOMString message;
  DOMString group = "default";
};
HTTP Method URI Template
POST /session/{session id}/reporting/generate_test_report

remote end steps은 다음과 같습니다:

  1. parameters가 JSON 객체가 아니면, WebDriver 오류WebDriver 오류 코드 invalid argument를 반환합니다.

  2. message시도(try)하여 parametersmessage 속성 값을 얻습니다.

  3. message가 없으면 WebDriver 오류WebDriver 오류 코드 invalid argument를 반환합니다.

  4. 현재 브라우징 컨텍스트가 더 이상 열려있지 않으면, WebDriver 오류WebDriver 오류 코드 no such window를 반환합니다.

  5. 사용자 프롬프트 처리를 실행하고 결과가 WebDriver 오류라면 해당 값을 반환합니다.

  6. groupparametersgroup 속성 값으로 설정합니다.

  7. bodyJSON 텍스트로 직렬화할 수 있는 새 객체로 설정하고, 단일 문자열 필드 body_message를 포함합니다.

  8. body_messagemessage 값으로 설정합니다.

  9. settingsenvironment settings object로, 현재 브라우징 컨텍스트활성 문서에서 가져옵니다.

  10. 보고서 생성 및 큐잉body, "test", group, settings으로 실행합니다.

  11. 성공과 data null을 반환합니다.

8. 보안 고려 사항

8.1. Capability URL

일부 URL은 그 자체로 가치가 있습니다. 사용자명과 비밀번호 부분에 명시적 자격증명이 포함되어 있을 수 있고, URL 경로를 알기만 해도 리소스에 접근할 수 있는 경우가 있습니다. 또한 URL 프래그먼트에 사용자의 브라우저를 벗어나서는 안 되는 정보가 포함될 수 있습니다. 자세한 내용은 [CAPABILITY-URLS]를 참고하세요.

이러한 URL이 보고 메커니즘을 통해 유출되는 가능성을 완화하기 위해, 본 명세의 알고리즘에서는 보고서에 포함된 URL에서 자격증명 정보와 프래그먼트 데이터를 제거합니다. 하지만 URL 경로에 민감한 정보가 포함된 경우는 여전히 유출될 수 있습니다. 이러한 URL을 사용하는 사이트는 자체 보고 엔드포인트를 운영해야 할 수도 있습니다.

또한 보고서의 본문에도 이러한 URL이 포함될 수 있습니다. 이 API를 확장하는 명세에서 보고서의 본문에 URL이 포함된다면, 마찬가지로 해당 정보도 제거해야 합니다(SHOULD).

9. 프라이버시 고려 사항

9.1. 네트워크 누출

페이지가 로드된 후 보고서가 생성되어 전송되기까지 지연이 있기 때문에, 사용자가 한 네트워크에 있을 때 생성된 보고서가 다른 네트워크에서 전송될 수 있습니다.

이 동작은 보고서를 생성한 문서의 생명주기 동안으로 제한되지만, 해당 문서는 navigator.sendBeacon과 같은 다른 방법을 통해 새 네트워크에서 트래픽을 생성할 수 있습니다(문서가 닫힌 이후에도).

대응책을 고려해야 합니다. 예를 들어, 네트워크가 변경되면 보고서를 폐기할 수도 있습니다. [WICG/background-sync Issue #107]

9.2. 클록 스큐

각 보고서는 생성된 시점의 타임스탬프가 아니라 age 속성과 함께 전달됩니다. 이는 각 사용자의 로컬 시계가 서버의 시계와 임의의 차이를 가질 수 있기 때문입니다. 보고서가 생성된 시간과 전송된 시간의 차이는 클록 스큐와 무관하게 안정적으로 유지되며, 이 API를 통해 클록 스큐가 노출되는 지문 위험을 방지할 수 있습니다.

9.3. 크로스 오리진 상관관계

여러 오리진이 동일한 보고 엔드포인트를 사용하면, 해당 엔드포인트는 특정 사용자가 어떤 웹사이트와 상호작용했는지 알 수 있습니다. 각 오리진에서 오리진 태그가 붙은 보고서를 받기 때문입니다. 이는 협력적 오리진에서 동일한 정보를 추적할 수 있는 기존 상태보다 더 나쁘지 않으며, <img> 등을 통한 기존의 추적 능력 이상을 제공하지 않습니다.

9.4. 보고 비활성화

보고는 어느 정도 공동체적 문제입니다. 전체적으로 보면 보고서가 전달되는 것이 모두에게 유용해 보입니다. 개발자에게 직접적인 이점이 있으며, 버그를 고치면 사용자가 즐기는 사이트가 더 안정적이고 쾌적해집니다. 예를 들어, 콘텐츠 보안 정책(CSP)은 사이트의 방어에 구멍이 있을 때 개발자에게 경고함으로써 크로스사이트 스크립팅 공격에 대해 집단 면역 효과를 제공합니다. 버그를 고치면 CSP를 지원하지 않는 사용자 에이전트의 사용자까지 도움을 받습니다.

물론, 전달되는 데이터의 성격과 보고 엔드포인트의 악의성에 따라 상황이 달라지지만, 넓은 의미에서 이것이 본 명세의 가치 제안입니다.

그렇다 하더라도, 이러한 일반적인 이점이 사용자가 개별적으로 이러한 시스템을 옵트아웃할 수 있는 능력보다 우선시되어서는 안 됩니다. 보고서를 전송하면 대역폭이 소모되고, 웹사이트가 인밴드로 얻을 수 있는 정보보다 약간 더 많은 정보가 노출될 수 있습니다([NETWORK-ERROR-LOGGING] 등). 사용자 에이전트는 [HTML-DESIGN-PRINCIPLES]의 우선순위 원칙을 지키기 위해 사용자가 적절한 수준으로 보고를 비활성화할 수 있도록 반드시 해야 합니다(MUST).

10. IANA 고려 사항

10.1. Reporting-Endpoints 헤더

영구 메시지 헤더 필드 등록부는 아래 등록 정보로 업데이트되어야 합니다 [RFC3864]

헤더 필드 이름

Reporting-Endpoints

적용 프로토콜

http

상태

standard

작성자/변경 컨트롤러

W3C

명세 문서

이 명세 (§ 3.2 Reporting-Endpoints HTTP 응답 헤더 필드 참고)

10.2. application/reports+json 미디어 타입

타입 이름

application

서브타입 이름

reports+json

필수 파라미터

N/A

선택 파라미터

N/A

인코딩 고려 사항

인코딩 고려 사항은 "application/json" 미디어 타입과 동일합니다. [RFC8259] 참고.

보안 고려 사항

§ 8 보안 고려 사항 참고.

상호운용성 고려 사항

이 문서는 메시지의 적합한 형식 및 해석을 명세합니다.

게시된 명세

§ 2.2 미디어 타입

이 미디어 타입을 사용하는 애플리케이션
프래그먼트 식별자 고려 사항
추가 정보

N/A

문의 및 추가 정보 담당자

이 문서의 편집자.

의도된 사용:

COMMON

사용 제한:

N/A

작성자

이 문서의 편집자.

변경 컨트롤러

W3C

임시 등록?

Yes.

색인

이 명세에서 정의한 용어

참조로 정의된 용어

참고 문헌

규범적 참고 문헌

[DOM]
Anne van Kesteren. DOM Standard. 현행 표준. URL: https://dom.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch Standard. 현행 표준. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. 현행 표준. URL: https://infra.spec.whatwg.org/
[RDF12-CONCEPTS]
Olaf Hartig; et al. RDF 1.2 Concepts and Abstract Syntax. 2025년 6월 6일. WD. URL: https://www.w3.org/TR/rdf12-concepts/
[RFC3864]
G. Klyne; M. Nottingham; J. Mogul. Registration Procedures for Message Header Fields. 2004년 9월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc3864
[RFC5234]
D. Crocker, Ed.; P. Overell. Augmented BNF for Syntax Specifications: ABNF. 2008년 1월. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc5234
[RFC8259]
T. Bray, Ed.. The JavaScript Object Notation (JSON) Data Interchange Format. 2017년 12월. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc8259
[RFC9110]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP Semantics. 2022년 6월. Internet Standard. URL: https://httpwg.org/specs/rfc9110.html
[SECURE-CONTEXTS]
Mike West; Yan Zhu. Secure Contexts. URL: https://w3c.github.io/webappsec-secure-contexts/
[STRUCTURED-FIELDS]
Mark Nottingham; Poul-Henning Kamp. Structured Field Values for HTTP. URL: https://www.rfc-editor.org/rfc/rfc8941.html
[URL]
Anne van Kesteren. URL Standard. 현행 표준. URL: https://url.spec.whatwg.org/
[WebDriver]
Simon Stewart; David Burns. WebDriver. 2018년 6월 5일. REC. URL: https://www.w3.org/TR/webdriver1/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. 현행 표준. URL: https://webidl.spec.whatwg.org/

정보성 참고 문헌

[CAPABILITY-URLS]
Jeni Tennison. Good Practices for Capability URLs. 2014년 2월 18일. FPWD. URL: https://www.w3.org/TR/capability-urls/
[CSP3]
Mike West; Antonio Sartori. Content Security Policy Level 3. 2025년 6월 6일. WD. URL: https://www.w3.org/TR/CSP3/
[HTML-DESIGN-PRINCIPLES]
Anne van Kesteren; Maciej Stachowiak. HTML Design Principles. 2007년 11월 26일. WD. URL: https://www.w3.org/TR/html-design-principles/
[NETWORK-ERROR-LOGGING]
Douglas Creager; Ian Clelland. Network Error Logging. 2025년 5월 5일. WD. URL: https://www.w3.org/TR/network-error-logging/
[RFC7469]
C. Evans; C. Palmer; R. Sleevi. Public Key Pinning Extension for HTTP. 2015년 4월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7469

IDL 색인

dictionary ReportBody {
};

dictionary Report {
  DOMString type;
  DOMString url;
  ReportBody? body;
};

[Exposed=(Window,Worker)]
interface ReportingObserver {
  constructor(ReportingObserverCallback callback, optional ReportingObserverOptions options = {});
  undefined observe();
  undefined disconnect();
  ReportList takeRecords();
};

callback ReportingObserverCallback = undefined (sequence<Report> reports, ReportingObserver observer);

dictionary ReportingObserverOptions {
  sequence<DOMString> types;
  boolean buffered = false;
};

typedef sequence<Report> ReportList;

dictionary GenerateTestReportParameters {
  required DOMString message;
  DOMString group = "default";
};

이슈 색인

실패한 보고서에 대한 재전송 메커니즘이 명시되어 있지 않습니다. 여기에 추가하거나, 전달 실패를 나타내는 방법을 제공할 필요가 있습니다.
body를 다형적으로 어떻게 초기화할지?
대응책을 고려해야 합니다. 예를 들어, 네트워크가 변경되면 보고서를 폐기할 수도 있습니다. [WICG/background-sync Issue #107]
MDN

Report/body

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Report/type

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Report/url

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Report

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportBody

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver/ReportingObserver

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver/disconnect

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver/observe

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver/takeRecords

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?