네트워크 오류 로깅

W3C 작업 초안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2025/WD-network-error-logging-20250505/
최신 공개 버전:
https://www.w3.org/TR/network-error-logging/
최신 편집자 초안:
https://w3c.github.io/network-error-logging/
이력:
https://www.w3.org/standards/history/network-error-logging/
커밋 이력
편집자:
Douglas Creager (GitHub)
Ian Clelland (Google)
이전 편집자:
Ilya Grigorik (Google) - 까지
Julia Tuttle (Google) - 까지
Arvind Jain (Google) - 까지
Alois Reitbauer (Compuware Corp.) - 까지
Jatinder Mann (Microsoft) - 까지
피드백:
GitHub w3c/network-error-logging (풀 리퀘스트, 새 이슈, 열린 이슈)

초록

이 문서는 개발자가 웹 애플리케이션에 대한 네트워크 오류 보고 정책을 선언할 수 있도록 하는 메커니즘을 정의합니다. 사용자 에이전트는 이 정책을 사용하여 요청된 리소스를 성공적으로 가져오지 못하게 한 네트워크 오류를 보고할 수 있습니다.

이 문서의 상태

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

이 문서는 웹 성능 작업 그룹에서 권고 표준 절차를 사용하여 작업 초안으로 발행했습니다.

작업 초안으로 발행되었다고 해서 W3C 및 그 회원이 이를 승인했다는 의미는 아닙니다.

이 문서는 초안 문서이며 언제든지 다른 문서에 의해 갱신되거나 대체되거나 폐기될 수 있습니다. 진행 중인 작업 이외의 것으로 이 문서를 인용하는 것은 적절하지 않습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했습니다. W3C는 이 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하며, 해당 페이지에는 특허를 공개하는 방법에 대한 지침도 포함되어 있습니다. 자신이 알고 있는 특허가 필수 청구항을 포함한다고 판단하는 사람은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 합니다.

이 문서는 2023년 11월 3일 W3C 프로세스 문서의 적용을 받습니다.

1. 소개

웹 애플리케이션의 성능 특성을 정확하게 측정하는 것은 사이트 개발자가 웹 애플리케이션을 개선하는 방법을 이해하도록 돕는 데 중요한 요소입니다. 최악의 경우는 네트워크 오류로 인해 애플리케이션이나 특정 리소스를 불러오지 못하는 것이며, 이러한 실패에 대처하려면 개발자는 그러한 실패가 언제, 어디서, 왜 발생하는지 식별할 수 있도록 사용자 에이전트의 지원이 필요합니다.

현재 애플리케이션 개발자는 최종 사용자로부터 실시간 웹 애플리케이션 가용성 데이터를 얻을 수 없습니다. 예를 들어 DNS 조회 실패, 연결 시간 초과, 연결 재설정 또는 기타 원인과 같은 네트워크 오류로 인해 사용자가 페이지를 불러오지 못하면, 사이트 개발자는 이 문제를 감지하고 해결할 수 없습니다. 이러한 종류의 네트워크 오류는 순전히 서버 측에서 감지할 수 없다는 점에 유의하십시오. 정의상 클라이언트가 서버와 성공적으로 연결을 설정하지 못했을 수도 있기 때문입니다.

기존 방법(예: 합성 모니터링)은 미리 정해진 지리적 위치에 모니터링 노드를 배치하여 부분적인 해결책을 제공하지만, 추가적인 인프라 투자가 필요하며 실제 최종 사용자에 대해 진정한 전 세계적이고 거의 실시간인 가용성 데이터를 제공할 수 없습니다.

Network Error Logging(NEL)은 웹 애플리케이션이 특정 오리진에 대한 네트워크 오류를 사용자 에이전트가 보고하는 데 사용할 수 있는 보고 정책을 선언할 수 있도록 하는 메커니즘을 정의하여 이러한 필요를 해결합니다. 웹 애플리케이션은 원하는 NEL HTTP 응답 헤더 필드를 제공하여 NEL 사용에 참여하며, 이 헤더는 원하는 NEL 정책을 설명합니다. 이 정책은 사용자 에이전트에 해당 오리진으로의 요청에 관한 정보를 기록하고, 이전에 Reporting API를 사용하여 구성된 엔드포인트 그룹에 해당 정보를 전달하도록 시도하라고 지시합니다. 이름에서 알 수 있듯이 NEL 보고서는 주로 오류를 설명하는 데 사용됩니다. 그러나 서로 다른 클라이언트 집단에서 오류의 비율을 확인하려면 얼마나 많은 성공적인 요청이 발생하는지도 알아야 하며, 이러한 성공적인 요청 역시 NEL 메커니즘을 통해 보고할 수 있습니다.

예를 들어 중단된 TCP 연결로 인해 사용자 에이전트가 https://www.example.com에서 리소스를 가져오지 못한 경우, 사용자 에이전트는 Reporting API를 통해 다음 보고서를 대기열에 추가합니다.

유형
"network-error"
엔드포인트 그룹
report_to 필드로 구성된 엔드포인트 그룹
데이터
{
  "referrer": "https://referrer.com/",
  "sampling_fraction": 1.0,
  "server_ip": "192.0.2.42",
  "protocol": "http/1.1",
  "elapsed_time": 321,
  "phase": "connection",
  "type": "tcp.aborted"
}

전달되는 필드와 보고서 형식에 대한 설명은 5.4 네트워크 오류 보고서 생성을 참조하고, NEL 등록 및 보고 절차의 보다 실용적인 예제는 7. 예제를 참조하십시오.

2. 적합성

비규범적으로 표시된 절뿐만 아니라 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적입니다. 이 명세의 그 밖의 모든 내용은 규범적입니다.

이 문서에서 핵심 단어 할 수 있습니다, 해야 합니다, 해서는 안 됩니다, 선택 사항, 필수 및 하는 것이 좋습니다는 여기에서 보이는 것처럼 모두 대문자로 표시된 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 합니다.

알고리즘의 일부로 명령형으로 표현된 요구 사항(예: "선행 공백 문자를 모두 제거한다" 또는 "false를 반환하고 이 단계를 중단한다")은 해당 알고리즘을 도입할 때 사용된 핵심 단어("해야 합니다", "하는 것이 좋습니다", "할 수 있습니다" 등)의 의미로 해석해야 합니다.

일부 적합성 요구 사항은 속성, 메서드 또는 객체에 대한 요구 사항으로 표현됩니다. 이러한 요구 사항은 사용자 에이전트에 대한 요구 사항으로 해석해야 합니다.

알고리즘이나 특정 단계로 표현된 적합성 요구 사항은 최종 결과가 동등한 한 어떤 방식으로든 구현할 수 있습니다. (특히 이 명세에서 정의한 알고리즘은 쉽게 따라갈 수 있도록 의도된 것이며, 성능을 높이도록 의도된 것은 아닙니다.)

3. 개념

3.1 네트워크 요청

네트워크 요청은 사용자 에이전트가 주어진 HTTP 네트워크 가져오기를 통해 네트워크에서 리소스를 요청하려고 할 때 발생합니다.

사용자 에이전트가 오프라인인 것으로 알려진 경우(즉, navigator. onLine이 false를 반환하는 경우), 요청은 네트워크 요청으로 이어져서는 안 됩니다.

요청이 네트워크 요청으로 이어져서는 안 됩니다. 혼합 콘텐츠 또는 CORS 실패로 인해 차단된 경우입니다. 모든 CORS 사전 요청은 자체 네트워크 요청으로 이어져야 합니다.

참고

[FETCH] 표준에 따라 요청을 처리하는 사용자 에이전트에서 네트워크 요청은 HTTP 네트워크 가져오기 알고리즘의 한 번의 실행에 해당합니다.

어떤 가져오기 알고리즘과 어떤 기본 애플리케이션 및 전송 프로토콜이 사용되는지와 관계없이, 네트워크 요청을 처리하는 것은 다음 단계로 구성됩니다.

  1. DNS 이름 해석: 사용자 에이전트는 도메인 이름 시스템 [RFC1034]을 사용하여 도메인 이름을 해당 도메인에 대한 HTTP 요청을 처리할 수 있는 서버의 IP 주소로 해석합니다.
  2. 보안 연결 설정: 사용자 에이전트는 서버에 연결을 열고, 이 연결을 통해 보안 채널을 설정합니다.
  3. 요청 및 응답 전송: 보안 채널이 설정되면 사용자 에이전트는 HTTP 요청을 전송하고 응답을 서버에서 받을 수 있습니다.

