네트워크 오류 로깅

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/ 에서 확인할 수 있습니다.

이 문서는 Web Performance Working Group에서 권고안 절차를 이용하여 Working Draft로 발행한 것입니다.

Working Draft로서의 발행은 W3C 및 그 회원사의 승인을 의미하지 않습니다.

이 문서는 초안으로, 언제든지 갱신, 대체 또는 폐기될 수 있습니다. 해당 문서는 작업 중인 자료 외에 인용하는 것이 적절하지 않습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹이 작성하였습니다. W3C는 그룹 산출물과 관련하여 공개 특허 고지 목록을 관리합니다. 해당 페이지에는 특허 고지 방법에 대한 안내도 있습니다. 특정 특허에 대해 실질적인 지식이 있는 개인은, 그 특허에 필수 청구항이 포함되어 있다고 판단될 경우, W3C 특허 정책 6조에 따라 정보를 공개해야 합니다.

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

1. 소개

웹 애플리케이션의 성능 특성을 정확하게 측정하는 것은 사이트 개발자가 웹 애플리케이션을 어떻게 개선할 수 있을지 이해하는 데 중요한 요소입니다. 최악의 경우는 네트워크 오류로 인해 애플리케이션 또는 특정 리소스가 로드되지 않는 상황이며, 이러한 실패를 해결하기 위해 개발자는 언제, 어디서, 왜 이러한 실패가 발생하는지 사용자 에이전트의 지원이 필요합니다.

현재는 응용 프로그램 개발자가 엔드유저로부터 실시간 웹 애플리케이션 가용성 데이터를 확보할 수 없습니다. 예를 들어, 사용자가 DNS 조회 실패, 연결 시간 초과, 연결 리셋 등 네트워크 오류로 인해 페이지 로드에 실패한 경우, 사이트 개발자는 이를 탐지하거나 해결할 수 없습니다. 이러한 네트워크 오류는 서버 측에서만으로는 감지할 수 없는데, 클라이언트가 정의상 서버에 성공적으로 연결을 수립하지 못했을 수 있기 때문입니다.

기존 방식(예: synthetic monitoring)은 미리 정해진 지리적 위치에 모니터링 노드를 배치함으로써 부분 해결책을 제공하지만, 추가 인프라 투자가 필요하고, 실제 최종 사용자를 위한 진정한 글로벌 및 거의 실시간의 가용성 데이터를 제공하지는 못합니다.

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

예를 들어, 사용자 에이전트가 https://www.example.com에서 TCP 연결이 중단되어 리소스 가져오기에 실패한 경우, 사용자 에이전트는 Reporting API를 통해 다음과 같은 보고서를 큐에 추가합니다:

type
"network-error"
endpoint group
report_to 필드로 구성된 엔드포인트 그룹
data
{
  "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. 적합성

비표준으로 표시된 섹션뿐만 아니라, 본 명세의 모든 작성 가이드라인, 다이어그램, 예제, 주석 등은 비표준입니다. 이 명세서의 나머지 부분은 표준입니다.

본 문서에서 MAY, MUST, MUST NOT, OPTIONAL, REQUIRED, SHOULD 등은 BCP 14 [RFC2119] [RFC8174]에서 설명한 대로, 오직 이와 같이 대문자로 등장하는 경우에만 해당 의미로 해석되어야 합니다.

알고리즘의 일부로 명령문 형태("선행 공백 문자를 모두 제거한다" 또는 "false를 반환하고 이 단계를 중단한다" 등)로 기술된 요구 사항은, 알고리즘 도입 시 사용된 키워드("must", "should", "may" 등)의 의미로 해석해야 합니다.

어트리뷰트, 메서드, 오브젝트에 대한 요구 사항은 사용자 에이전트에 대한 요구 사항으로 해석해야 합니다.

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

3. 개념

3.1 네트워크 요청

네트워크 요청사용자 에이전트가 특정 HTTP-네트워크 fetch를 통해 네트워크 상의 리소스를 요청(request) 하려고 시도할 때 발생합니다.

request는 사용자 에이전트가 오프라인임이 확인될 때(즉, navigator. onLinefalse를 반환할 때) 네트워크 요청을 발생시키면 안 됩니다(MUST NOT).

request는 혼합 콘텐츠(mixed content)나 CORS 실패로 인해 차단된 경우 네트워크 요청을 발생시키면 안 됩니다(MUST NOT). 모든 CORS-사전요청(preflight request)은 반드시 별도의 네트워크 요청발생시켜야 합니다(MUST).

참고

[FETCH] 표준에 따라 요청을 처리하는 사용자 에이전트에서 네트워크 요청HTTP-네트워크 fetch 알고리즘이 한 번 실행되는 것에 해당합니다.

어떤 fetch 알고리즘, 어떤 하위 애플리케이션 및 전송 프로토콜을 사용하든, 네트워크 요청의 처리는 다음의 단계로 이루어집니다:

  1. DNS 해석: 사용자 에이전트는 DNS [RFC1034]를 사용해 도메인 이름을 IP 주소로 변환하여 서버를 찾고, 해당 서버가 HTTP 요청을 서비스할 수 있도록 합니다.
  2. 보안 연결 설정: 사용자 에이전트는 서버에 연결을 열고, 이를 통해 보안 채널을 설정합니다.
  3. 요청 및 응답 전송: 보안 채널이 설정되면, 사용자 에이전트는 HTTP 요청을 전송하고, 응답서버로부터 수신할 수 있습니다.

단계 중 필수적인 것은 요청 및 응답 전송 단계뿐이며, 나머지 단계들은 모든 네트워크 요청에서 필요하지 않을 수도 있습니다. 예를 들어, DNS 결과를 사용자 에이전트에 로컬로 캐시하면 동일 도메인에 대한 이후 요청에서 DNS 해석 단계를 생략할 수 있습니다. 마찬가지로, HTTP 지속 연결(persistent connections)을 활용하면 동일 네트워크 파티션 키에 대해 여러 요청이 하나의 연결을 공유할 수 있습니다. 그러나 여러 단계가 발생하는 경우, 위에 명시된 순서로 진행됩니다.

에디터의 주

이러한 단계의 정의를 [FETCH] 명세로 옮겨 재사용성을 높이고자 합니다.

네트워크 요청은 사용자 에이전트가 서버로부터 유효한 HTTP 응답을 받고, 그 응답이 4xx 또는 5xx 상태 코드를 포함하지 않을 때 성공한 것으로 간주됩니다.

네트워크 요청성공하지 않은 경우 실패한 것으로 간주됩니다.

참고

HTTP 오류 응답(즉, 4xx 또는 5xx 상태 코드 포함)은 실패로 간주되어 NEL 정책실패 샘플링 비율의 적용을 받으며, 성공 샘플링 비율이 적용되지 않습니다.

3.2 네트워크 오류

네트워크 오류네트워크 요청실패하게 만든 오류 상태입니다.

네트워크 오류는 문자열로 된 유형(type)을 가집니다.

네트워크 오류단계(phase)를 가지며, 이는 해당 오류가 어느 단계에서 발생했는지를 나타냅니다:

dns
오류가 DNS 해석 중에 발생함
connection
오류가 보안 연결 설정 중에 발생함
application
오류가 요청 및 응답 전송 중에 발생함

여러 사전 정의된 네트워크 오류 유형6. 사전 정의된 네트워크 오류 유형에 정의되어 있습니다.

3.3 네트워크 오류 보고서

네트워크 오류 보고서Reporting API보고로, 네트워크 오류를 설명합니다.

네트워크 오류 보고서리포트 유형(report type)network-error입니다.

네트워크 오류 보고서절대 ReportingObserver에게 보이지 않습니다.

참고

네트워크 오류 보고서ReportingObserver에 노출되지 않는 것은, 해당 보고서가 요청을 수신하는 서버의 소유자 또는 관리자에게만 노출되도록 의도되었기 때문입니다. 만약 ReportingObserver에 노출되면, 보고서가 요청자(originator)에게도 노출되며, 교차 오리진 요청의 경우 서버의 네트워크 구성 정보가 외부로 유출될 수 있습니다.

3.4 NEL 정책

NEL 정책은 사용자 에이전트에게 특정 네트워크 요청오리진에 대해 보고를 수집할지, 그리고 보고서를 어디로 전송할지를 지시합니다. NEL 정책은 HTTP 응답 헤더(response headers)를 통해 사용자 에이전트로 전달됩니다.

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

NEL 정책오리진을 가집니다.

NEL 정책하위 도메인(flag)을 가지며, 이 값은 include 또는 exclude입니다.

NEL 정책요청 헤더 리스트응답 헤더 리스트를 가지며, 각각 헤더 이름의 목록입니다.

NEL 정책은 리포팅 그룹을 가지며, 이는 본 정책에 대한 보고가 전송될 리포팅 엔드포인트 그룹의 이름입니다.

NEL 정책은 정책이 유효한 초 단위의 ttl 값을 가집니다.

NEL 정책은 사용자 에이전트가 정책을 수신한 시점을 나타내는 생성 시각(creation)을 가집니다.

NEL 정책은, 생성 시점부터 생성 시각에서 월 시계(wall clock)허용되지 않은 현재 시간까지 172800초(48시간)보다 크면 만료(stale)된 것으로 간주합니다.

NEL 정책은, 생성 시각부터 생성 시각에서 월 시계허용되지 않은 현재 시간까지 ttl (초 단위)보다 클 때 만료(expired)된 것으로 간주합니다.

3.5 샘플링 비율

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

NEL 정책은 0.0~1.0 범위의 성공 샘플링 비율을 가집니다.

NEL 정책은 0.0~1.0 범위의 실패 샘플링 비율을 가집니다.

3.6 정책 캐시

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

이 저장 메커니즘은 불투명, 벤더별, 웹에 노출되지 않지만, 본 명세에 정의된 알고리즘에서 사용할 다음의 메서드를 반드시(MUST) 제공합니다:

4. 정책 전달

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

4.1 NEL 응답 헤더

NEL 응답 헤더는 오리진의 NEL 정책을 사용자 에이전트에게 전달하는 데 사용됩니다. ABNF(Augmented Backus-Naur Form) [RFC5234] 문법에서 NEL 헤더의 구문은 다음과 같습니다:

NEL = json-field-value

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

사용자 에이전트는 본 명세에 정의된 문법에 맞지 않는 알 수 없거나 잘못된 필드나 값은 반드시(MUST) 무시해야 합니다. 유효한 NEL 헤더는 최소한 이 명세에서 정의된 모든 "REQUIRED" 필드를 포함한 객체를 하나 이상 가져야 합니다(MUST).

사용자 에이전트는 오류 보고의 하이재킹을 방지하기 위해 meta 요소를 통한 NEL 헤더를 반드시(MUST) 무시해야 합니다. NEL 정책은 반드시 NEL 응답 헤더로 전달되어야 합니다.

참고

meta 요소에 대한 제한은 [CSP] 명세와 일치하며, 동일한 이유로 보고 등록이 오직 HTTP 헤더 필드에서만 가능하게 합니다.

4.1.1 report_to 멤버

report_to 멤버는 이 엔드포인트 그룹NEL 정책의 보고가 전송될 대상을 지정합니다. report_to 멤버는 NEL 정책 등록 시 필수(REQUIRED)이며, 이전 등록 제거 목적일 경우 선택적(OPTIONAL)입니다. – max_age 참고. 만약 존재한다면, 값은 반드시(MUST) 문자열이어야 하며, 다른 타입이면 파싱 오류가 발생합니다.

참고

NEL 보고서의 전달률을 높이기 위해, 서버report_to 값을, 리소스가 가져와지는 오리진과 인프라가 분리된 대체 오리진의 엔드포인트를 하나 이상 포함하는 엔드포인트 그룹으로 설정하는 것이 바람직합니다. 그렇지 않으면 문제 해결 전까지 네트워크 오류가 보고되지 않을 수 있으며, 여러 엔드포인트를 제공하면 일부 엔드포인트가 접속 불가일 때에도 대안이 제공될 수 있습니다.

4.1.2 max_age 멤버

필수(REQUIRED) max_age 멤버는 이 NEL 정책의 유효기간을 초 단위의 0 이상의 정수로 지정합니다. 값은 반드시(MUST) 0 이상의 정수여야 하며, 다른 타입이면 파싱 오류가 발생합니다.

0 값은 이 NEL 정책오리진에 대해 정책 캐시에서 제거됨을 의미합니다.

참고

NEL 보고서의 전달을 보장하려면, 서버는 리포팅 엔드포인트 그룹 역시 충분히 큰 max_age로 설정해야 합니다. 만약 리포팅 정책이 만료되면, NEL 정책이 만료되지 않았더라도 NEL 보고서는 전달되지 않습니다.

4.1.3 include_subdomains 멤버

선택(OPTIONAL) include_subdomains 멤버는 이 오리진의 모든 하위 도메인(깊이 제한 없음)에 해당 NEL 정책을 활성화할지 여부를 결정하는 불리언 값입니다. 객체에 include_subdomains란 멤버가 없거나 값이 true가 아니면, NEL 정책이 하위 도메인에 대해 활성화되지 않습니다.

참고

하위 도메인에 대한 NEL 보고서를 보장하려면, 애플리케이션은 리포팅 엔드포인트 그룹include_subdomains를 활성화하여 설정해야 합니다. 리포팅 정책에 이 항목이 없고, 해당 하위 도메인에 대한 별도 리포팅 정책이 없다면, NEL 정책에 하위 도메인이 포함되어 있더라도 보고서는 전달되지 않습니다.

4.1.4 success_fraction 멤버

선택(OPTIONAL) success_fraction 멤버는 이 오리진에 대한 성공 네트워크 요청 보고에 적용할 샘플링 비율을 정의합니다. 값이 있을 경우 반드시(MUST) 0.0~1.0 사이의 수여야 하며, 다른 값이면 파싱 오류입니다. 이 멤버가 없으면 사용자 에이전트는 이 오리진의 성공 네트워크 요청에 대해 NEL 보고서를 수집하지 않습니다.

4.1.5 failure_fraction 멤버

선택(OPTIONAL) failure_fraction 멤버는 이 오리진에 대한 실패 네트워크 요청 보고에 적용할 샘플링 비율을 정의합니다. 값이 있을 경우 반드시(MUST) 0.0~1.0 사이의 수여야 하며, 다른 값이면 파싱 오류입니다. 이 멤버가 없으면 사용자 에이전트는 이 오리진의 모든 실패 네트워크 요청에 대해 NEL 보고서를 수집합니다.

4.1.6 request_headers 멤버

선택(OPTIONAL) request_headers 멤버는 이 오리진에 대한 요청 헤더이름네트워크 오류 보고서에 포함할 목록을 정의합니다. 값이 존재한다면 반드시(MUST) 문자열의 리스트여야 합니다.

4.1.7 response_headers 멤버

선택(OPTIONAL) response_headers 멤버는 이 오리진에 대한 응답 헤더이름네트워크 오류 보고서에 포함할 리스트를 정의합니다. 값이 존재하면 반드시(MUST) 문자열의 리스트여야 합니다.

4.2 정책 헤더 처리

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

  1. 다음 조건 중 하나라도 참이면 이 단계를 중단(abort)합니다:
  2. originrequest오리진으로 설정합니다.
  3. key네트워크 파티션 키 결정 알고리즘 결과로 설정합니다(requestreserved client 인자 사용).
  4. headerNEL이라는 응답 헤더의 값으로 설정합니다.
  5. list를 [HTTP-JFV]의 Section 4에서 정의된 알고리즘을 사용해 header에 대해 수행한 결과로 설정합니다. 알고리즘이 오류를 반환하거나 list가 비어 있으면 이 단계를 중단합니다.
  6. itemlist의 첫 번째 요소로 설정합니다.
  7. itemmax_age란 멤버가 없거나 멤버의 값이 숫자가 아니면 이 단계를 중단합니다.
  8. itemmax_age 값이 0이면, 정책 캐시에서 originorigin인 모든 NEL 정책을 삭제하고 이후 단계는 건너뜁니다.
  9. itemreport_to 멤버가 없거나 그 값이 문자열이 아니면 이 단계를 중단합니다.
  10. itemsuccess_fraction 멤버가 있고, 값이 0.0~1.0 범위가 아니면 이 단계를 중단합니다.
  11. itemfailure_fraction 멤버가 있고, 값이 0.0~1.0 범위가 아니면 이 단계를 중단합니다.
  12. itemrequest_headers 멤버가 있고, 값이 리스트가 아니거나 리스트의 요소 중 문자열이 아니면 이 단계를 중단합니다.
  13. itemresponse_headers 멤버가 있고, 값이 리스트가 아니거나 리스트의 요소 중 문자열이 아니면 이 단계를 중단합니다.
  14. policy를 새 NEL 정책으로 생성하고, 다음 속성으로 설정합니다:

    수신 IP 주소
    사용자 에이전트가 response를 받은 서버의 IP 주소
    에디터의 주

    [FETCH]에서 좀 더 명확히 연결 예정.

    오리진
    origin
    하위 도메인 플래그
    includeiteminclude_subdomains 멤버가 있고 그 값이 true일 때, 아니면 exclude
    요청 헤더
    itemrequest_headers
    응답 헤더
    itemresponse_headers
    리포팅 그룹
    itemreport_to
    ttl
    itemmax_age
    생성 시각
    월 시계허용되지 않은 현재 시간
    성공 샘플링 비율
    itemsuccess_fraction 값(존재 시), 없으면 0.0
    실패 샘플링 비율
    itemfailure_fraction 값(존재 시), 없으면 1.0
  15. 정책 캐시에 (key, origin)에 해당하는 엔트리가 이미 있으면 policy로 대체하고, 없으면 정책 캐시policy를 추가합니다.

5. 보고서 전달

5.1 요청에 대한 정책 선택

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

  1. originrequestorigin으로 설정합니다.
  2. keyrequest네트워크 파티션 키 결정의 결과로 설정합니다(reserved client 사용).
  3. 정책 캐시에 (key, origin) 엔트리가 있으면:
    1. policy를 해당 엔트리로 설정합니다.
    2. policy만료(expired)되지 않았다면, 그것을 반환합니다.
  4. origin상위도메인 일치(superdomain match)인 각각의 parent origin에 대해:
    1. 정책 캐시에 (key, parent origin) 엔트리가 있으면:
      1. policy를 해당 엔트리로 설정합니다.
      2. policy만료(expired)되지 않았고, 서브도메인(subdomains) 플래그가 include라면, 그것을 반환합니다.
  5. 정책 없음(no policy)을 반환합니다.

5.2 요청 헤더 추출

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

  1. headers를 새로운 비어있는 ECMAScript 객체로 만듭니다.
  2. policy요청 헤더 리스트의 각 header name에 대해:
    1. request헤더 리스트포함하지 않으면, 리스트의 다음 header name로 넘어갑니다.
    2. values를 비어있는 ECMAScript 리스트로 지정합니다.
    3. request헤더 리스트 중, 이름header name과 일치하는 header 각각에 대해, headervalues에 추가합니다.
    4. header name을 이름으로, values를 값으로 하는 새 프로퍼티를 headers에 추가합니다.
  3. headers를 반환합니다.

5.3 응답 헤더 추출

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

  1. headers를 새로운 비어있는 ECMAScript 객체로 만듭니다.
  2. policy응답 헤더 리스트의 각 header name에 대해:
    1. response헤더 리스트포함하지 않으면, 리스트의 다음 header name으로 넘어갑니다.
    2. values를 비어있는 ECMAScript 리스트로 설정합니다.
    3. response헤더 리스트 중, 이름header nameheader 각각에 대해, headervalues에 추가합니다.
    4. header name을 이름으로, values를 값으로 하는 새 프로퍼티를 headers에 추가합니다.
  3. headers를 반환합니다.

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

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

  1. requestorigin에 대해 "Is origin potentially trustworthy?" 알고리즘의 결과가 Potentially Trustworthy가 아니면 null을 반환합니다.
  2. originrequestorigin으로 설정합니다.
  3. policy5.1 요청에 대한 정책 선택request에 대해 실행한 결과로 설정합니다. 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
    리소스 fetch 시작부터 사용자 에이전트가 완료 또는 중단할 때까지 경과된 밀리초(ms).
    phase
    request실패한 경우, 단계(phase)네트워크 오류의 단계입니다. request성공한 경우, "application"입니다.
    type
    request실패했다면, 유형(type)네트워크 오류의 유형입니다. request성공이라면, "ok"입니다.
  7. report bodyphase 속성이 dns가 아니라면, 아래 프로퍼티를 report body에 추가합니다:
    server_ip
    사용자가 요청을 전송한 서버의 IP 주소(가능할 경우), 아니면 빈 문자열.
    • IPv4 주소는 점으로 구분된 4개의 0~255 십진수 a.b.c.d 형식입니다 [RFC1123]
    • IPv6 주소는 8개의 16비트 블록을 x:x:x:x:x:x:x:x로 표현하며, x는 각 블록의 1~4자리 16진수입니다 [RFC4291]
    protocol
    리소스 fetch에 사용된 네트워크 프로토콜(ALPN Protocol ID, 가능할 경우), 아니면 "".
  8. report bodyphase 속성이 dns 또는 connection이 아니라면, 아래 프로퍼티를 report body에 추가합니다:
    referrer
    request의 referrer(해당 referrer policy에 따라 결정)
    method
    requestHTTP 메서드
    request_headers
    5.2 요청 헤더 추출requestpolicy로 실행한 결과
    response_headers
    5.3 응답 헤더 추출responsepolicy로 실행한 결과
    status_code
    HTTP 응답의 상태 코드(가능한 경우), 없으면 0
  9. originpolicyorigin과 다르고, policysubdomains 플래그가 include이며, report bodyphasedns가 아니라면 null을 반환합니다.
    참고

    이 단계는 하위 도메인 NEL 정책정책 오리진의 하위 도메인에 대해 DNS 해석 단계에서만 보고서 생성을 허용함을 보장합니다. 자세한 내용은 9. 프라이버시 고려사항 참조.

  10. report bodyphase 속성이 dns가 아니고, server_ip 값이 비어있지 않고 policy수신 IP 주소와 다르다면:
    1. report bodyphasedns로 변경합니다.
    2. report bodytypedns.address_changed로 변경합니다.
    3. report bodyrequest_headers, response_headers, status_code, elapsed_time 프로퍼티를 초기화합니다.
    4. report bodyDNS 해석 단계에서 제공되지 않는 모든 필드는 비워졌는지 확인합니다.
    참고

    이 단계는 서버의 IP 주소와 정책의 IP 주소가 일치하지 않을 경우 NEL 보고서를 "다운그레이드"합니다. 이는 프라이버시 보호를 위한 조치로, NEL 보고서가 보고서에 명시된 서비스 소유자에게만 전송되도록 보장합니다. 만약 두 IP 주소가 일치하지 않는다면, 사용자 에이전트는 NEL 정책origin도메인 이름 소유자에 의해 전달된 것임만 확인할 수 있고, 정책이 이 서버도메인 이름 해석 결과와 연결된 서버 소유자에 의해 전달된 것임은 확인할 수 없습니다. 따라서 보고서는 DNS 해석 정보만 포함하도록 다운그레이드됩니다. 자세한 내용은 9. 프라이버시 고려사항7.5 여러 IP 주소를 가진 오리진을 참조하세요.

  11. policystale(오래된) 상태라면, 정책 캐시에서 policy를 삭제합니다.
  12. report bodypolicy를 반환합니다.

5.5 네트워크 보고서 전달

ECMAScript 객체(report body, 보통 네트워크 오류 보고서 생성에서 반환되고 상위 명세에 의해 보강됨)와, 일치하는 NEL 정책 (policy), 네트워크 요청(request)이 주어지면, 이 알고리즘은 보고서를 큐잉해 전송합니다.

  1. urlrequest의 URL로 설정합니다.

  2. urlfragment를 비웁니다.

  3. report bodyphasedns 또는 connection이면:

    1. url경로(path)쿼리(query)를 비웁니다.

  4. 네트워크 보고서 생성을 다음 파라미터로 실행합니다:

    type
    network-error
    data
    report body
    endpoint group
    policyreporting group
    url
    urlURL serializer를 적용한 결과

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

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

사용자 에이전트는 이 목록에 커스텀 네트워크 오류 유형을 확장할 수 있습니다 (MAY) — 예를 들어 새로운 프로토콜 대응, 또는 기존 오류의 더 세부적인 설명에 대응하기 위함입니다. 이 경우 사용자 에이전트는 오류 리포트의 단순하고 일관된 처리를 위해 SHOULD 점(.)으로 구분된 패턴([group].[optional-subgroup].[error-name])을 유형명에 따라야 합니다. 예를 들어 수집기는 카테고리별 또는 한 개 이상의 하위 그룹별 집계를 지원할 수 있습니다.

6.1 DNS 해석 오류

이 절의 모든 네트워크 오류DNS 해석 중에 발생하며, 단계(phase)dns입니다.

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

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 연결이 잘못된 인증기관(Authority)으로 중단됨
tls.cert.invalid
TLS 연결이 잘못된 인증서로 중단됨
tls.cert.revoked
TLS 연결이 폐기(revoked)된 서버 인증서로 중단됨
tls.cert.pinned_key_not_in_cert_chain
핀 고정된 키가 인증서 체인에 없어 TLS 연결이 중단됨
tls.protocol.error
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
리소스 fetch가 완료되기 전에 사용자가 중단함
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일) 동안 적용됩니다.