유일하게 필수인 단계는 요청 및 응답 전송이며, 다른 단계는 모든 네트워크 요청에 필요하지 않을 수도 있습니다. 예를 들어 DNS 결과는 사용자 에이전트에 로컬로 캐시할 수 있으므로 동일한 도메인에 대한 향후 요청에서는 DNS 이름 해석이 필요하지 않습니다. 마찬가지로 HTTP 지속 연결을 사용하면 열린 연결을 동일한 네트워크 파티션 키에 대한 여러 요청이 공유할 수 있습니다. 그러나 여러 단계가 발생하는 경우에는 위의 순서대로 발생합니다.

편집자 참고

이러한 단계의 정의를 [FETCH]로 옮겨 더 폭넓게 재사용할 수 있도록 하고자 합니다.

사용자 에이전트가 서버에서 유효한 HTTP 응답을 받을 수 있고 해당 응답에 4xx 또는 5xx 상태 코드가 없다면, 네트워크 요청은 성공적입니다.

네트워크 요청이 성공적이지 않다면 실패한 것입니다.

참고

HTTP 오류 응답(즉, 4xx 또는 5xx 상태 코드가 있는 응답)은 실패로 간주되므로, NEL 정책의 실패 샘플링 비율이 성공 샘플링 비율 대신 적용된다는 점에 유의하십시오.

3.2 네트워크 오류

네트워크 오류는 네트워크 요청이 실패하게 만든 오류 조건입니다.

각 네트워크 오류에는 문자열인 유형이 있습니다.

각 네트워크 오류에는 오류가 발생한 단계를 설명하는 단계가 있습니다.

dns
오류가 DNS 이름 해석 중에 발생했습니다.
connection
오류가 보안 연결 설정 중에 발생했습니다.
application
오류가 요청 및 응답 전송 중에 발생했습니다.

6. 미리 정의된 네트워크 오류 유형에는 미리 정의된 여러 네트워크 오류 유형이 정의되어 있습니다.

3.3 네트워크 오류 보고서

네트워크 오류 보고서는 네트워크 오류를 설명하는 Reporting API 보고서입니다.

네트워크 오류 보고서의 보고서 유형은 network-error입니다.

네트워크 오류 보고서는 절대로 ReportingObserver에 표시되지 않습니다.

참고

네트워크 오류 보고서가 ReportingObserver에 표시되지 않는 이유는 요청을 수신하는 서버의 관리자 또는 소유자에게만 표시되도록 의도되었기 때문입니다. 이것이 ReportingObserver에 표시된다면, 보고서는 요청의 발신자에게도 표시됩니다. 교차 오리진 요청에서는 서버의 네트워크 구성에 관한 정보가 서버의 통제를 벗어난 당사자에게 유출될 수 있습니다.

3.4 NEL 정책

NEL 정책은 사용자 에이전트에 오리진으로의 네트워크 요청에 관한 보고서를 수집할지 여부와, 수집한다면 어디로 보낼지를 지시합니다. NEL 정책은 HTTP 응답 헤더를 통해 사용자 에이전트에 전달됩니다.

각 NEL 정책에는 수신 IP 주소가 있으며, 이는 사용자 에이전트가 이 NEL 정책을 받은 서버의 IP 주소입니다.

각 NEL 정책에는 오리진이 있습니다.

각 NEL 정책에는 include 또는 exclude인 하위 도메인 플래그가 있습니다.

각 NEL 정책에는 요청 헤더 목록과 응답 헤더 목록이 있으며, 각각은 헤더 이름의 목록입니다.

각 NEL 정책에는 보고 그룹이 있으며, 이는 이 정책에 대한 보고서가 전송될 Reporting 엔드포인트 그룹의 이름입니다.

각 NEL 정책에는 정책이 유효한 초 수를 나타내는 ttl이 있습니다.

각 NEL 정책에는 사용자 에이전트가 정책을 수신한 시각의 타임스탬프인 생성 시각이 있습니다.

생성 시각부터 벽시계의 안전하지 않은 현재 시각까지의 기간이 172800초(48시간)보다 크면 NEL 정책은 오래된 상태입니다.

생성 시각부터 벽시계의 안전하지 않은 현재 시각까지의 기간이 ttl(초 단위)보다 크면 NEL 정책은 만료된 상태입니다.

3.5 샘플링 비율

대량의 트래픽을 처리할 것으로 예상되는 오리진은 해당 오리진으로 이루어지는 모든 네트워크 요청에 대한 NEL 보고서를 수집할 준비가 되어 있지 않을 수 있습니다. 오리진은 각 사용자 에이전트가 제출하는 NEL 보고서 수를 제한하기 위해 샘플링 비율을 정의할 수 있습니다. 일반적으로 성공한 요청의 수가 실패한 요청의 수보다 훨씬 많아야 하므로, 오리진은 각각에 대해 서로 다른 샘플링 비율을 지정할 수 있습니다.

각 NEL 정책에는 0.0 이상 1.0 이하의 숫자인 성공 샘플링 비율이 있습니다.

각 NEL 정책에는 0.0 이상 1.0 이하의 숫자인 실패 샘플링 비율이 있습니다.

3.6 정책 캐시

적합한 사용자 에이전트는 (네트워크 파티션 키, 오리진) 튜플을 키로 하여 NEL 정책 집합을 유지하는 저장 메커니즘인 정책 캐시를 제공해야 합니다.

이 저장 메커니즘은 불투명하고 공급업체별로 다르며 웹에는 노출되지 않지만, 이 문서에서 정의하는 알고리즘에서 사용될 다음 메서드를 제공해야 합니다.

4. 정책 전달

서버는 NEL HTTP 응답 헤더를 통해 자신이 제어하는 오리진에 대한 NEL 정책을 정의할 수 있습니다.

4.1 NEL 응답 헤더

NEL 응답 헤더는 오리진의 NEL 정책을 사용자 에이전트에 전달하는 데 사용됩니다. NEL 헤더에 대한 ABNF(확장 Backus-Naur 형식) [RFC5234] 구문은 다음과 같습니다.

NEL = json-field-value

헤더의 값은 json-field-value에 정의된 JSON 객체 배열로 해석됩니다. 배열의 각 객체는 해당 오리진에 대한 NEL 정책을 정의합니다. 사용자 에이전트는 배열에서 첫 번째 유효한 정책을 처리하고 배열에 있는 추가 정책은 무시해야 합니다.

사용자 에이전트는 이 명세에 정의된 구문을 따르지 않는 알 수 없거나 유효하지 않은 필드 또는 값을 무시해야 합니다. 유효한 NEL 헤더 필드는 최소한 이 명세에서 "필수"로 정의된 모든 필드를 가진 객체 하나를 포함해야 합니다.

사용자 에이전트는 스크립팅 공격을 통한 오류 보고 하이재킹을 완화하기 위해 meta 요소를 통해 지정된 NEL 헤더를 무시해야 합니다. NEL 정책은 NEL 응답 헤더를 통해 전달되어야 합니다.

참고

meta 요소에 대한 제한은 동일한 이유로 보고 등록을 HTTP 헤더 필드로만 제한하는 [CSP] 명세와 일치합니다.

4.1.1 report_to 멤버

report_to 멤버는 이 NEL 정책의 보고서가 전송될 엔드포인트 그룹을 지정합니다. report_to 멤버는 NEL 정책을 등록할 때 필수이며, 이전 등록을 제거하려는 경우에는 선택 사항입니다. max_age를 참조하십시오. 이 멤버가 있으면 그 값은 문자열이어야 합니다. 다른 유형은 구문 분석 오류가 발생합니다.

참고

NEL 보고서의 전달을 개선하려면 서버는 report_to를 리소스를 가져오는 오리진과 인프라가 결합되어 있지 않은 대체 오리진의 엔드포인트을 하나 이상 포함하는 엔드포인트 그룹으로 설정하는 것이 좋습니다. 그렇지 않으면 네트워크 오류는 문제가 해결될 때까지, 혹은 끝내 해결되지 않는 경우 보고될 수 없습니다. 또한 일부 엔드포인트에 접근할 수 없을 때 대안을 제공할 수 있도록 여러 엔드포인트를 제공하는 것이 좋습니다.

4.1.2 max_age 멤버

필수 max_age 멤버는 이 NEL 정책의 수명을 음이 아닌 정수 초 단위로 지정합니다. 그 값은 음이 아닌 정수여야 합니다. 다른 유형은 구문 분석 오류가 발생합니다.

값이 0이면 이 오리진에 대한 모든 NEL 정책이 정책 캐시에서 제거됩니다.

참고

NEL 보고서가 전달되도록 하려면 서버는 Reporting 엔드포인트 그룹에도 충분히 큰 max_age가 설정되어 있는지 확인하는 것이 좋습니다. Reporting 정책이 만료되면 NEL 정책이 아직 만료되지 않았더라도 NEL 보고서는 전달되지 않습니다.

4.1.3 include_subdomains 멤버

선택 사항인 include_subdomains 멤버는 이 오리진의 모든 하위 도메인(하위 도메인 깊이에 제한 없이)에 대해 이 NEL 정책을 활성화하는 불리언입니다. 객체에 include_subdomains라는 멤버가 없거나 그 값이 true가 아니면 NEL 정책은 하위 도메인에 대해 활성화되지 않습니다.

참고

하위 도메인에 대한 NEL 보고서가 전달되도록 하려면 애플리케이션은 Reporting 엔드포인트 그룹에도 include_subdomains가 활성화되어 있는지 확인하는 것이 좋습니다. Reporting 정책에서 활성화되어 있지 않고 특정 하위 도메인에 대한 별도의 Reporting 정책도 없다면, NEL 정책에 해당 하위 도메인이 포함되어 있어도 그 하위 도메인에 대한 NEL 보고서는 전달되지 않습니다.

4.1.4 success_fraction 멤버

선택 사항인 success_fraction 멤버는 이 오리진에 대한 성공한 네트워크 요청에 관한 보고서에 적용해야 하는 샘플링 비율을 정의합니다. 이 멤버가 있으면 그 값은 0.0 이상 1.0 이하의 숫자여야 합니다. 다른 값은 구문 분석 오류가 발생합니다. 이 멤버가 없으면 사용자 에이전트는 이 오리진에 대한 성공한 네트워크 요청에 관한 NEL 보고서를 수집하지 않습니다.

4.1.5 failure_fraction 멤버

선택 사항인 failure_fraction 멤버는 이 오리진에 대한 실패한 네트워크 요청에 관한 보고서에 적용해야 하는 샘플링 비율을 정의합니다. 이 멤버가 있으면 그 값은 0.0 이상 1.0 이하의 숫자여야 하며, 다른 값은 구문 분석 오류가 발생합니다. 이 멤버가 없으면 사용자 에이전트는 이 오리진에 대한 모든 실패한 네트워크 요청에 관한 NEL 보고서를 수집합니다.

4.1.6 request_headers 멤버

선택 사항인 request_headers 멤버는 이 오리진에 관한 네트워크 오류 보고서에 이름과 값이 포함될 요청 헤더 목록을 정의합니다. 이 멤버가 있으면 그 값은 문자열 목록이어야 합니다.

4.1.7 response_headers 멤버

선택 사항인 response_headers 멤버는 이 오리진에 관한 네트워크 오류 보고서에 이름과 값이 포함될 응답 헤더 목록을 정의합니다. 이 멤버가 있으면 그 값은 문자열 목록이어야 합니다.

4.2 정책 헤더 처리

네트워크 요청(request)과 이에 대응하는 응답(response)이 주어지면, 이 알고리즘은 request의 NEL 정책을 오리진에 대해 추출하고, 그에 따라 정책 캐시를 갱신합니다.

  1. 다음 조건 중 하나라도 참이면 이 단계를 중단합니다.
  2. origin을 request의 오리진으로 설정합니다.
  3. key를 request의 예약된 클라이언트가 주어졌을 때 네트워크 파티션 키 결정을 호출한 결과로 설정합니다.
  4. header를 이름이 NEL인 응답 헤더의 값으로 설정합니다.
  5. list를 header에 대해 [HTTP-JFV]의 4절에 정의된 알고리즘을 실행한 결과로 설정합니다. 해당 알고리즘에서 오류가 발생하거나 list가 비어 있으면 이 단계를 중단합니다.
  6. item을 list의 첫 번째 요소로 설정합니다.
  7. item에 max_age라는 멤버가 없거나, 해당 멤버의 값이 숫자가 아니면 이 단계를 중단합니다.
  8. item의 max_age 멤버의 값이 0이면, 정책 캐시에서 오리진이 origin인 모든 NEL 정책을 제거하고 나머지 단계를 건너뜁니다.
  9. item에 report_to라는 멤버가 없거나, 해당 멤버의 값이 문자열이 아니면 이 단계를 중단합니다.
  10. item에 success_fraction이라는 멤버가 있고, 그 값이 0.0 이상 1.0 이하 범위의 숫자가 아니면 이 단계를 중단합니다.
  11. item에 failure_fraction이라는 멤버가 있고, 그 값이 0.0 이상 1.0 이하 범위의 숫자가 아니면 이 단계를 중단합니다.
  12. item에 request_headers라는 멤버가 있고, 그 값이 목록이 아니거나 해당 목록의 요소 중 하나라도 문자열이 아니면 이 단계를 중단합니다.
  13. item에 response_headers라는 멤버가 있고, 그 값이 목록이 아니거나 해당 목록의 요소 중 하나라도 문자열이 아니면 이 단계를 중단합니다.
  14. policy를 다음과 같이 속성이 설정된 새로운 NEL 정책으로 설정합니다.

    수신 IP 주소
    사용자 에이전트가 response를 수신한 서버의 IP 주소
    편집자 참고

    [FETCH]에서 이를 더 명시적으로 전달하도록 합니다.

    오리진
    origin
    하위 도메인 플래그
    item에 값이 true인 include_subdomains라는 멤버가 있으면 include, 그렇지 않으면 exclude
    요청 헤더
    item의 request_headers 멤버의 값
    응답 헤더
    item의 response_headers 멤버의 값
    보고 그룹
    item의 report_to 멤버의 값
    ttl
    item의 max_age 멤버의 값
    생성 시각
    벽시계의 안전하지 않은 현재 시각
    성공 샘플링 비율
    item의 success_fraction 멤버가 있으면 그 값, 그렇지 않으면 0.0
    실패 샘플링 비율
    item의 failure_fraction 멤버가 있으면 그 값, 그렇지 않으면 1.0
  15. (key, origin)에 대한 항목이 이미 정책 캐시에 있으면 이를 policy로 교체합니다. 그렇지 않으면 (key, origin)에 대한 정책 캐시에 policy를 삽입합니다.

5. 보고서 전달

5.1 요청에 대한 정책 선택

네트워크 요청(request)이 주어지면, 이 알고리즘은 해당 네트워크 요청에 대한 보고서를 생성하는 데 정책 캐시의 어느 NEL 정책을 사용해야 하는지 결정합니다.

  1. origin을 request의 오리진으로 설정합니다.
  2. key를 request의 예약된 클라이언트가 주어졌을 때 네트워크 파티션 키 결정을 호출한 결과로 설정합니다.
  3. (key, origin)에 대한 항목이 정책 캐시에 있으면:
    1. policy를 해당 항목으로 설정합니다.
    2. policy가 만료되지 않았으면 이를 반환합니다.
  4. origin과 상위 도메인 일치하는 각 parent origin에 대해:
    1. (key, parent origin)에 대한 항목이 정책 캐시에 있으면:
      1. policy를 해당 항목으로 설정합니다.
      2. policy가 만료되지 않았고 해당 하위 도메인 플래그가 include이면 이를 반환합니다.
  5. no policy를 반환합니다.

5.2 요청 헤더 추출