위 등록은 응답이 신뢰할 수 있는 오리진(potentially trustworthy origin)에서 전달된 경우에만 성공합니다.

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

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

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

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

이 섹션은 등록된 NEL 정책이 있는 오리진에서 네트워크 오류가 발생할 때, 사용자 에이전트가 큐잉할 수 있는 네트워크 오류 보고서의 예제를 포함합니다. 보고 업로드 시 생성되는 전체 전송 페이로드 예시를 보여주며, payload의 body 필드는 네트워크 오류 리포트 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밀리초 후 사용자 에이전트가 탐색을 중단하였고, 네트워크 오류 발생 즉시 이 보고서를 보냈습니다(리포트 age: 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를 가져오려고 시도했으나, widget.com의 DNS 이름을 해석할 수 없어 143밀리초 후 요청이 중단되었음을 나타냅니다. 이전 widget.com 요청에서 유효한 NEL 정책을 받았기 때문에 이 요청에 대해 네트워크 오류 보고서가 생성되며, 오류 발생 직후 업로드되었습니다(리포트 age: 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_headersresponse_headers 필드를 포함하면, 브라우저는 해당 요청에 대해 생성되는 모든 NEL 보고서에 If-None-Match 요청 헤더와 ETag 응답 헤더 사본을 포함하며, 사이트 소유자가 캐시 정책의 효과를 추적할 수 있게 합니다.

이에 따라 다음과 같은 시나리오를 생각해 볼 수 있습니다:

  1. 사용자 에이전트가 requestexample.com에 보내고, response를 성공적으로 수신합니다. 응답에는 리소스 버전을 나타내는 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으로 request를 보냅니다. 에이전트는 원본 리소스의 캐시 사본을 여전히 가지고 있고, 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.comrequest를 보냅니다. 에이전트는 같은 사본을 가지고 있고, 이전과 같이 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 주소를 가진 세 서버에 의해 운영된다고 가정합니다. 서비스 소유자가 DNS를 example.com에 대해 192.0.2.1, 192.0.2.2, 192.0.2.3으로 해석되게 구성하고, 사용자 에이전트가 세 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.1request를 보내고, response를 성공적으로 수신합니다. 해당 응답에는 위 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.2request를 보내고, 또 다른 response를 성공적으로 수신합니다. 이 응답에도 NEL 정책이 포함되어 있고, 수신 IP 주소192.0.2.2로 갱신됩니다. 역시 서버 IP와 일치하므로 다음과 같은 보고서가 생성됩니다:

    {
      "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으로 request를 보냈으나 서버에 연결할 수 없습니다. 정책의 수신 IP 주소(192.0.2.2)가 해당 요청의 IP와 일치하지 않으므로, tcp.timed_out 대신 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로 시도해도 마찬가지로 정책의 수신 IP 주소가 마지막으로 192.0.2.2로 기록되어 있으므로, 다운그레이드 보고서가 생성됩니다:

    {
      "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 1차 자원 하위요소 불러오기 실패 보고

일반적인 애플리케이션은 수십 개의 리소스를 필요로 하며, 이러한 리소스들은 주로 HTML, CSS, JavaScript 등을 통해 불러오기(fetched)됩니다. 리소스를 요청하는 애플리케이션은 대부분 이러한 fetch 실패를(예: onerror 콜백 등으로) 감지할 수 있지만, 실패의 자세한 네트워크 오류(DNS 실패, TCP 오류, TLS 프로토콜 위반 등) 원인에 대한 보고는 알 수 없습니다.

이 점을 해결하기 위해, 애플리케이션은 하위 리소스를 불러오는 1차 호스트들에 대해 사용자 에이전트에 적절한 NEL 정책을 등록할 수 있습니다. 그런 다음, 해당 정책이 있고 등록된 origin의 리소스에서 네트워크 오류가 발생하면, 사용자 에이전트가 자세한 네트워크 오류 리포트를 보고하여 애플리케이션 개발자가 원인을 조사할 수 있게 됩니다.

8.3 3차 자원 하위요소 불러오기 실패 보고

리소스가 3차 제공자에 의해 삽입된 경우, 리소스 제공자는 실패를 계측하거나 관찰할 수 없는 경우가 많습니다. 예를 들어 example.com이 사이트에 widget.com/thing.js 리소스를 삽입하였고, example.com을 방문한 사용자가 네트워크 오류로 해당 리소스 로드에 실패했을 때, widget.com 호스트는 이러한 실패를 모를 뿐 아니라 감지할 수도 없습니다.

이런 상황을 해결하기 위해 widget.com은 자신의 호스트에 대해 NEL 정책을 등록할 수 있습니다. 그런 다음 정책이 존재하고, 해당 origin에서 네트워크 오류가 발생하면(1차 또는 3차 오리진에서 요청되었는지와 무관하게), 사용자 에이전트는 네트워크 오류를 보고하여 제공자가 문제를 조사할 수 있도록 합니다.

9. 프라이버시 고려사항

NEL은 사용자의 네트워크 구성에 대한 새로운 정보를 노출할 수 있는 네트워크 오류 보고서를 제공합니다. 예를 들어, 공격자는 NEL 보고를 악용해 사용자의 네트워크 구성을 탐색하거나 내부 네트워크의 서버를 스캔할 수 있습니다. 또한 HSTS, HPKP, 고정 CSP 정책과 유사하게, 저장된 NEL 정책을 각 사용자별로 맞춤화한 리포트 URI를 통해 식별자로 써서(HTTP 쿠키 조합 혹은 대체) "슈퍼쿠키(supercookie)"로 사용할 수 있습니다.

이러한 위험 완화를 위해 NEL 등록 및 네트워크 오류 보고서 전달 모두 신뢰할 수 있는 오리진에만 제한됩니다. 이는 임시 HTTP MITM 공격자가 NEL을 영속적 추적기로 악용하는 것을 어렵게 만듭니다.

또한, NEL 정책 캐시네트워크 파티션 키 단위로 분할되기 때문에, 한 임베딩 컨텍스트에 저장된 NEL 정책이 다른 컨텍스트(예: 다른 최상위 사이트에 임베딩)에서 사용되지 않습니다.

NEL은 기존의 서버 모니터링을 보완하도록 설계되었습니다. NEL 보고서는 오직 요청 대상 서비스 소유자에게만 전송되어야 합니다. DNS 해석 단계 오류에서는, NEL 정책을 해당 도메인 네임스페이스 트리 소유자에게서 받은 경우에만 보고가 생성됩니다. 보안 연결 설정 또는 요청 및 응답 전송 단계 오류의 경우, NEL 정책을 해당 서버 소유자에게서 받은 경우에만 보고가 생성됩니다.

위 정책의 수신 IP 주소서브도메인 플래그 처리 이유도 이것과 관련됩니다. 정책의 수신 IP 주소서버의 IP와 일치하는지 검사함으로써, NEL은 정책의 신뢰 경계를 오리진 뿐 아니라 실제 통신하는 서버까지 확대합니다. 이는 공격자가 소유한 서버에서 장기 NEL 정책을 배포하고, 이후 자신의 네임서버를 바꿔 오리진을 자신이 소유하지 않은 서버로 해석하게 해 사용자 에이전트가 해당 서버 정보를 공격자에게 보고하는 것을 방지합니다. (즉, DNS 리바인딩 공격 예방)

마찬가지로, 서브도메인 NEL 정책은 제한되어 있으며, 정책 오리진의 하위 도메인에 대해서도 DNS 해석 단계(phase)에서만 보고서를 생성할 수 있습니다. 이 단계에서는 소유자 확인을 위한 서버가 없으며, 정책이 requestorigin의 상위도메인에서 내려왔는지만으로 소유권을 확인합니다. 이를 통해 특정 도메인 소유자가 7.3 DNS 오구성 오류를 감지할 수 있으나, 악의적 DNS 엔트리를 통한 정보 수집은 차단됩니다.

정보 유출을 방지하기 위해, NEL은 request에 대해 서버가 요청 처리 시 접근할 수 없는 정보는 포함하지 않습니다. DNS 해석 오류의 경우 NEL 보고서는 오로지 DNS에서 확인 가능한 정보만 포함합니다. 이는 서버가 NEL을 통해 사용자의 추가 정보를 수집하는 것을 차단합니다. 다만, NEL 보고서에는 server_ip 필드에 웹사이트의 공개 IP가 포함되며, 예컨대 서비스가 로드밸런서 뒤에 있거나 투명 프록시(MitM)가 있는 경우 서비스 소유자가 반드시 이를 아는 것은 아닙니다.

참고

예를 들어, NEL 보고서는 특정 DNS 리졸버(resolver)를 통해 request도메인 이름을 해석했는지에 관한 정보는 포함하지 않습니다.

위와 같은 제한 외에도, 사용자 에이전트는 반드시(MUST) 다음을 해야 합니다:

NEL을 배포하는 개발자는 지정 수집기(collector)로 전송되는 NEL 보고서의 프라이버시 영향을 반드시(should) 고려해야 합니다. 예를 들어, 보고서에 민감한 데이터가 포함된 URL(예: "Capability URLs")이 실릴 수 있으며, 이에 대해 특별한 조치가 필요할 수 있습니다([CAPABILITY-URLS] 참고). 이런 경우 이를 제3자에게 전송하지 않도록 자체 NEL 수집기를 운영해야 할 수도 있습니다.

10. IANA 고려사항

permanent message header field registry는 다음 등록사항들로 갱신되어야 합니다([RFC3864] 참고):

10.1 NEL

헤더 필드 이름
NEL
적용 프로토콜
http
상태
표준
작성자/변경 컨트롤러
W3C
명세 문서
이 명세(자세한 내용은 NEL response header 참고)

A. 색인

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

A.2 참조에 의해 정의된 용어

B. 감사의 글

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

C. 참고 문헌

C.1 표준 참고 문헌

[CAPABILITY-URLS]
Good Practices for Capability URLs. Jeni Tennison. W3C. 2014년 2월 18일. FPWD. URL: https://www.w3.org/TR/capability-urls/
[CSP]
Content Security Policy Level 3. Mike West; Antonio Sartori. W3C. 2025년 4월 30일. W3C Working Draft. URL: https://www.w3.org/TR/CSP3/
[ECMA-262]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[fetch]
Fetch Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://fetch.spec.whatwg.org/
[hr-time]
High Resolution Time. Yoav Weiss. W3C. 2024년 11월 7일. W3C Working Draft. URL: https://www.w3.org/TR/hr-time-3/
[html]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[HTTP-JFV]
A JSON Encoding for HTTP Header Field Values. J. Reschke. IETF. 2017년 10월 24일. Active Internet-Draft. URL: https://datatracker.ietf.org/doc/html/draft-reschke-http-jfv
[infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[mixed-content]
Mixed Content. Emily Stark; Mike West; Carlos IbarraLopez. W3C. 2023년 2월 23일. CRD. URL: https://www.w3.org/TR/mixed-content/
[network-reporting]
Network Reporting API. W3C. Editor's Draft. URL: https://w3c.github.io/reporting/network-reporting.html
[referrer-policy]
Referrer Policy. Jochen Eisinger; Emily Stark. W3C. 2017년 1월 26일. W3C Candidate Recommendation. URL: https://www.w3.org/TR/referrer-policy/
[REPORTING]
Reporting API. Douglas Creager; Ian Clelland; Mike West. W3C. 2024년 8월 13일. W3C Working Draft. URL: https://www.w3.org/TR/reporting-1/
[RESOURCE-TIMING-2]
Resource Timing. Yoav Weiss; Noam Rosenthal. W3C. 2025년 2월 13일. CRD. URL: https://www.w3.org/TR/resource-timing/
[RFC1034]
Domain names - concepts and facilities. P. Mockapetris. IETF. 1987년 11월. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc1034
[RFC1123]
Requirements for Internet Hosts - Application and Support. R. Braden, Ed. IETF. 1989년 10월. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc1123
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. 1997년 3월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC3864]
Registration Procedures for Message Header Fields. G. Klyne; M. Nottingham; J. Mogul. IETF. 2004년 9월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc3864
[RFC4291]
IP Version 6 Addressing Architecture. R. Hinden; S. Deering. IETF. 2006년 2월. Draft Standard. URL: https://www.rfc-editor.org/rfc/rfc4291
[RFC5234]
Augmented BNF for Syntax Specifications: ABNF. D. Crocker, Ed.; P. Overell. IETF. 2008년 1월. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc5234
[RFC6797]
HTTP Strict Transport Security (HSTS). J. Hodges; C. Jackson; A. Barth. IETF. 2012년 11월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6797
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. 2017년 5월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC9110]
HTTP Semantics. R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. 2022년 6월. Internet Standard. URL: https://httpwg.org/specs/rfc9110.html
[RFC9112]
HTTP/1.1. R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. 2022년 6월. Internet Standard. URL: https://httpwg.org/specs/rfc9112.html
[secure-contexts]
Secure Contexts. Mike West. W3C. 2023년 11월 10일. CRD. URL: https://www.w3.org/TR/secure-contexts/
[url]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/