네트워크 요청(request)과 NEL 정책(policy)이 주어지면, 이 알고리즘은 정책의 지시에 따라 요청에서 헤더 값을 추출합니다.

  1. headers를 새로운 빈 ECMAScript 객체로 설정합니다.
  2. policy의 요청 헤더 목록에 있는 각 header name에 대해:
    1. request의 헤더 목록에 header name이 포함되어 있지 않으면, 목록의 다음 header name으로 건너뜁니다.
    2. values를 빈 ECMAScript 목록으로 설정합니다.
    3. request의 헤더 목록에 있는 각 header 중 이름이 header name인 것에 대해, header의 값을 values에 추가합니다.
    4. 이름이 header name이고 값이 values인 새 속성을 headers에 추가합니다.
  3. headers를 반환합니다.

5.3 응답 헤더 추출

응답(response)과 NEL 정책 (policy)이 주어지면, 이 알고리즘은 정책의 지시에 따라 응답에서 헤더 값을 추출합니다.

  1. headers를 새로운 빈 ECMAScript 객체로 설정합니다.
  2. policy의 응답 헤더 목록에 있는 각 header name에 대해:
    1. response의 헤더 목록에 header name이 포함되어 있지 않으면, 목록의 다음 header name으로 건너뜁니다.
    2. values를 빈 ECMAScript 목록으로 설정합니다.
    3. response의 헤더 목록에 있는 각 header 중 이름이 header name인 것에 대해, header의 값을 values에 추가합니다.
    4. 이름이 header name이고 값이 values인 새 속성을 headers에 추가합니다.
  3. headers를 반환합니다.

5.4 네트워크 오류 보고서 생성

네트워크 요청(request)과 이에 대응하는 응답(response)이 주어지면, 이 알고리즘은 일치하는 NEL 정책에서 지시하는 경우 request에 대한 보고서를 생성하고 보고서와 NEL 정책을 반환합니다. 그렇지 않으면 이 알고리즘은 null을 반환합니다.

  1. request의 오리진에 대해 "오리진은 잠재적으로 신뢰할 수 있는가?" 알고리즘을 실행한 결과가 Potentially Trustworthy가 아니면, null을 반환합니다.
  2. origin을 request의 오리진으로 설정합니다.
  3. policy를 request에 대해 5.1 요청에 대한 정책 선택을 실행한 결과로 설정합니다. policy가 no policy이면 null을 반환합니다.
  4. 이 요청에 대한 활성 샘플링 비율을 결정합니다.
  5. 이 요청을 보고할지 여부를 결정합니다. roll을 0.0 이상 1.0 이하의 임의의 숫자로 설정합니다. roll > sampling rate이면 null을 반환합니다.
  6. report body를 다음 속성을 가진 새로운 ECMAScript 객체로 설정합니다. [ECMA-262]
    sampling_fraction
    sampling rate
    elapsed_time
    리소스 가져오기를 시작한 시점부터 완료되거나 사용자 에이전트에 의해 중단된 시점까지 경과한 밀리초 수입니다.
    phase
    request가 실패했으면, 해당 네트워크 오류의 단계입니다. request가 성공했으면, "application"입니다.
    type
    request가 실패했으면, 해당 네트워크 오류의 유형입니다. request가 성공했으면, "ok"입니다.
  7. report body의 phase 속성이 dns가 아니면 다음 속성을 report body에 추가합니다.
    server_ip
    사용 가능한 경우 사용자 에이전트가 요청을 전송한 서버의 IP 주소입니다. 그렇지 않으면 빈 문자열입니다.
    • IPv4 주소로 식별되는 호스트는 점으로 구분된 십진 표기법("."으로 구분된 0~255 범위의 네 개 십진수 시퀀스)으로 나타냅니다. [RFC1123]
    • IPv6 주소로 식별되는 호스트는 8개의 16비트 조각이 순서대로 나열된 목록(주소의 8개 16비트 조각 각각을 1~4개의 16진수 숫자인 'x'로 나타낸 x:x:x:x:x:x:x:x 시퀀스)으로 나타냅니다. [RFC4291]
    protocol
    사용 가능한 경우 ALPN 프로토콜 ID로 식별되는, 리소스를 가져오는 데 사용된 네트워크 프로토콜입니다. 그렇지 않으면 ""입니다.
  8. report body의 phase 속성이 dns 또는 connection이 아니면 다음 속성을 report body에 추가합니다.
    referrer
    request의 클라이언트와 연결된 리퍼러 정책에 따라 결정되는 request의 리퍼러입니다.
    method
    request의 요청 메서드입니다.
    request_headers
    request와 policy에 대해 5.2 요청 헤더 추출을 실행한 결과입니다.
    response_headers
    response와 policy에 대해 5.3 응답 헤더 추출을 실행한 결과입니다.
    status_code
    사용 가능한 경우 HTTP 응답의 상태 코드입니다. 그렇지 않으면 0입니다.
  9. origin이 policy의 오리진과 같지 않고, policy의 하위 도메인 플래그가 include이며, report body의 phase 속성이 dns가 아니면, null을 반환합니다.
    참고

    이 단계는 하위 도메인 NEL 정책을 요청의 DNS 이름 해석 단계 동안에만 정책 오리진의 하위 도메인에 대한 보고서를 생성하는 데 사용할 수 있도록 보장합니다. 자세한 내용은 9. 개인정보 보호 고려사항을 참조하십시오.

  10. report body의 phase 속성이 dns가 아니고 report body의 server_ip 속성이 비어 있지 않으며 policy의 수신 IP 주소와 같지 않으면:
    1. report body의 phase를 dns로 설정합니다.
    2. report body의 type을 dns.address_changed로 설정합니다.
    3. report body의 request_headers, response_headers, status_code 및 elapsed_time 속성을 지웁니다.
    4. 단언: report body에서 DNS 이름 해석 중 사용할 수 없는 정보에서 파생된 모든 필드가 지워졌습니다.
    참고

    이 단계는 서버와 정책의 IP 주소가 일치하지 않는 경우 NEL 보고서를 "다운그레이드"합니다. 이는 NEL 보고서가 해당 보고서가 설명하는 서비스의 소유자에게만 전송되도록 보장하는 개인정보 보호 조치입니다. IP 주소가 일치하지 않으면 사용자 에이전트는 NEL 정책이 오리진의 도메인 이름 소유자가 전송했다는 것만 확인할 수 있으며, 해당 정책이 이 도메인 이름이 해석되는 서버의 소유자가 전송했다는 것은 확인할 수 없습니다. 따라서 보고서를 DNS 이름 해석에 대한 정보만 포함하도록 다운그레이드합니다. 자세한 내용은 9. 개인정보 보호 고려사항 및 7.5 여러 IP 주소가 있는 오리진을 참조하십시오.

  11. policy가 오래된 상태이면 policy를 정책 캐시에서 삭제합니다.
  12. report body와 policy를 반환합니다.

5.5 네트워크 보고서 전달

ECMAScript 객체(report body, 일반적으로 네트워크 오류 보고서 생성에서 반환된 후 호출 명세에 의해 확장됨)와 이에 일치하는 NEL 정책(policy) 및 네트워크 요청 (request)이 주어지면, 이 알고리즘은 전달을 위해 보고서를 대기열에 추가합니다.

  1. url을 request의 URL로 설정합니다.

  2. url의 프래그먼트를 지웁니다.

  3. report body의 phase 속성이 dns 또는 connection이면:

    1. url의 경로와 쿼리를 지웁니다.

  4. 다음 매개변수가 주어졌을 때 네트워크 보고서를 생성합니다.

    유형
    network-error
    데이터
    report body
    엔드포인트 그룹
    policy의 보고 그룹
    url
    url에 대해 URL 직렬화기를 실행한 결과입니다.

6. 미리 정의된 네트워크 오류 유형

미리 정의된 여러 네트워크 오류 유형이 있습니다.

사용자 에이전트는 이 목록을 사용자 정의 네트워크 오류 유형으로 확장할 수 있습니다 — 예를 들어 새로운 프로토콜을 수용하거나 기존 오류를 더 상세하게 설명하기 위해서입니다. 이렇게 할 때 사용자 에이전트는 오류 보고서를 간단하고 일관되게 처리할 수 있도록 유형 이름에 점으로 구분된 패턴 ([group].[optional-subgroup].[error-name])을 따르는 것이 좋습니다 — 예를 들어 수집기는 범주 및/또는 하나 이상의 하위 그룹별 집계를 제공할 수 있습니다.

6.1 DNS 이름 해석 오류

이 절의 모든 네트워크 오류는 DNS 이름 해석 중에 발생하므로 단계는 dns입니다.

dns.unreachable
DNS 서버에 연결할 수 없습니다
dns.name_not_resolved
DNS 서버가 응답했지만 주소를 해석할 수 없습니다
dns.failed
이전 오류에 포함되지 않은 이유로 DNS 서버에 대한 요청이 실패했습니다
dns.address_changed
요청의 오리진에 대해 해석된 IP 주소가 대응하는 NEL 정책이 수신된 이후 변경되었음을 나타냅니다

6.2 보안 연결 설정 오류

이 절의 모든 네트워크 오류는 보안 연결 설정 중에 발생하므로 단계는 connection입니다.

tcp.timed_out
서버에 대한 TCP 연결 시간이 초과되었습니다
tcp.closed
서버가 TCP 연결을 종료했습니다
tcp.reset
TCP 연결이 재설정되었습니다
tcp.refused
서버가 TCP 연결을 거부했습니다
tcp.aborted
TCP 연결이 중단되었습니다
tcp.address_invalid
IP 주소가 유효하지 않습니다
tcp.address_unreachable
IP 주소에 연결할 수 없습니다
tcp.failed
이전 오류에 포함되지 않은 이유로 TCP 연결이 실패했습니다
tls.version_or_cipher_mismatch
버전 또는 암호 스위트 불일치로 인해 TLS 연결이 중단되었습니다
tls.bad_client_auth_cert
유효하지 않은 클라이언트 인증서로 인해 TLS 연결이 중단되었습니다
tls.cert.name_invalid
유효하지 않은 이름으로 인해 TLS 연결이 중단되었습니다
tls.cert.date_invalid
유효하지 않은 인증서 날짜로 인해 TLS 연결이 중단되었습니다
tls.cert.authority_invalid
유효하지 않은 발급 기관으로 인해 TLS 연결이 중단되었습니다
tls.cert.invalid
유효하지 않은 인증서로 인해 TLS 연결이 중단되었습니다
tls.cert.revoked
폐기된 서버 인증서로 인해 TLS 연결이 중단되었습니다
tls.cert.pinned_key_not_in_cert_chain
키 고정 오류로 인해 TLS 연결이 중단되었습니다
tls.protocol.error
TLS 프로토콜 오류로 인해 TLS 연결이 중단되었습니다
tls.failed
이전 오류에 포함되지 않은 이유로 TLS 연결이 실패했습니다

6.3 요청 및 응답 전송 오류

이 절의 모든 네트워크 오류는 요청 및 응답 전송 중에 발생하므로 단계는 application입니다.

http.error
사용자 에이전트가 응답을 성공적으로 수신했지만 4xx 또는 5xx 상태 코드가 포함되어 있습니다
http.protocol.error
HTTP 프로토콜 오류로 인해 연결이 중단되었습니다
http.response.invalid
응답이 비어 있거나, content-length가 일치하지 않거나, 인코딩이 올바르지 않거나, 사용자 에이전트가 응답을 처리하지 못하게 하는 기타 조건이 있습니다
http.response.redirect_loop
리디렉션 루프가 감지되어 요청이 중단되었습니다
http.failed
이전 오류에 포함되지 않은 HTTP 프로토콜 오류로 인해 연결이 실패했습니다
abandoned
리소스 가져오기가 완료되기 전에 사용자가 중단했습니다
unknown
오류 유형을 알 수 없습니다

7. 예제

7.1 정책 정의 예제

> GET / HTTP/1.1
> Host: example.com

< HTTP/1.1 200 OK
< ...
< Report-To: {"group": "network-errors", "max_age": 2592000,
              "endpoints": [{"url": "https://example.com/upload-reports"}]}
< NEL: {"report_to": "network-errors", "max_age": 2592000}

이 NEL 헤더는 NEL 정책을 정의하여 사용자 에이전트가 example.com에 관한 네트워크 오류를 network-errors라는 이름의 엔드포인트 그룹에 보고하도록 지시합니다. 이 정책은 2592000초(30일) 동안 적용됩니다.

위 등록은 응답이 잠재적으로 신뢰할 수 있는 오리진에서 전달된 경우에만 성공한다는 점에 유의하십시오.

> GET / HTTP/1.1
> Host: example.com

< HTTP/1.1 200 OK
< ...
< NEL: {"max_age": 0}

이 NEL 헤더는 사용자 에이전트에 example.com에 대한 기존의 모든 NEL 정책을 제거하도록 지시합니다.

7.2 네트워크 오류 보고서 예제

이 절에는 등록된 NEL 정책이 있는 오리진에서 네트워크 오류가 발생했을 때 사용자 에이전트가 대기열에 추가할 수 있는 네트워크 오류 보고서 예제가 포함되어 있습니다. 보고서를 업로드할 때 [REPORTING] API가 생성하는 전체 보고서 페이로드를 보여 줍니다. 페이로드의 body 필드에는 네트워크 오류 보고서 본문이 포함됩니다.

{
  "age": 0,
  "type": "network-error",
  "url": "https://www.example.com/",
  "body": {
    "sampling_fraction": 0.5,
    "referrer": "http://example.com/",
    "server_ip": "2001:DB8:0:0:0:0:0:42",
    "protocol": "h2",
    "method": "GET",
    "request_headers": {},
    "response_headers": {},
    "status_code": 200,
    "elapsed_time": 823,
    "phase": "application",
    "type": "http.protocol.error"
  }
}

이 보고서는 사용자 에이전트가 example.com에서 www.example.com으로 이동하려 했으며, 해당 주소가 2001:DB8::42로 성공적으로 해석되었음을 나타냅니다. 그러나 사용자 에이전트가 HTTP/2(h2) 프로토콜을 통해 서버로부터 200 응답을 수신했지만, 교환 과정에서 프로토콜 오류가 발생하여 탐색을 중단해야 했습니다. 사용자 에이전트는 탐색이 시작된 지 823밀리초 후 탐색을 중단했습니다. 마지막으로 사용자 에이전트는 네트워크 오류가 발생한 직후 이 보고서를 전송했습니다. 즉, 보고서의 경과 시간은 0입니다.

{
  "age": 0,
  "type": "network-error",
  "url": "https://widget.com/thing.js",
  "body": {
    "sampling_fraction": 1.0,
    "referrer": "https://www.example.com/",
    "server_ip": "",
    "protocol": "",
    "method": "GET",
    "request_headers": {},
    "response_headers": {},
    "status_code": 0,
    "elapsed_time": 143,
    "phase": "dns",
    "type": "dns.name_not_resolved"
  }
}

위 보고서는 사용자 에이전트가 https://www.example.com/에서 https://widget.com/thing.js를 가져오려고 했음을 나타냅니다. 그러나 사용자 에이전트는 DNS 이름(widget.com)을 해석할 수 없었으며 요청은 143밀리초 후 사용자 에이전트에 의해 중단되었습니다. widget.com에 대한 이전 요청에서 유효한 NEL 정책을 전달했기 때문에 사용자 에이전트는 이 요청에 대한 네트워크 오류 보고서를 생성합니다. 이 보고서는 네트워크 오류가 발생한 직후 업로드되었습니다. 즉, 보고서 경과 시간은 0입니다.

7.3 DNS 잘못된 구성

> GET / HTTP/1.1
> Host: example.com

< HTTP/1.1 200 OK
< ...
< Report-To: {"group": "network-errors", "max_age": 2592000,
              "endpoints": [{"url": "https://example.com/upload-reports"}]}
< NEL: {"report_to": "network-errors", "max_age": 2592000, "include_subdomains": true}

이 NEL 헤더를 사용하면 example.com의 소유자는 자신이 DNS 서버를 잘못 구성한 경우를 감지할 수 있습니다. 예를 들어 new-subdomain.example.com을 IP 주소로 해석하는 새 리소스 레코드를 추가하는 것을 잊은 경우입니다. 사용자 에이전트가 new-subdomain.example.com에 요청을 시도하면 다음 보고서를 생성할 수 있습니다.

{
  "age": 0,
  "type": "network-error",
  "url": "https://new-subdomain.example.com/",
  "body": {
    "sampling_fraction": 1.0,
    "server_ip": "",
    "protocol": "http/1.1",
    "method": "GET",
    "request_headers": {},
    "response_headers": {},
    "status_code": 0,
    "elapsed_time": 48,
    "phase": "dns",
    "type": "dns.name_not_resolved"
  }
}

7.4 캐시 검증 모니터링

> GET / HTTP/1.1
> Host: example.com

< HTTP/1.1 200 OK
< ...
< Report-To: {"group": "network-errors", "max_age": 2592000,
              "endpoints": [{"url": "https://example.com/upload-reports"}]}
< NEL: {"report_to": "network-errors", "max_age": 2592000, "success_fraction": 1.0,
        "request_headers": ["If-None-Match"], "response_headers": ["ETag"]}
< ETag: 01234abcd

이 예제에서 example.com의 소유자는 서버에서 호스팅되는 리소스의 서로 다른 버전을 식별하기 위해 ETag 응답 헤더를 사용합니다. 그러면 사용자 에이전트는 If-None-Match 요청 헤더를 사용하여 현재 클라이언트 측에 캐시된 리소스 버전을 서버에 알릴 수 있으며, 이를 통해 클라이언트의 기존 복사본이 최신 상태인 경우 서버가 리소스 콘텐츠를 생성하고 전송하지 않을 수 있습니다.

이 도메인의 NEL 헤더에 request_headers 및 response_headers 필드를 포함하면 브라우저는 해당 요청에 대해 생성하는 모든 NEL 보고서에 If-None-Match 요청 헤더의 복사본과 ETag 응답 헤더를 포함하여, 사이트 소유자가 캐싱 정책의 효과를 추적할 수 있도록 합니다.

위 내용을 전제로 다음과 같은 일련의 이벤트를 살펴보겠습니다.

  1. 사용자 에이전트는 example.com에 요청을 보내고, 서버로부터 성공적인 응답을 수신하며, 이 응답에는 리소스의 버전을 나타내는 ETag 헤더가 포함되어 있습니다. 사용자 에이전트는 다음 NEL 보고서를 생성합니다.

    {
      "age": 0,
      "type": "network-error",
      "url": "https://example.com/",
      "body": {
        "sampling_fraction": 1.0,
        "server_ip": "192.0.2.1",
        "protocol": "http/1.1",
        "method": "GET",
        "request_headers": {},
        "response_headers": {
          "ETag": ["01234abcd"]
        },
        "status_code": 200,
        "elapsed_time": 1392,
        "phase": "application",
        "type": "ok"
      }
    }
  2. 얼마 후 사용자 에이전트는 example.com에 또 다른 요청을 보냅니다. 사용자 에이전트는 여전히 원래 리소스의 복사본을 로컬 캐시에 보유하고 있으며 그 버전을 If-None-Match 요청 헤더에 포함합니다. 서버는 이 버전을 확인하고 여전히 최신 상태임을 확인한 뒤, 캐시된 리소스 복사본이 여전히 유효하다는 것을 사용자 에이전트에 알리는 304 응답을 전송합니다. 사용자 에이전트는 다음 보고서를 생성합니다.

    {
      "age": 0,
      "type": "network-error",
      "url": "https://example.com/",
      "body": {
        "sampling_fraction": 1.0,
        "server_ip": "192.0.2.1",
        "protocol": "http/1.1",
        "method": "GET",
        "request_headers": {
          "If-None-Match": ["01234abcd"]
        },
        "response_headers": {
          "ETag": ["01234abcd"]
        },
        "status_code": 304,
        "elapsed_time": 45,
        "phase": "application",
        "type": "ok"
      }
    }
  3. 더 시간이 지난 후 사용자 에이전트는 example.com에 다시 또 다른 요청을 보냅니다. 사용자 에이전트는 여전히 동일한 리소스 복사본을 로컬 캐시에 보유하고 있으며 이전 예제와 마찬가지로 그 버전을 If-None-Match 요청 헤더에 포함합니다. 그러나 이번에는 서버가 리소스의 새 버전을 사용할 수 있음을 확인합니다. 서버는 이 리소스의 콘텐츠를 생성하여 클라이언트에 전송하고, 새 버전을 새로운 ETag 응답 헤더 값에 인코딩합니다. 사용자 에이전트는 다음 보고서를 생성합니다.

    {
      "age": 0,
      "type": "network-error",
      "url": "https://example.com/",
      "body": {
        "sampling_fraction": 1.0,
        "server_ip": "192.0.2.1",
        "protocol": "http/1.1",
        "method": "GET",
        "request_headers": {
          "If-None-Match": ["01234abcd"]
        },
        "response_headers": {
          "ETag": ["56789ef01"]
        },
        "status_code": 200,
        "elapsed_time": 935,
        "phase": "application",
        "type": "ok"
      }
    }

7.5 여러 IP 주소가 있는 오리진

오리진의 도메인 이름이 여러 IP 주소로 해석되는 경우 NEL은 오류의 원인에 대해 더 적은 정보를 제공하도록 오류 보고서를 때때로 "다운그레이드"합니다. 이는 오리진의 소유자와 요청을 처리하는 서버의 소유자가 동일한지 확인할 수 없기 때문입니다.

예를 들어 example.com이 각각 서로 다른 IP 주소를 가진 세 서버에서 처리된다고 가정합니다. 서비스 소유자는 example.com이 192.0.2.1, 192.0.2.2 및 192.0.2.3으로 해석되도록 DNS를 구성하고, 사용자 에이전트가 이 세 IP 주소에 걸쳐 요청을 분산하도록 합니다. 서비스 소유자는 다음 NEL 정책을 전달합니다.

> GET / HTTP/1.1
> Host: example.com

< HTTP/1.1 200 OK
< ...
< Report-To: {"group": "network-errors", "max_age": 2592000,
              "endpoints": [{"url": "https://example.com/upload-reports"}]}
< NEL: {"report_to": "network-errors", "max_age": 2592000,
        "success_fraction": 1.0, "failure_fraction": 1.0}

위 내용을 전제로 다음과 같은 일련의 이벤트를 살펴보겠습니다.

  1. 사용자 에이전트는 192.0.2.1에 요청을 보내고, 서버로부터 성공적인 응답을 수신합니다. 이 응답에는 위의 NEL 정책도 포함되며, 사용자 에이전트는 정책의 수신 IP 주소를 192.0.2.1로 설정합니다. 수신 IP 주소가 서버의 IP 주소와 일치하므로(성공한 모든 요청에서는 반드시 일치해야 합니다) 다음 NEL 보고서를 생성합니다.

    {
      "age": 0,
      "type": "network-error",
      "url": "https://example.com/",
      "body": {
        "sampling_fraction": 1.0,
        "server_ip": "192.0.2.1",
        "protocol": "http/1.1",
        "method": "GET",
        "request_headers": {},
        "response_headers": {},
        "status_code": 200,
        "elapsed_time": 57,
        "phase": "application",
        "type": "ok"
      }
    }
  2. 사용자 에이전트는 192.0.2.2에 새 요청을 보내고 또 다른 성공적인 응답을 수신합니다. 이 응답에도 NEL 정책이 포함되어 있으며, 사용자 에이전트는 정책의 수신 IP 주소를 192.0.2.2로 갱신합니다. 수신 IP 주소가 서버의 IP 주소와 일치하므로(성공한 모든 요청에서는 반드시 일치해야 합니다) 다음 NEL 보고서를 생성합니다.

    {
      "age": 0,
      "type": "network-error",
      "url": "https://example.com/",
      "body": {
        "sampling_fraction": 1.0,
        "server_ip": "192.0.2.2",
        "protocol": "http/1.1",
        "method": "GET",
        "request_headers": {},
        "response_headers": {},
        "status_code": 200,
        "elapsed_time": 34,
        "phase": "application",
        "type": "ok"
      }
    }
  3. 그런 다음 사용자 에이전트는 192.0.2.3에 요청을 보내려고 하지만 서버와 연결을 설정할 수 없습니다. 사용자 에이전트는 여전히 NEL 정책을 정책 캐시에 보유하고 있으며, 이상적으로는 이 정책을 사용하여 실패한 네트워크 요청에 대한 tcp.timed_out 보고서를 생성하려고 합니다. 그러나 정책의 수신 IP 주소(192.0.2.2)가 이 요청이 전송된 IP 주소와 일치하지 않으므로 사용자 에이전트는 192.0.2.3의 서버가 실제로 example.com의 소유자에게 소유되어 있는지 확인할 수 없습니다. 따라서 사용자 에이전트는 보고서를 dns.address_changed로 다운그레이드해야 합니다.

    {
      "age": 0,
      "type": "network-error",
      "url": "https://example.com/",
      "body": {
        "sampling_fraction": 1.0,
        "server_ip": "192.0.2.3",
        "protocol": "http/1.1",
        "method": "GET",
        "request_headers": {},
        "response_headers": {},
        "status_code": 0,
        "elapsed_time": 0,
        "phase": "dns",
        "type": "dns.address_changed"
      }
    }
  4. 그런 다음 사용자 에이전트는 192.0.2.1에 또 다른 요청을 보내려고 하지만 이번에도 서버와 연결을 설정할 수 없습니다. 사용자 에이전트가 과거 어느 시점에 192.0.2.1에서 NEL 정책을 수신했더라도, 정책의 수신 IP 주소는 정책이 가장 최근에 어디에서 수신되었는지만 기록합니다. 이 경우에는 192.0.2.2입니다. 따라서 사용자 에이전트는 보고서를 dns.address_changed로 다운그레이드해야 합니다.

    {
      "age": 0,
      "type": "network-error",
      "url": "https://example.com/",
      "body": {
        "sampling_fraction": 1.0,
        "server_ip": "192.0.2.1",
        "protocol": "http/1.1",
        "method": "GET",
        "request_headers": {},
        "response_headers": {},
        "status_code": 0,
        "elapsed_time": 0,
        "phase": "dns",
        "type": "dns.address_changed"
      }
    }

8. 사용 사례

8.1 탐색 실패 보고

사용자가 시작한 탐색 요청(예: 링크 클릭, 주소 표시줄을 통한 직접 입력, 사용자 상호작용으로 인해 스크립트에서 시작된 경우 등)은 여러 연결 문제로 인해 실패할 수 있습니다. DNS 실패, TCP 오류, TLS 프로토콜 위반 등이 이에 해당합니다. 이러한 오류는 네트워크 잘못된 구성, 일시적인 라우팅 문제, 서버 중단, 악성 소프트웨어 또는 사용자에 대한 기타 공격 등으로 인해 발생할 수 있습니다.

이러한 경우 대상 호스트는 정의상 요청이 자신의 인프라에 도달하는 것을 볼 수 없고 문제를 조사할 수 없으므로 실패한 탐색을 인지하지 못하는 경우가 많습니다. 이를 해결하기 위해 호스트는 사용자 에이전트에 NEL 정책을 등록하여 이러한 실패에 대한 보고서를 조사할 수 있도록 어디로 전달해야 하는지 지정할 수 있습니다.

8.2 퍼스트 파티 하위 리소스 가져오기 실패 보고

일반적인 애플리케이션에는 수십 개의 리소스가 필요하며, 이러한 리소스의 가져오기는 일반적으로 HTML, CSS 또는 JavaScript를 통해 시작됩니다. 이러한 리소스를 요청하는 애플리케이션은 대부분의 가져오기 실패를 관찰할 수 있지만(예: onerror 콜백을 통해), 실패가 발생한 이유에 대한 상세한 네트워크 오류 보고서에는 접근할 수 없습니다. 예를 들어 DNS 실패, TCP 오류, TLS 프로토콜 위반 등이 이에 해당합니다.

이를 해결하기 위해 애플리케이션은 하위 리소스를 가져오는 퍼스트 파티 호스트에 대해 관련 NEL 정책을 사용자 에이전트에 등록할 수 있습니다. 그러면 이러한 정책이 존재하고 등록된 NEL 정책이 있는 오리진의 리소스에서 네트워크 오류가 발생하는 경우, 사용자 에이전트는 상세한 네트워크 오류 보고서를 보고하여 애플리케이션 개발자가 오류를 조사할 수 있도록 합니다.

8.3 서드 파티 하위 리소스 가져오기 실패 보고

리소스가 서드 파티에 의해 삽입되는 경우 리소스 제공자는 해당 실패를 계측하고 관찰할 수 없는 경우가 많습니다. 예를 들어 example.com이 자신의 사이트에 widget.com/thing.js 리소스를 삽입하고, example.com을 방문한 사용자가 네트워크 오류로 인해 해당 리소스를 가져오지 못하면 widget.com 호스트는 실패를 인지하지 못할 뿐만 아니라 감지할 수도 없습니다.

이를 해결하기 위해 widget.com은 자신의 호스트에 NEL 정책을 등록할 수 있습니다. 그러면 이러한 정책이 존재하고, 퍼스트 파티 또는 서드 파티 오리진 중 어디에서 요청되었는지와 관계없이 리소스를 가져오는 동안 등록된 NEL 정책이 있는 오리진에서 네트워크 오류가 발생하면 사용자 에이전트는 네트워크 오류를 보고하여 제공자가 오류를 조사할 수 있도록 합니다.

9. 개인정보 보호 고려사항

NEL은 사용자의 네트워크 구성에 관한 새로운 정보를 노출할 수 있는 네트워크 오류 보고서를 제공합니다. 예를 들어 공격자는 NEL 보고를 악용하여 사용자의 네트워크 구성을 탐색하거나 사용자의 내부 네트워크에서 서버를 스캔할 수 있습니다. 또한 HSTS, HPKP 및 고정된 CSP 정책과 마찬가지로 저장된 NEL 정책은 사용자별 사용자 정의 보고 URI가 있는 고유한 정책을 설정하여 HTTP 쿠키와 함께(또는 대신) 식별자로 작동하도록 하는 "슈퍼쿠키"로 사용될 수 있습니다.

위 위험 중 일부를 완화하기 위해 NEL 등록은 잠재적으로 신뢰할 수 있는 오리진으로 제한되며, 네트워크 오류 보고서 전달 역시 잠재적으로 신뢰할 수 있는 오리진으로 제한됩니다. 이는 일시적인 HTTP MITM이 NEL을 지속적인 추적기로 손쉽게 악용하는 것을 방지합니다.

또한 NEL 정책 캐시는 네트워크 파티션 키를 사용하여 분할되므로, 한 삽입 컨텍스트에서 사이트에 대해 저장된 NEL 정책은 다른 컨텍스트에서는 사용되지 않습니다 (예를 들어 다른 최상위 사이트에 의해 삽입된 경우).

NEL은 기존의 서버 측 모니터링을 보완하기 위한 것입니다. NEL 보고서는 요청되는 서비스의 소유자에게만 전송되어야 합니다. DNS 이름 해석 중 발생하는 오류의 경우, NEL 보고서는 NEL 정책이 정책 오리진을 포함하는 도메인 이름 공간 트리의 소유자에게서 수신된 경우에만 생성됩니다. 보안 연결 설정 또는 요청 및 응답 전송 중 발생하는 오류의 경우, NEL 보고서는 NEL 정책이 요청이 전송된 서버의 소유자에게서 수신된 경우에만 생성됩니다.

이러한 근거는 NEL 정책의 수신 IP 주소 및 하위 도메인 플래그를 처리하는 방식을 설명합니다. 정책의 수신 IP 주소가 서버의 IP 주소와 일치하는지 확인함으로써 NEL은 정책의 신뢰 경계를 정책의 오리진뿐만 아니라 사용자 에이전트가 통신 중인 특정 서버까지 포함하도록 확장합니다. 이는 예를 들어 공격자가 자신이 소유한 서버에서 장기간 유지되는 NEL 정책을 전달한 다음, 자신이 제어하지 않는 서버로 정책 오리진이 해석되도록 이름 서버를 변경하는 DNS 리바인딩 공격을 방지하는 데 도움이 됩니다. 수신 IP 주소 검증이 없다면, 이는 사용자 에이전트가 두 번째 서버에 관한 보고서를 공격자에게 전송하게 할 수 있습니다.

마찬가지로 하위 도메인 NEL 정책은 제한되며, 정책 오리진의 하위 도메인에 대한 보고서를 DNS 이름 해석 단계에서만 요청에 대해 생성하는 데 사용할 수 있습니다. 이 단계에서는 소유권을 확인할 서버가 없으며, 정책이 요청의 오리진의 상위 도메인에서 수신되었다는 사실만으로도 오류의 소유권을 확립하기에 충분합니다. 이를 통해 도메인 이름 공간 트리의 특정 부분 소유자는 NEL을 사용하여 7.3 DNS 잘못된 구성 오류를 감지할 수 있으며, 동시에 악의적인 DNS 항목을 사용하여 자신이 제어하지 않는 서버에 관한 정보를 수집하는 것은 방지됩니다.

정보 유출을 방지하기 위해 요청에 관한 NEL 보고서에는 요청을 처리할 때 서버에서 볼 수 없는 정보는 포함되지 않습니다. DNS 이름 해석 중 오류의 경우, NEL 보고서는 DNS 자체에서 사용할 수 있는 정보만 포함합니다. 이는 서버가 NEL을 악용하여 이미 접근할 수 있는 것보다 더 많은 사용자 정보를 수집하는 것을 방지합니다. NEL 보고서는 보고서 본문의 server_ip 필드에 웹 사이트의 공개 IP 주소를 포함한다는 점에 유의하십시오. 이 주소는 NEL 헤더를 생성하는 서비스에 항상 알려져 있는 것은 아닐 수 있습니다. 예를 들어 로드 밸런서 또는 기타 투명한 MitM 프록시 뒤에 있는 경우가 이에 해당합니다.

참고

예를 들어 NEL 보고서에는 요청의 도메인 이름을 IP 주소로 해석하는 데 어떤 DNS 리졸버가 사용되었는지에 관한 정보가 명시적으로 포함되지 않습니다.

위 제한 사항 외에도 사용자 에이전트는 다음을 해야 합니다.

NEL을 배포할 때 개발자는 지정된 수집기에 전달되는 NEL 보고서의 개인정보 보호 영향을 고려하는 것이 좋습니다. 예를 들어 보고서에는 특별한 주의가 필요할 수 있는 민감한 데이터가 포함된 URL(예: "Capability URL")이 포함될 수 있으며([CAPABILITY-URLS] 참조), 이러한 URL이 서드 파티에 보고되는 것을 방지하기 위해 개발자가 자체 NEL 수집기를 운영해야 할 수도 있습니다.

10. IANA 고려사항

영구 메시지 헤더 필드 레지스트리는 다음 등록으로 갱신하는 것이 좋습니다([RFC3864]).

10.1 NEL

헤더 필드 이름
NEL
적용 가능한 프로토콜
http
상태
표준
작성자/변경 관리자
W3C
명세 문서
이 명세(NEL 응답 헤더 참조)

A. 색인

A.1 이 명세에서 정의된 용어

A.2 참조로 정의된 용어

B. 감사의 글

이 문서는 해당 명세의 라이선스가 허용하는 바에 따라 [CSP] 및 [RFC6797] 명세의 텍스트를 재사용합니다. 또한 이 작업에 유용한 의견과 기여를 해 주신 Julia Tuttle, Chris Bentzel, Todd Reifsteck, Aaron Heady 및 Mark Nottingham께 진심으로 감사드립니다.

C. 참고 문헌

C.1 규범적 참고 문헌

[CAPABILITY-URLS]
Capability URL에 대한 모범 사례. Jeni Tennison. W3C. 2014년 2월 18일. FPWD. URL: https://www.w3.org/TR/capability-urls/
[CSP]
콘텐츠 보안 정책 레벨 3. Mike West; Antonio Sartori. W3C. 2025년 4월 30일. W3C 작업 초안. URL: https://www.w3.org/TR/CSP3/
[ECMA-262]
ECMAScript 언어 명세. Ecma International. URL: https://tc39.es/ecma262/multipage/
[fetch]
Fetch 표준. Anne van Kesteren. WHATWG. 현행 표준. URL: https://fetch.spec.whatwg.org/
[hr-time]
고해상도 시간. Yoav Weiss. W3C. 2024년 11월 7일. W3C 작업 초안. URL: https://www.w3.org/TR/hr-time-3/
[html]
HTML 표준. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[HTTP-JFV]
HTTP 헤더 필드 값을 위한 JSON 인코딩. J. Reschke. IETF. 2017년 10월 24일. 활성 인터넷 초안. URL: https://datatracker.ietf.org/doc/html/draft-reschke-http-jfv
[infra]
Infra 표준. Anne van Kesteren; Domenic Denicola. WHATWG. 현행 표준. URL: https://infra.spec.whatwg.org/
[mixed-content]
혼합 콘텐츠. Emily Stark; Mike West; Carlos IbarraLopez. W3C. 2023년 2월 23일. CRD. URL: https://www.w3.org/TR/mixed-content/
[network-reporting]
네트워크 보고 API. W3C. 편집자 초안. URL: https://w3c.github.io/reporting/network-reporting.html
[referrer-policy]
리퍼러 정책. Jochen Eisinger; Emily Stark. W3C. 2017년 1월 26일. W3C 후보 권고안. URL: https://www.w3.org/TR/referrer-policy/
[REPORTING]
Reporting API. Douglas Creager; Ian Clelland; Mike West. W3C. 2024년 8월 13일. W3C 작업 초안. URL: https://www.w3.org/TR/reporting-1/
[RESOURCE-TIMING-2]
리소스 타이밍. Yoav Weiss; Noam Rosenthal. W3C. 2025년 2월 13일. CRD. URL: https://www.w3.org/TR/resource-timing/
[RFC1034]
도메인 이름 - 개념 및 기능. P. Mockapetris. IETF. 1987년 11월. 인터넷 표준. URL: https://www.rfc-editor.org/rfc/rfc1034
[RFC1123]
인터넷 호스트 요구 사항 - 애플리케이션 및 지원. R. Braden, 편집자. IETF. 1989년 10월. 인터넷 표준. URL: https://www.rfc-editor.org/rfc/rfc1123
[RFC2119]
요구 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어. S. Bradner. IETF. 1997년 3월. 현행 모범 사례. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC3864]
메시지 헤더 필드 등록 절차. G. Klyne; M. Nottingham; J. Mogul. IETF. 2004년 9월. 현행 모범 사례. URL: https://www.rfc-editor.org/rfc/rfc3864
[RFC4291]
IP 버전 6 주소 지정 아키텍처. R. Hinden; S. Deering. IETF. 2006년 2월. 표준 초안. URL: https://www.rfc-editor.org/rfc/rfc4291
[RFC5234]
구문 명세를 위한 확장 BNF: ABNF. D. Crocker, 편집자; P. Overell. IETF. 2008년 1월. 인터넷 표준. URL: https://www.rfc-editor.org/rfc/rfc5234
[RFC6797]
HTTP 엄격한 전송 보안 (HSTS). J. Hodges; C. Jackson; A. Barth. IETF. 2012년 11월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6797
[RFC8174]
RFC 2119 핵심 단어의 대문자와 소문자 모호성. B. Leiba. IETF. 2017년 5월. 현행 모범 사례. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC9110]
HTTP 의미론. R. Fielding, 편집자; M. Nottingham, 편집자; J. Reschke, 편집자. IETF. 2022년 6월. 인터넷 표준. URL: https://httpwg.org/specs/rfc9110.html
[RFC9112]
HTTP/1.1. R. Fielding, 편집자; M. Nottingham, 편집자; J. Reschke, 편집자. IETF. 2022년 6월. 인터넷 표준. URL: https://httpwg.org/specs/rfc9112.html
[secure-contexts]
보안 컨텍스트. Mike West. W3C. 2023년 11월 10일. CRD. URL: https://www.w3.org/TR/secure-contexts/
[url]
URL 표준. Anne van Kesteren. WHATWG. 현행 표준. URL: https://url.spec.whatwg.org/