1. 소개
이 섹션은 규범적이지 않습니다.
현재, 사용자 에이전트는 일반적으로 각 요청에 User-Agent HTTP 요청 헤더 필드를 서버에 함께 전송하여 자신을 식별합니다( [rfc9110] 5.5.3절에 정의됨).
이상적으로는, 이 헤더가 서버에게 콘텐츠 협상 능력을 제공해, 해당 사용자 에이전트에 가장 적합한 리소스를 전송함으로써 대역폭과 사용자 경험 모두를 최적화할 수 있어야 합니다. 하지만 실제로 이
헤더 값은 기본값으로 보기엔 너무 많은 정보를 사용자 기기에 대해 노출하고, 동시에 잘못된 서버 측 휴리스틱을 우회하기 위해 진짜 사용자 에이전트를 의도적으로 숨기기도 합니다.
예를 들어, 최신 버전의 iOS용 Chrome은 아래와 같이 자신을 식별합니다:
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X)
AppleWebKit/605.1.15 (KHTML, like Gecko)
CriOS/69.0.3497.105 Mobile/15E148 Safari/605.1
최신 버전의 Edge는 아래와 같이 자신을 식별합니다:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.2704.79
Safari/537.36 Edge/18.014
이 문자열들에는 꽤 많은 정보(그리고 거짓 정보도 다수)가 포함되어 있습니다. 버전 번호, 플랫폼 정보, 모델 정보 등이 모든 요청과 함께 전송되며, 다양한 지문 채취 기법의 기반이 됩니다. 개별 벤더들은 자신의 사용자 에이전트 문자열을 변경하려 시도했고, 개발자들로부터 여러 가지 피드백 범주를 받아왔습니다. 이는 기존 방식의 발전을 막는 요인이 되었습니다:
-
브랜드 및 버전 정보(예: "Chrome 69")는 사이트가 감지 불가능한 특정 릴리즈의 알려진 버그를 우회할 수 있게 해줍니다. 예를 들어, 콘텐츠 보안 정책의 구현은 벤더마다 크게 달랐으며, 어떤 브라우저가 파싱과 실행을 담당하는지 모르면 어떤 정책을 HTTP 응답에 포함해야 할지 알기 어렵습니다.
-
개발자들은 종종 사용자 에이전트와 플랫폼에 따라 어떤 콘텐츠를 보낼지 협상합니다. 예를 들어, 일부 애플리케이션 프레임워크는 iOS와 Android에서 각각의 미적·디자인 패턴에 맞게 스타일을 다르게 적용합니다.
-
1번과 유사하게, OS 버전과 아키텍처는 특정 버그의 원인이 될 수 있으며, 웹사이트 코드에서 이를 우회하거나, 다운로드할 적절한 실행파일(32/64비트, ARM/Intel 등)을 선택하는 데 활용됩니다.
-
숙련된 개발자들은 모델/제조정보를 활용하여 사이트를 기기 성능에 맞게 최적화하고(예: [FacebookYearClass]), 성능 버그 및 회귀가 특정 모델/제조사에 국한될 때 이를 정확히 파악합니다.
이 문서는 User-Agent 문자열에서 엔트로피를 더 적극적으로 제거할 수 있는 메커니즘을 제안합니다. 서버가 클라이언트에 대한 특정 정보가 정말 필요할 때만 해당 정보를
받을 수 있도록 옵트인할 수 있습니다. 이 문서는 클라이언트의 브랜드/버전 정보, OS 브랜드/주요 버전, 그리고 기기 정보 등을 제공하는 새로운 클라이언트 힌트([RFC8942])들을 소개합니다. 이 데이터는
항상 모든 곳에 브로드캐스트 되는 대신, 사용자 에이전트가 더 세분화된 데이터 요청에 대해 적절하게 응답함으로써 수동 지문 채취 노출 영역을 줄일 수 있습니다( 최고 모범 사례 1 및 [FINGERPRINTING-GUIDANCE] 참고).
1.1. 예시
이 섹션은 규범적이지 않습니다.
사용자가 최신 버전의 "Examplary Browser"로 https://example.com/에 처음 진입합니다. 이때 사용자 에이전트는 HTTP 요청에 아래와 같은
헤더를 포함해 전송합니다:
Sec-CH-UA: "Examplary Browser"; v="73", ";Not?A.Brand"; v="27" Sec-CH-UA-Mobile: ?0 Sec-CH-UA-Platform: "Windows"
서버가 사용자의 기본 플랫폼 버전에 맞는 콘텐츠를 렌더링하고자 할 때, 초기 응답에 Accept-CH 헤더( [RFC8942] 2.2.1절)로 정보를 더 요청합니다:
Accept-CH: Sec-CH-UA-Platform-Version
이에 대해 사용자 에이전트는 다음 요청에 플랫폼 버전 정보를 포함합니다:
Sec-CH-UA: "Examplary Browser"; v="73", ";Not?A.Brand"; v="27" Sec-CH-UA-Mobile: ?0 Sec-CH-UA-Platform: "Windows" Sec-CH-UA-Platform-Version: "14.0.0"
1.2. 활용 사례
이 섹션은 규범적이지 않습니다.
이 섹션은 User-Agent 문자열의 현재 활용 방식과, 유사한 기능을 User-Agent Client Hints(UA-CH)로 어떻게 구현할 수 있는지 문서화합니다.
1.2.1. 차등 제공
1.2.1.1. 브라우저 기능 기반
이 활용 사례는 polyfill.io 같은 서비스가 최신 브라우저 사용자에게 불필요한 폴리필을 제공하지 않고, 맞춤 폴리필만 제공할 수 있게 지원합니다.비슷하게, 사용자의 브라우저가 최신 ES 기능을 지원한다면 자바스크립트 전환(transpilation)을 피할 수 있고, 이는 코드의 비대화와 비효율을 막아줍니다. 또한, 이미지를 제공할 때 일부
브라우저는 Accept 요청 헤더를 업데이트하지 않거나 MIME 타입만으로는 동일 포맷의 다양한 변종을 구분하기 힘든 경우(WebP 등)가 있습니다. 이런 경우에는
브라우저와 버전 정보를 아는 것이 올바른 이미지를 제공하는 데 중요합니다.
이 활용 사례가 동작하려면, 서버는 브라우저와 의미 있는 버전을 알고, 이를 사용 가능한 기능 목록과 매핑해야 합니다. 이를 통해 어떤 폴리필이나 코드 변종을 제공해야 하는지 알 수 있습니다.
UA-CH를 사용하는 서비스는 모든 요청에 기본적으로 전송되는 Sec-CH-UA 헤더를 검사하고, 이에 따라 응답을 수정해야 합니다.
1.2.1.2. 브라우저 버그 우회
일부 브라우저 버전에는 잘 알려진 버그가 존재하며, 해당 버그를 우회하기 위해 콘텐츠에서 별도 처리가 필요합니다. 이런 버그가 발생하면 브라우저가 충돌하거나 콘텐츠가 깨지는 등 문제가 생기며, 해당 버그는 기능 탐지로 감지할 수 없습니다. 따라서 영향을 받는 브라우저 버전에 대해서는 콘텐츠에서 해당 문제를 완전히 회피해야 합니다.이 활용 사례에서는 서버가 브라우저와 의미 있는 버전을 파악하고, 해당 브라우저 버전에 영향을 주는 버그를 인지하며, 그 버전에 대해 우회 처리를 적용해야 합니다.
UA-CH를 사용하는 서비스는 모든 요청에 기본적으로 전송되는 Sec-CH-UA 헤더를 검사하여 응답을 수정해야 합니다.
1.2.2. 시장 점유율 분석
브라우저의 시장 점유율은 매우 중요할 수 있습니다. 브라우저 사용 현황을 파악하면 개발자들이 특정 브라우저에서 테스트를 늘려 사용자 호환성 문제를 줄일 수 있습니다. 또한, 시장 점유율은 브라우저 벤더의 비즈니스 목표에도 직접적인 영향을 주며, 브라우저의 향후 개발을 보장합니다.시장 점유율 분석을 위해서는 서버가 아래 중 하나 이상을 파악해야 합니다: 사용자 에이전트 이름과 그 의미 있는 버전, 운영체제 및 버전, 기기 모델. 이를 등록하고 상대적 시장 점유율을 산출할 수 있습니다.
UA-CH로 시장 점유율 분석을 하고자 하는 사이트는 모든 요청에 기본적으로 전송되는 Sec-CH-UA 헤더를 기록해야 하며, 추가적인 UA 클라이언트 힌트가 활용 사례에
따라 요청될 수 있습니다(예: 모바일 기기 모델 분석).
설계상, 브랜드 리스트 각각을 개별적으로 보면 덜 인기 있는 브라우저의 실제 브랜드와 인기 있는 브라우저의 임의 GREASE를 구분하기 어렵습니다. 덜 인기 있는 브라우저는 호환성을 위해 여러 인기 브랜드 이름을 포함할 수 있으므로, 이 방식으로 시장 점유율을 집계하면 인기 있는 브라우저의 사용자로 분류되어 덜 인기 있는 브라우저가 가시성을 얻지 못할 수 있습니다.
따라서 분석 목적으로는 브랜드 리스트 전체를 하나의 단위로 취급해, 구분하려는 (브라우저, 버전) 쌍이 보내는 브랜드 리스트와 비교하는 것이 좋습니다. 이 방법을 쓰려면, 새로운 브라우저 버전이 출시되거나 새로운 브라우저가 인기 있을 때 브랜드 리스트 목록을 정기적으로 업데이트해야 하며, 그렇지 않으면 모두 미확인 브라우저로 분류됩니다. 하지만 이런 경우 사이트가 깨지지는 않으므로, 미확인 브라우저에 대해 폐쇄적으로 대응해도 괜찮습니다.
이러한 브랜드 리스트 목록은 중앙 집중식으로 관리되어 많은 사이트에서 사용할 수 있습니다(예: caniuse와 MDN에서 브라우저 기능 지원을 관리하고 많은 웹마스터가 활용하는 것처럼).
명세에서는 브라우저가 버전별로 고정된 브랜드 리스트를 전송하도록 권장합니다. 이렇게 하면 사용량 집계가 간단해지고 캐싱에도 도움이 되며, 브랜드 리스트와 (브라우저, 버전) 쌍의 간단한 매핑으로 구현할 수 있습니다.
1.2.3. 콘텐츠 적응
콘텐츠 적응이란 사용자의 필요에 맞게 콘텐츠를 맞춤화하는 것입니다. UA 문자열 외에도 콘텐츠 적응에는 다양한 차원이 있습니다: 뷰포트 크기, 기기 메모리, 사용자 선호도 등. 이 하위 섹션에서는 현재User-Agent 문자열에 포함된 정보에
기반한 콘텐츠 적응 요구를 다룹니다.
1.2.3.1. 브라우저 기반 적응
일부 사이트는 서로 다른 브라우저에 약간씩 다른 콘텐츠를 제공합니다. 그 이유는 다양합니다. 일부는 기능 지원 차이로 인해 다양한 경험을 제공하기 위함이고(정당한 이유), 일부는 해당 브라우저에서 테스트되지 않았음을 경고하기 위함입니다(덜 정당한 이유). 일부는 특정 브라우저 사용자를 사이트 접근에서 차단하려는 경우도 있습니다(명백히 잘못된 이유).브라우저로서 우리는 첫 번째 목적은 지원하고, 후자는 지양하고자 합니다.
1.2.3.2. 모바일 특화 사이트
많은 사이트 운영자는 모바일과 데스크탑 사이트 간에 다른 콘텐츠를 제공합니다. 반응형 웹 디자인 덕분에 단일 코드베이스로 다양한 폼팩터 지원이 가능하지만, 여전히 모바일 특화 버전을 제공하는 것이 더 나은 경우가 있습니다.이런 경우에는 모바일 기기 사용자에게 모바일 특화 사이트를 제공하는 것이 도움이 됩니다. 이를 위해 서버는 HTML 제공 시점에 사용자가 모바일 기기인지 아닌지를 파악해야 합니다.
UA-CH를 활용하여 모바일 특화 사이트를 제공하려는 사이트는 모든 요청에 기본적으로 전송되는 Sec-CH-UA-Mobile 헤더를 사용할 수 있습니다.
1.2.3.3. 저사양 기기
일부 사이트는 CPU 집약적 작업, 대용량 영상·이미지 등을 처리할 수 없는 저사양 기기에 대해 다른 콘텐츠를 제공합니다. 이런 콘텐츠 적응은 주로 현재User-Agent
문자열에 포함된 기기 모델 정보를 사용하며, 서버 측 데이터베이스로 기기 모델을 메모리, CPU 성능 등으로 분류해 콘텐츠를 나눕니다.
분류 기준이 메모리인 경우 Device-Memory Client Hint를 사용할 수 있습니다. 그 외에는 UA-CH를 통해 Sec-CH-UA-Model 힌트로 기기 모델을
얻을 수 있습니다.
이 두 힌트 모두 기본값으로 전송되지 않으므로, 추가 작업이 필요합니다.
최상위 오리진은 Accept-CH: Device-Memory, Sec-CH-UA-Model 헤더를 응답에 포함해 해당 힌트 수신에 옵트인해야 합니다. 모든 탐색 요청에서
적응이 꼭 필요하다면, 브라우저가 해당 힌트를 지원하지만 없는 경우 리다이렉트가 필요합니다. 또는 Critical-CH를 사용해 클라이언트가 추가 요청/응답 라운드트립을 처리하게 할 수도
있습니다.
이런 적응이 필요한 서드파티 오리진은 위임이 필요합니다.
최상위 오리진은 Accept-CH로 옵트인하고, Permissions-Policy 헤더로 해당 힌트를 서드파티에 위임해야 합니다.
1.2.3.4. OS 특화 스타일
일부 사이트는 사용자의 OS에 맞춘 인터페이스를 제공하기를 원할 수 있습니다. 점진적 개선 방식(예: 스크립트로 버튼 스타일을 다르게 적용)이 더 바람직할 수 있지만, 플랫폼 및 플랫폼 버전에 따라 인라인 스타일을 서버에서 맞춤 제공하는 경우도 있습니다.이 경우는 위 "저사양 기기" 사례와 유사하며, Sec-CH-UA-Platform 및 Sec-CH-UA-Platform-Version 힌트를 활용하면
됩니다.
1.2.3.5. OS 통합
비슷하게, 일부 사이트는 OS별 링크(예: Android 인텐트 링크)를 제공하기를 원할 수 있습니다. 역시 점진적 개선 방식으로 스크립트로 링크를 수정하는 것이 더 바람직하지만, 일부 사이트는 서버 측 적응을 선호할 수 있습니다.이 경우에도 "OS 특화 스타일"과 같이 Sec-CH-UA-Platform 및 Sec-CH-UA-Platform-Version 힌트를 사용하면
됩니다.
1.2.3.6. 브라우저 및 OS 특화 실험
일부 서버는 다중 변종 실험을 특정 브라우저, 특정 플랫폼, 또는 그 버전에 제한하고자 할 수 있습니다. 브라우저와 버전 한정 실험은Sec-CH-UA 값을 사용하고, 플랫폼과
버전까지 필요하면 Sec-CH-UA-Platform 힌트(기본값)를 쓰고, Sec-CH-UA-Platform-Version 힌트는 별도 요청하거나
클라이언트 측 스크립트로 실험을 제어해야 합니다.
1.2.4. 사용자 로그인 알림
특히 보안 민감 사이트는 새로운 기기에서 로그인이 발생할 때 사용자를 알리기를 선호합니다. 사용자는 해당 로그인을 인지하고 자신이 직접 하거나 대리한 로그인이 아니라면 조치를 취할 수 있습니다.이런 알림이 의미 있으려면, 사이트는 브라우저의 상업 브랜드를 인식하여 사용자에게 전달해야 합니다. 메시지에는 플랫폼 및 버전도 포함되어 사용자가 어떤 기기인지 알 수 있게 합니다.
이런 메시지는 서버 측 적응이 필요 없으므로, userAgentData.getHighEntropyValues() 메서드로 필요한 정보를 얻는 것이 더 좋습니다.
1.2.5. 적합한 바이너리 실행파일 다운로드
일부 사이트는 네이티브 애플리케이션의 바이너리 실행파일 다운로드를 지원하며, 사용자에게 올바른 바이너리를 제안해야 합니다. 적합한 바이너리는 운영체제, 버전, 비트수, CPU 아키텍처 등 여러 요소에 따라 달라집니다.이 활용 사례를 해결하려면 다운로드 사이트가 Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version,
Sec-CH-UA-Arch, Sec-CH-UA-Bitness 힌트(혹은 API를 통한 쿼리)를 옵트인하여 사용자에게 기본값으로 맞는 바이너리를
제공합니다.
1.2.6. 전환 모델링
일부 머신러닝 모델은User-Agent 문자열의 다양한 정보를 활용해 사용자에 대해 여러 가지를 추정합니다. 유사 모델링도 가능하지만, 필요한 정보를 수집하려면 명시적으로
옵트인을 해야 합니다.
1.2.7. 취약점 필터링
일부 환경에서는 프록시 서버가 구식 기기에서 접근하는 사용자를 차단하여 보안 취약점을 방지합니다.Sec-CH-UA를 통해 브라우저 및 버전 정보를 얻을 수 있지만, 브라우저와
OS의 전체 버전 정보가 추가 분석에 유용합니다.
이런 프록시는 리다이렉트 단계를 추가하거나, 브라우저 및 플랫폼 버전 힌트 수신에 옵트인하는 Client Hint 신뢰성 메커니즘 중 하나를 사용해야 계속 해당 힌트에 접근할 수 있습니다.
1.2.8. 로그 및 디버깅
많은 서비스가User-Agent 문자열을 기록하며, 과거 트래픽 분석이나 에러 디버깅에 활용합니다. 이런 서비스는 기록 목적으로 Sec-CH-UA의
저엔트로피 값을 사용하거나, 고엔트로피 힌트 수신을 옵트인해야 합니다. 후자는 단순 포렌식 목적으로는 적합하지 않습니다. 반면, 특정 이슈 발생 시에는 추가 정보를 받거나
userAgentData.getHighEntropyValues() API를 사용할 수 있습니다.
1.2.9. 지문 채취
사용자 지문 채취란 여러 출처에서 다양한 사용자 정보를 수집·교차해 고유한 사용자 식별자를 생성하는 행위로, 이는 사용자가 브라우저의 상태를 초기화해도(예: 쿠키 삭제) 이후 다시 식별할 수 있게 합니다.
이 경우에는 오리진이 가능한 많은 엔트로피를 수집하려 하므로, 모든 힌트를 수집할 가능성이 높습니다.
1.2.9.1. 스팸 필터링 및 봇 감지
이는 사용자에게 불리하지 않은 지문 채취 사례로, UA-CH에서는 다양한 힌트의 능동적 수집으로 가능합니다.향후에는 브라우저가 사용자를 대신해 수집 엔트로피를 제한(예: Privacy Budget 제안)함으로써 스팸 필터링 및 봇 감지에 대한 대체 방법이나 API가 나오길 기대합니다.
1.2.9.2. 지속적인 사용자 추적
이 사례는 명시적으로 더 어렵게 하려는 지문 채취입니다. "스팸 필터링" 사례와 마찬가지로 모든 힌트의 능동 수집은 가능하지만, Privacy Budget 등의 제안은 이를 방지하며, 지속적 사용자 추적을 위한 대체 메커니즘은 제공하지 않습니다.1.2.9.3. 알려진 봇 및 크롤러 차단
현재User-Agent 문자열은 알려진 봇 및 크롤러를 차단하는 단순한 수단으로 자주 사용됩니다. "일반" 트래픽이 기본적으로 더 적은 엔트로피를 노출하면 봇이 군중 속에 숨기
쉬워질 수 있다는 우려가 있습니다. 하지만 이 때문에 군중을 더 쉽게 식별 가능하게 만드는 것은 정당하지 않습니다.
스팸 필터링 사례와 마찬가지로, 향후 User-Agent 문자열 매칭을 대체할 방법이 나오길 기대합니다.
2. 인프라
이 명세는 Client Hints Infrastructure, HTTP Client Hints, Infra Standard, Permissions Policy에 의존합니다. [CLIENT-HINTS-INFRASTRUCTURE] [RFC8942] [INFRA] [permissions-policy-1]
이 명세에서 사용하는 일부 용어는 HTTP를 위한 구조화된 필드 값에서 정의됩니다. [rfc9651]
3. 유저 에이전트 힌트
다음 섹션에서는 서버가 유저 에이전트에 대한 세부 정보를 노출하는 여러 HTTP 요청 헤더 필드를 정의합니다. 서버는 [RFC8942]에서 정의한 Client Hints 인프라를 통해 해당 정보를 받을 수 있도록 옵트인할 수 있습니다. 아래 정의는 각 유저 에이전트가 자신에 대해 여러 속성을 정의했다고 가정합니다:
-
brand - 유저 에이전트의 상업적 이름(예: "cURL", "Edge", "The World’s Best Web Browser")으로, 32 ASCII alpha 문자 미만이어야 합니다.
-
form-factors - 장치의 폼팩터로, 기존에는 User-Agent 문자열 내 <deviceCompat> 토큰으로 표현됨(예: "Tablet", "VR" 등)
-
full version - 해당 유저 에이전트 또는 brands 리스트 내 브랜드의 빌드 버전(예: "72.0.3245.12", "3.14159", "297.70E04154A")
-
model - 유저 에이전트의 장치 모델(예: "", 또는 "Pixel 2 XL")
-
mobileness - 유저 에이전트의 장치가 모바일 기기인지 나타내는 불리언 값(예: ?0 또는 ?1)
-
platform brand - 유저 에이전트의 운영체제 상업적 이름(예: "Windows", "iOS", "AmazingOS")
-
platform version - 유저 에이전트의 운영체제 버전(예: "NT 6.0", "15", "17G")
-
platform architecture - 유저 에이전트의 CPU 아키텍처(예: "ARM", "x86")
-
platform bitness - 유저 에이전트의 CPU 아키텍처 비트수(예: "32" 또는 "64")
-
significant version - 웹에 노출되는 주요 기능을 포함한 마케팅 버전(예: "72", "3", "12.1")으로, 해당 유저 에이전트 또는 brands 리스트 내 모든 브랜드(예: 렌더링 엔진 또는 동등 클래스의 full version)에 해당함.
-
wow64-ness - 유저 에이전트의 바이너리가 64비트 Windows에서 32비트 모드로 실행 중인지 나타내는 불리언 값(예: ?0 또는 ?1)
사용자 에이전트는 이러한 문자열을 짧고 명확하게 유지하는 것이 좋지만, 서버는 각 값에 대해 임의의 값을 반드시 허용해야 합니다. 이는 모두 사용자 에이전트가 임의로 구성한 값입니다.
사용자 에이전트는 고엔트로피 플랫폼 아키텍처 값을 다음 버킷으로 매핑해야 합니다:
-
x86 CPU 아키텍처 => "x86"
-
ARM CPU 아키텍처 => "arm"
기타 CPU 아키텍처는 경우에 따라 이 값 중 하나로 매핑되거나, 빈 문자열로 매핑될 수 있습니다.
사용자 에이전트는 플랫폼 아키텍처 또는 플랫폼 비트수에 대해 사용자의 플랫폼이 다음 두 조건을 모두 충족하지 않는 한, 빈 문자열 또는 허구의 값을 반환하는 것이 좋습니다:
-
실행 파일의 바이너리 다운로드가 예상됨.
-
서로 다른 CPU 아키텍처가 서로 다른 바이너리 실행 파일 리소스를 요구할 가능성이 높으며, 이러한 리소스가 제공될 가능성이 높음.
User agents는 mobileness 가 false일 경우 model에 대해 반드시 빈 문자열을 반환해야 한다. User agents는 model에 대해, mobileness가 true이더라도 일반적으로 모델 정보가 노출되는 플랫폼이 아닌 한, 빈 문자열을 반환해야 한다.
User
agents는 다음 힌트들에 대해 요청이 있을 때, 프라이버시, 호환성 또는 기타 이유로
sf-string 타입의 힌트에는 빈 문자열,
sf-boolean 타입의 힌트에는 false,
또는 기타 임의의 값(fictitious value)을 반환할 수 있다:
full
version, platform architecture, platform bitness,
wow64-ness 또는
model.
-
환경 설정에 연관된 에뮬레이트된 UA Client Hints를 에뮬레이트된 client hints로 한다.
-
만약 에뮬레이트된 client hints가 null이 아니고, 에뮬레이트된 client hints의 property가 undefined가 아니라면, 에뮬레이트된 client hints의 property를 반환한다.
-
property의 구현-정의 값을 반환한다.
3.1. 'Sec-CH-UA' 헤더 필드
Sec-CH-UA 요청 헤더 필드는 서버에 사용자 에이전트의 브랜딩 및 중요 버전 정보를 제공합니다. 이는 Structured Header이며, 값은 반드시 리스트 [rfc9651]여야 합니다.
리스트의 항목은 반드시 문자열이어야 하며, 각 항목의 값에는 "v" 파라미터(즉, 사용자 에이전트의 버전)가 포함되는 것이
좋습니다.
헤더의 ABNF는 다음과 같습니다:
Sec-CH-UA = sf-list
요청에 대한 Sec-CH-UA 값을
반환하려면 다음 단계에 따라 수행합니다:
-
brands는 "중요 버전"으로 브랜드 생성을 실행한 결과로 합니다.
-
list는 brands와 "중요 버전"으로 브랜드-버전 리스트 생성을 실행한 결과로 합니다.
-
그 후 list로 리스트 직렬화를 실행한 결과를 반환합니다.
참고: 대부분의 클라이언트 힌트와 달리 저엔트로피 힌트 테이블에 포함되므로, Sec-CH-UA 헤더는 서버가
Accept-CH 헤더를 통해 수신을 선택하지 않았더라도 기본적으로 전송됩니다(단, 정책 제어 클라이언트 힌트 기능에 의해 여전히 제어할 수 있습니다.)
저엔트로피로 간주되는 이유는 사용자 에이전트의 브랜딩 정보와 중요 버전 번호만 포함되기 때문이며, 둘 다 "다른 헤더의 구조를 조사하거나 각 브라우저의 특정
릴리스에서 도입·수정된 기능의 존재·동작을 테스트"함으로써 명확히 식별할 수 있습니다. [Janc2014]
참고: Sec-CH-UA는 브랜드 목록의 각 브랜드에 대해 주요
버전을 공개합니다. 전체 버전이 필요한 경우는 전체 버전 및 Sec-CH-UA-Full-Version-List를
참조하세요.
3.2. 'Sec-CH-UA-Arch' 헤더 필드
Sec-CH-UA-Arch 요청 헤더 필드는 서버에 특정 user
agent가 실행 중인 플랫폼의 아키텍처 정보를 제공합니다.
이것은 Structured
Header이며 값은 반드시 string이어야 합니다
[rfc9651].
헤더의 ABNF:
Sec-CH-UA-Arch = sf-string
3.3. 'Sec-CH-UA-Bitness' 헤더 필드
Sec-CH-UA-Bitness 요청 헤더 필드는 주어진 user
agent가 실행되고 있는 플랫폼의 아키텍처 platform bitness에 대한 정보를 서버에 제공합니다. 이것은 Structured
Header이며, 값은 반드시 string이어야 합니다
[rfc9651].
해더의 ABNF는 다음과 같습니다:
Sec-CH-UA-Bitness = sf-string
3.4. 'Sec-CH-UA-Form-Factors' 헤더 필드
Sec-CH-UA-Form-Factors 요청 헤더 필드는 서버에 user
agent의 form-factors에 대한 정보를 제공합니다. 이는 Structured Header이며, 값은 반드시 list여야 합니다 [rfc9651]. 추가 지문 채취 엔트로피를 제공하지 않기 위해, 헤더의 값들은 반드시 사전 순서로
제공되어야 하며, 값은 대소문자를 구분합니다.
해더는 다음의 일반적인 form-factor 값 중 하나 이상("Desktop", "Automotive", "Mobile", "Tablet", "XR", "EInk", "Watch")을 사용하여 기기의 form-factor를 설명해야 합니다. 해당되는 모든 form-factor 값은 반드시 포함되어야 합니다.
user-agent의 form-factor는 사용자가 user-agent와 상호작용하는 방식을 설명합니다. 허용되는 값의 의미는 다음과 같습니다:
-
"Desktop"은 개인용 컴퓨터에서 실행되는 user-agent를 나타냅니다.
-
"Automotive"는 차량에 내장되어 사용자가 차량 조작을 책임지고 있어 세부적인 내용에 신경을 쓰기 어려운 환경에서 동작하는 user-agent를 나타냅니다.
-
"Mobile"은 사용자가 평소에 지니고 다니는, 작고 터치 기반의 기기를 나타냅니다.
-
"Tablet"은 "Mobile"보다 크고, 일반적으로 사용자가 휴대하지 않는 터치 기반 기기를 나타냅니다.
-
"XR"은 사용자를 둘러싼 환경을 증강하거나 대체하는 몰입형 장치를 나타냅니다.
-
"EInk"는 화면 갱신이 느리고 색상 해상도가 없거나 매우 제한적인 기기를 나타냅니다.
-
"Watch"는 매우 작은 화면(일반적으로 2 in 미만)을 가진, 사용자가 빠르게 확인할 수 있도록 착용하는 형태의 모바일 기기를 나타냅니다.
사용자가 의미 있게 다르게 상호작용하는 새로운 form-factor가 등장하고, 사이트가 해당 장치에서 사용자와의 상호작용 방식을 바꾸고자 하는 충분한 사용사례가 있으며, 기존 힌트로 해당 form-factor를 신뢰성 있게 식별할 수 없는 경우에는 새로운 값을 제안하여 명세에 추가해야 합니다.
해더의 ABNF는 다음과 같습니다:
Sec-CH-UA-Form-Factors = sf-list
3.5. 'Sec-CH-UA-Full-Version' 헤더 필드
Sec-CH-UA-Full-Version은 더 이상 사용되지 않으며 향후 제거될 예정입니다. 개발자들은 Sec-CH-UA-Full-Version-List를 대신 사용해야
합니다.
Sec-CH-UA-Full-Version 요청 헤더 필드는 사용자 에이전트의
전체 버전 정보를
서버에 제공합니다. 이것은 Structured Header이며, 값은 반드시 문자열이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Full-Version = sf-string
3.6. 'Sec-CH-UA-Full-Version-List' 헤더 필드
Sec-CH-UA-Full-Version-List 요청 헤더 필드는
각 브랜드에 따른 전체 버전 정보를
서버에 제공합니다. 이것은 Structured Header이며, 값은 반드시 리스트여야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Full-Version-List = sf-list
요청에 대한
Sec-CH-UA-Full-Version-List 값을 반환하려면, 다음 단계들을 수행합니다:
-
brands에 "full version"으로 브랜드 생성을 실행한 결과를 할당합니다.
-
list에 brands와 "full version"으로 브랜드-버전 리스트 생성을 실행한 결과를 할당합니다.
-
리스트 직렬화(serializing a list)를 list에 대해 실행한 출력을 반환합니다.
3.7. 'Sec-CH-UA-Mobile' 헤더 필드
Sec-CH-UA-Mobile 요청 헤더 필드는 user
agent가 "모바일" 사용자 경험을 선호하는지에 대한 정보를 서버에 제공합니다. 이것은 Structured Header이며, 값은 반드시 불리언이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Mobile = sf-boolean
참고: Sec-CH-UA와 마찬가지로, low entropy hint table에 포함되어 있기 때문에
Sec-CH-UA-Mobile 헤더는 서버가 Accept-CH 헤더를 통해 명시적으로 요청하지 않았더라도 기본적으로 전송됩니다(물론 정책 제어
클라이언트 힌트 기능으로 제어할 수 있음). 이것은 사용자가 직접 제어할 수 있는 1비트 정보이기 때문에 낮은 엔트로피로 간주됩니다.
3.8. 'Sec-CH-UA-Model' 헤더 필드
Sec-CH-UA-Model 요청 헤더 필드는 특정 user
agent가 실행되고 있는 기기(device)에 대한 정보를 서버에 제공합니다. 이것은 Structured Header이고, 값은 반드시 문자열이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Model = sf-string
3.9. 'Sec-CH-UA-Platform' 헤더 필드
Sec-CH-UA-Platform 요청 헤더 필드는 특정 user
agent가 실행되고 있는 플랫폼에 대한 정보를 서버에 제공합니다. 이것은 Structured Header이며, 값은 반드시 문자열이어야 합니다 [rfc9651]. 값은 "Android", "Chrome OS", "Fuchsia", "iOS",
"Linux", "macOS", "Windows", "Unknown" 등 공통 플랫폼 값 중 하나와 일치하는 것이 좋습니다.
헤더의 ABNF:
Sec-CH-UA-Platform = sf-string
참고: Sec-CH-UA와 마찬가지로, low entropy hint table에 포함되어 있어 Sec-CH-UA-Platform
헤더도 서버가 Accept-CH를 통해 명시적으로 요청하지 않았더라도 기본적으로 전송됩니다(물론 정책 제어 클라이언트 힌트 기능으로 제어 가능).
3.10. 'Sec-CH-UA-Platform-Version' 헤더 필드
Sec-CH-UA-Platform-Version 요청
헤더 필드는 서버에
주어진 플랫폼
버전에 대한 정보를 제공하며,
해당 버전에서 사용자 에이전트가 실행되고 있는지를 알려준다.
이 헤더는 구조화
헤더이며 값은 문자열[rfc9651]이어야 한다.
값은 플랫폼 버전
가져오기를 플랫폼 브랜드와 함께 수행한 결과값이다.
플랫폼 버전 가져오기를 실행하려면, 문자열 platform이 주어졌을 때 다음 단계를 수행한다:
-
platform이 "Linux" 또는 "Fuchsia"이면:
-
빈 문자열을 반환합니다.
-
-
platform이 "Android"이면:
-
platformReturnedVersionString에 OS의
android.os.Build.VERSION.RELEASE스트링을 할당합니다. -
통합된 플랫폼 버전 문자열 생성을 platformReturnedVersionString으로 실행한 결과를 반환합니다.
-
-
platform이 "iOS"이면:
-
currentDevice로 반환된UIDevice객체에서systemVersion속성을 읽어 platformReturnedVersionString에 할당합니다. -
통합된 플랫폼 버전 문자열 생성을 platformReturnedVersionString으로 실행한 결과를 반환합니다.
-
-
platform이 "Windows"이면:
-
(Windows 10 이상에서 사용 가능할 경우)
Windows.Foundation.UniversalApiContract의 정수 값을 쿼리하여 문자열로 변환해 platformReturnedVersionString에 할당합니다. 그렇지 않으면 레거시 Windows 버전 번호 구하기 결과를 할당합니다. -
통합된 플랫폼 버전 문자열 생성을 platformReturnedVersionString으로 실행한 결과를 반환합니다.
-
-
platformVersionComponentList라는 리스트를 만듭니다.
-
platform이 "macOS"이면:
-
processInfo정보 에이전트로 얻은NSProcessInfo의operatingSystemVersion속성 값을 macOSVersion에 할당합니다. -
추가를 사용해 macOSVersion의
majorVersion,minorVersion,patchVersion순으로 platformVersionComponentList에 추가합니다.
-
-
platform이 다른 값이면:
-
연결을 사용해 platformVersionComponentList를 U+002E FULL STOP (
.) 구분자로 합친 결과를 반환합니다.
레거시 Windows 버전 번호 구하기는 다음 단계로 동작합니다:
-
GetVersionExWin32 API에서OSVERSIONINFO의dwMajorVersion값을 major에 할당 -
dwMinorVersion값을 minor에 할당 -
만약 major가
6이고 minor가3이면("Windows 8.1"), "0.3" 반환 -
만약 major가
6이고 minor가2이면("Windows 8"), "0.2" 반환 -
만약 major가
6이고 minor가1이면("Windows 7"), "0.1" 반환 -
그 외의 경우 "0" 반환
통합된 플랫폼 버전 문자열 생성은 문자열 input이 주어졌을 때 다음과 같이 동작합니다:
-
platformVersionComponentList라는 리스트를 만들고 index를 0으로 설정
-
platformVersionUnprocessedTokenList에 엄격 분할(strictly splitting)로 input을 U+002E FULL STOP(
.)으로 나눈 리스트를 할당 -
index가 3 미만인 동안:
-
연결을 사용해 platformVersionComponentList를 U+002E FULL STOP(
.) 구분자로 합친 결과 반환
헤더의 ABNF:
Sec-CH-UA-Platform-Version = sf-string
3.11. 'Sec-CH-UA-WoW64' 헤더 필드
Sec-CH-UA-WoW64 요청 헤더 필드는
서버에 64비트 Windows에서 32비트 모드로 실행 중인 user agent 바이너리 여부에 대한 정보를 제공합니다.
이 헤더는 Structured Header이며, 값은 반드시 boolean이어야 합니다
[rfc9651].
이 헤더의 ABNF는 다음과 같습니다:
Sec-CH-UA-WoW64 = sf-boolean
참고: 다음의 client hints token 집합을 통해 이들 client hints를 요청할 수 있습니다:
Sec-CH-UA, Sec-CH-UA-Arch, Sec-CH-UA-Bitness,
Sec-CH-UA-Form-Factors,
Sec-CH-UA-Full-Version, Sec-CH-UA-Full-Version-List,
Sec-CH-UA-Mobile, Sec-CH-UA-Model,
Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA-WoW64
4. 인터페이스
dictionary {NavigatorUABrandVersion DOMString ;brand DOMString ; };version dictionary {UADataValues DOMString ;architecture DOMString ;bitness sequence <NavigatorUABrandVersion >;brands sequence <DOMString >;formFactors sequence <NavigatorUABrandVersion >;fullVersionList DOMString ;model boolean ;mobile DOMString ;platform DOMString ;platformVersion DOMString ; // fullVersionList로 대체됨uaFullVersion boolean ; };wow64 dictionary {UALowEntropyJSON sequence <NavigatorUABrandVersion >;brands boolean ;mobile DOMString ; }; [platform Exposed =(Window ,Worker )]interface {NavigatorUAData readonly attribute FrozenArray <NavigatorUABrandVersion >;brands readonly attribute boolean ;mobile readonly attribute DOMString ;platform Promise <UADataValues >(getHighEntropyValues sequence <DOMString >);hints UALowEntropyJSON (); };toJSON interface mixin { [NavigatorUA SecureContext ]readonly attribute NavigatorUAData ; };userAgentData Navigator includes NavigatorUA ;WorkerNavigator includes NavigatorUA ;
참고: user agent 정보의 high-entropy 부분은 Promise를
통해 가져오며,
이는 user
agent가 노출을 사용자 허락 등 시간 소모가 필요한 검사 뒤로 지연할 수 있도록 하기 위함입니다.
4.1. 처리 모델
4.1.1. WindowOrWorkerGlobalScope
각 user agent는 연관된 brands를 가진다. 이는 리스트이며, significant version과 함께 create brands를 실행해서 생성한다.
모든 WindowOrWorkerGlobalScope
객체는 연관된
brands frozen array를 가진다.
이는
FrozenArray<NavigatorUABrandVersion>이다.
이 초기값은 frozen array 생성을
user
agent의
brands로부터
수행한 결과이다.
또한, 모든 WindowOrWorkerGlobalScope
객체는 연관된
full version list frozen array를 가진다.
이는
FrozenArray<NavigatorUABrandVersion>이다.
이 값은 frozen array 생성을
full
version과 함께
create brands 실행 결과로 얻는다.
4.1.2. brands 생성
create brands를 version type과 함께 요청받으면, 다음 절차를 실행합니다:
-
list라는 리스트를 생성합니다.
-
assert 를 통해 version type이 "full version" 또는 "significant version"임을 확인합니다.
-
각 brand 별로, 해당 user agent 또는 equivalence class를 나타낸다면:
-
version 문자열을 다음과 같이 초기화합니다:
-
version type이 "full version"이면 version을 full version에 해당하는 문자열로 설정
-
version type이 "significant version"이면 version을 significant version에 해당하는 문자열로 설정
-
-
dict라는
NavigatorUABrandVersiondictionary를 만들고,brand를 brand로,version을 version으로 설정 -
append로 dict를 list에 추가
-
-
user agent는 다음 단계를 수행해야 합니다:
-
append로 item을 list에 한 개 추가하며, 해당
NavigatorUABrandVersiondictionary의brand값은 arbitrary brand로,version은 create an arbitrary version의 version type 실행 결과로 설정 -
list의 item 순서를 무작위로 섞음
Note: 이러한 랜덤 요소를 생성할 때 캐싱 차이를 최소화하는 한 가지 방법은 빌드 시점에 값을 결정하고, user agent의 significant version이 지속되는 동안 동일하게 유지하는 것이다.
Note: 이러한 무작위화 단계가 필요한 경우와 그 이유에 대한 자세한 내용은 § 8.2 GREASE와 유사한 UA 브랜드 리스트를 참고하라.
-
-
list를 반환
equivalence class는 서로 호환 가능하다고 여겨지는 브라우저의 집합을 나타냅니다. 예를 들어, 동일 렌더링 엔진을 공유할 경우 equivalence class를 형성할 수 있습니다.
4.1.3. 임의의 brand와 version 값 생성
arbitrary brand 생성을 위해 user agent는 다음 절차를 반드시 실행해야 합니다:
-
arbitraryBrand에 ASCII alpha와 0x20(SP)로 구성된 문자열을 대입. arbitraryBrand에는 하나 이상의 0x20(SP) 바이트가 반드시 포함되어야 하며, 길이는 20 ASCII 바이트 이하여야 하며, 0x20(SP)로 시작하거나 끝나서는 안 됨
-
arbitraryBrandList에 arbitraryBrand를 ASCII 공백으로 분할한 결과를 대입
-
greaseyStack이라는 스택 준비
-
greaseyChars를 ASCII bytes 리스트: « 0x20, 0x28, 0x29, 0x2D, 0x2E, 0x2F, 0x3A, 0x3B, 0x3D, 0x3F, 0x5F » 로 설정
-
index를 0으로 설정
-
index가 arbitraryBrandList의 크기-1보다 작은 동안:
-
greaseyBrandList라는 리스트를 만들고 index를 0으로 설정
-
greaseyStack이 비어있지 않을 동안:
-
append로 arbitraryBrandList[index]를 greaseyBrandList에 추가
-
좌우 ASCII 공백 제거를 greaseyBrandList 연결 결과에 적용, 그 결과 반환
또한 Structured Header에서는 string 내부에 0x22(\")와 0x5C(\\) 이스케이프를 지원하지만, 이 문자들은 방화벽 등에서 호환성 문제를 야기하기도 합니다.
arbitrary version 생성은 version type을 입력받아 다음 절차를 따릅니다:
-
assert를 통해 version type이 "full version" 또는 "significant version"임을 확인
-
arbitrary version이라는 문자열을 다음과 같이 초기화:
-
version type이 "full version"이면, arbitrary version을 full version 포맷에 맞는 임의 문자열로 설정(값은 동일하지 않음)
-
version type이 "significant version"이면, arbitrary version을 significant version 포맷에 맞는 임의 문자열로 설정(값은 동일하지 않음)
-
-
arbitrary version 반환
참고: user agent는 적절한 버전 체크를 보장하기 위해 임의로 낮은 값을 보낼 수 있으며, 그 값은 시간에 따라 변동되어야 합니다.
4.1.4. 브랜드-버전 목록 생성
브랜드-버전 목록 생성을 위해 brands와 version type이 주어지면, 다음 단계를 수행합니다:
-
list를 리스트로, 초기값은 빈 리스트입니다.
-
version type이 "full version" 또는 "significant version"임을 assert합니다.
-
brands의 각 brand에 대해:
-
version을 문자열로, 다음에 따라 초기화:
-
version type이 "full version"이면 version을 full version에 해당하는 문자열로 설정합니다.
-
version type이 "significant version"이면 version을 significant version에 해당하는 문자열로 설정합니다.
-
-
parameter를 딕셔너리로, 초기값은 빈 딕셔너리입니다.
-
parameter["param_key"]를 "v"로 설정합니다.
-
parameter["param_value"]를 version으로 설정합니다.
-
pair를 brand의
brand와 parameter로 구성된 튜플로 설정합니다. -
pair를 list에 추가합니다.
-
-
list를 반환합니다.
4.1.5. Getter
가져올 때, brands
속성은 this의 relevant global object의 brands frozen array를 반환해야 합니다.
가져올 때, mobile
속성은 user
agent의 mobileness를 반환해야 합니다.
가져올 때, platform
속성은 user
agent의 platform brand를 반환해야 합니다.
4.1.6. getHighEntropyValues 메서드
getHighEntropyValues(hints)
메서드는 다음 단계를 실행해야 합니다:
-
p를 a new promise로, current realm에서 생성합니다.
-
uaData를 새로운
UADataValues로 둡니다. -
uaData["
brands"] 값을 this의 relevant global object의 brands frozen array로 설정합니다. -
uaData["
mobile"] 값을 user agent의 mobileness로 설정합니다. -
uaData["
platform"] 값을 user agent의 platform brand로 설정합니다. -
만약 this의 relevant global object의 associated Document가 allowed to use 상태가 아니라면 ch-ua-high-entropy-values 기능에 대해 p를 uaData로 resolve합니다.
-
그렇지 않으면, 다음 단계를 병렬로 실행합니다:
-
hints에 "architecture"가 포함되어 있으면, uaData["
architecture"] 값을 user agent의 platform architecture로 설정합니다. -
hints에 "bitness"가 포함되어 있으면, uaData["
bitness"] 값을 user agent의 platform bitness로 설정합니다. -
hints에 "formFactors"가 포함되어 있으면, uaData["
formFactors"] 값을 user agent의 form-factors로 설정합니다. -
hints에 "fullVersionList"가 포함되어 있으면, uaData["
fullVersionList"] 값을 this의 relevant global object의 full version list frozen array로 설정합니다. -
hints에 "model"이 포함되어 있으면, uaData["
model"] 값을 user agent의 model로 설정합니다. -
hints에 "platformVersion"이 포함되어 있으면, uaData["
platformVersion"] 값을 get the platform version을 platform brand와 함께 실행한 결과로 설정합니다. -
hints에 "uaFullVersion"이 포함되어 있으면, uaData["
uaFullVersion"] -
hints에 "wow64"가 포함되어 있으면, uaData["
wow64"] 값을 user agent의 wow64-ness로 설정합니다. -
Queue a task를 permission task source에 올려 resolve p를 uaData로 합니다.
-
-
p를 반환합니다.
4.1.7. toJSON 메서드
toJSON() 메서드는 다음 단계를 실행해야 합니다:
-
uaLowEntropyData를 새로운
UALowEntropyJSON로 둡니다. -
uaLowEntropyData["
brands"] 값을 this의 relevant global object의 brands frozen array로 설정합니다. -
uaLowEntropyData["
mobile"] 값을 user agent의 mobileness로 설정합니다. -
uaLowEntropyData["
platform"] 값을 user agent의 platform brand로 설정합니다. -
uaLowEntropyData를 반환합니다.
5. 자동화
사용자 에이전트 자동화 및 애플리케이션 테스트를 위해, 이 문서는 [WebDriver-BiDi] 명세에 대한 확장 기능을 정의한다.
5.1. 정의
UserAgentClientHintsCommand = ( userAgentClientHints.SetClientHintsOverrideCommand )
브랜드 버전은 다음을 갖는 구조체입니다:
user agent client hints는 다음을 갖는 구조체입니다:
-
item 이름은 brands이고, brand version 쌍의 리스트 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 full version이고, 문자열 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 full version list이고, brand version 리스트 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 mobile이고, boolean 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 model이고, 문자열 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 platform이고, 문자열 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 platform version이고, 문자열 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 architecture이고, 문자열 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 bitness이고, 문자열 또는 undefined이며, 초기값은 undefined이다.
-
item 이름은 wow64이고, boolean 또는 undefined이며, 초기값은 undefined이다.
remote end는 연관된 emulated client hints를 가진다. 이것은 struct이며, 다음을 포함한다:
-
item 이름은 default emulated client hints이고, user agent client hints 또는 null이며, 초기값은 null이다.
-
item 이름은 emulated client hints per user contexts이고, user context와 user agent client hints 간의 weak map이며, 초기값은 비어 있음이다.
-
item 이름은 emulated client hints per navigables이고, navigables와 user agent client hints 간의 weak map이며, 초기값은 비어 있음이다.
5.2. userAgentClientHints.setClientHintsOverride 명령어
userAgentClientHints.setClientHintsOverride 명령은 navigables 또는 user context들 목록, 혹은 전역적으로 에뮬레이트된 user agent client hints를 설정 또는 제거한다.
- 명령 타입
-
userAgentClientHints.SetClientHintsOverrideCommand= {method:"userAgentClientHints.setClientHintsOverride",params: {clientHints: userAgentClientHints.ClientHintsMetadata / null, ?contexts: [+text], ?userContexts: [+text], } }userAgentClientHints.ClientHintsMetadata= { ?brands: [* userAgentClientHints.BrandVersion], ?fullVersionList: [* userAgentClientHints.BrandVersion], ?platform: text, ?platformVersion: text, ?architecture: text, ?model: text, ?mobile: bool, ?bitness: text, ?wow64: bool, ?formFactors: [* text]; }userAgentClientHints.BrandVersion= {brand: text,version: text } - 반환 타입
-
userAgentClientHints.SetClientHintsOverrideResult= {}
-
related navigables를 get related navigables에 environment settings를 넣어서 얻은 결과로 한다.
-
related navigables의 각 navigable에 대해:
-
top-level navigable을 navigable의 top-level traversable로 한다.
-
user context를 top-level navigable의 associated user context로 한다.
-
에뮬레이트된 client hints의 emulated client hints per navigables에 top-level navigable이 포함되어 있으면 에뮬레이트된 client hints의 emulated client hints per navigables[top-level navigable]을 반환한다.
-
에뮬레이트된 client hints의 emulated client hints per user contexts에 user context가 포함되어 있으면 에뮬레이트된 client hints의 emulated client hints per user contexts[user context]을 반환한다.
-
-
default emulated client hints를 에뮬레이트된 client hints의 default emulated client hints로 한다.
-
default emulated client hints가 null이 아니면 default emulated client hints를 반환한다.
-
null을 반환한다.
remote end steps는 command parameters가 주어졌을 때 다음과 같다:
-
command parameters가 "
userContexts"와 "contexts"를 모두 포함하면, error와 error code invalid argument를 반환한다. -
emulated client hints를 command parameters["
clientHints"]로 한다. -
command parameters가 "
contexts"를 포함하면: -
navigables를 try로 get valid top-level traversables by ids에 command parameters["
contexts"]를 넣어서 얻은 결과로 한다. -
navigables의 각 navigable에 대해:
-
emulated client hints가 null이면 제거 navigable 에뮬레이트된 client hints의 emulated client hints per navigables에서 제거한다.
-
그 외의 경우, set 에뮬레이트된 client hints의 emulated client hints per navigables[navigable]을 emulated client hints로 설정한다.
-
-
success와 data null을 반환한다.
-
command parameters가 "
userContexts"를 포함하면: -
user contexts를 try로 get valid user contexts에 command parameters["
userContexts"]를 넣어서 얻은 결과로 한다. -
user contexts의 각 user context에 대해:
-
emulated client hints가 null이면 제거 user context를 에뮬레이트된 client hints의 emulated client hints per user contexts에서 제거한다.
-
그 외의 경우, set 에뮬레이트된 client hints의 emulated client hints per user contexts[user context]를 emulated client hints로 설정한다.
-
-
success와 data null을 반환한다.
-
Set 에뮬레이트된 client hints의 default emulated client hints를 emulated client hints로 설정한다.
-
success와 data null을 반환한다.
6. Permissions-Policy 연동
이 명세는 문자열
"ch-ua-high-entropy-values"
로 식별되는 정책-제어 기능을 정의하며,
기본 허용 목록은
'*' 입니다. 이는 특정 문서가 고엔트로피 클라이언트 힌트 값을
getHighEntropyValues()
API를 통해 반환할 수 있는지 여부를 결정합니다.
참고: 특정 문서가 "ch-ua-high-entropy-values" 기능
사용이 허용되지 않은 경우,
getHighEntropyValues() API는 편의를 위해 저엔트로피 값을 계속 반환합니다.
7. 보안 및 개인정보 보호 고려사항
7.1. 보안 전송
Client Hints는 비보안 엔드포인트로 전송되지 않습니다(참조: [RFC8942]의 2.2.1절 보안 전송 요건). 즉, user agent 정보가 평문 채널로 유출되지 않아, 네트워크 공격자가 에이전트의 행동 패턴을 시간에 걸쳐 프로파일링할 가능성이 줄어듭니다.
7.2. 위임
Client Hints는 최상위 페이지로부터 Permissions Policy를 통해 위임됩니다 ([permissions-policy-1]). 이는 user agent 정보가 하위 리소스 요청에 같이 전달될 가능성을 줄여, 수동 지문 채취 가능성을 낮춥니다.
이 위임 흐름은 append client hints to request의 일부로 정의됩니다.
7.3. 지문 채취
User Agent Client Hints의 주요 목표는 User-Agent 헤더 필드를 통해 웹에 노출되는 기본 엔트로피의 양을 줄이는 데 있다. 이는 수동 지문 채취(passive fingerprinting)에 악용될 수 있다.
user agent는 제공할 힌트 여부를 스스로 결정할 수 있다. 제공 정보는 수정되지 않은 User-Agent 헤더에 포함될 정보 이상이 아니어야 한다. user agent는 제공을 원치 않는 값에 대해 빈 문자열을 제공하거나, 아예 힌트 반환 자체를 거부할 수 있다.
하지만 일부 또는 모든 힌트는 여전히 1차 또는 위임된 3차 당사자에 의해 능동 지문 채취(active fingerprinting) 목적으로 요청되고 사용될 수 있다. § 7.4 Access Restrictions에서 언급했듯, user agents는 사용자를 능동적으로 지문 채취하는 것으로 알려진 당사자가 접근하지 못하도록 제한하거나 접근을 줄이는 정책을 고려해야 한다.
User agents는 GREASE와 유사한 브랜드 리스트를 통해 개별 사용자 또는 극소수 그룹만을 식별할 수 있는 지문 채취 벡터가 생성되지 않도록 주의해야 한다. 오히려 임의 브랜드 값이 많은 사용자(예: 모든 사용자의 주요 버전별로 안정적으로 공유되는 값) 에게 공유되는 전략이 권장된다.
7.4. 접근 제한
위에서 정의된 Client Hints에 담긴 정보는 user agent 및 해당 장치에 대해 상당히 많은 정보를 드러냅니다. User agents는 이 정보 접근을 허용하기 전에 신중해야 하며, 위의 보안 전송 및 위임 요구사항 외에도 추가 제한을 둘 수 있습니다. 예를 들어 user agents는 플랫폼 아키텍처 또는 플랫폼 비트수 정보를 다운로드 의도가 있는 요청에만 공개하여, 서버가 맞는 바이너리를 제공할 수 있도록 할 수 있습니다. 또한, 사용자에게 어떤 값이 서버에 공개되는지 제어권을 제공하거나, 사용자 명시적 상호작용(권한 팝업, 설정 인터페이스 등)을 통해 접근을 차단할 수 있습니다.
8. 구현 관련 사항
8.1. 'User-Agent' 헤더
User
agents는 User-Agent 헤더의 정보 정밀도(granularity)를 낮게 하여 본 문서에서 설명하는 Client Hints 모델을 우선적으로
사용하도록 하는 것이 바람직합니다.
이 헤더는 단기간 내 완전히 제거되기는 어려운데, 기존 사이트의 콘텐츠 협상 코드가 여전히 필드를 필요로 하기 때문입니다(최근 예시로 [Rossi2015] 참고).
권장되는 한 접근법은 각 user agent가
User-Agent 헤더 값을 고정(lock)하여, 하위 호환성을 위해 "like Gecko"와 "AppleWebKit/537.36" 등의 낡은 선언도 계속 유지하는
것입니다.
시간이 지나면 버전 번호를 먼저 고정(freeze)하고, 이후 플랫폼과 모델 정보를 보다 일반적인 값으로 변경해 지문 정보를 점진적으로 줄이도록 설계할 수 있습니다.
8.2. GREASE 스타일의 UA 브랜드 리스트
과거 사례로 볼 때, user agents는 사이트의 sniffing 스크립트를 우회하고, UA 기반 허용/차단 목록으로 인한 차단을 피하기 위해 자신들의 branding을 속이는 동기가 있었습니다.
기대치 리셋은 단기적으로 brands 목록의 남용을 막을 수 있지만, 장기적으로는 큰 도움이 되지 않을 수도 있습니다. 네트워크 프로토콜 세계에선 GREASE [I-D.ietf-tls-grease] 개념이 있었고, 이 개념을 차용할 수 있습니다.
User agents의 brands에 값이 하나 이상 있으면 brands 리스트의 표준화된 처리를 유도할 수 있습니다. 임의로 잘못된(의도적으로, 단어 순서까지 임의로) 값들을 쉼표로 구분해 추가함으로써, 특정 문자열에 대한 요구사항이 고착화 되는 것을 줄일 수 있습니다.
일부 예시 살펴보기:
-
알려지지 않은 브라우저를 허용 목록에서 차단하지 않도록 하기 위해, Chrome은 존재하지 않는 브라우저가 포함된 UA 세트를 보낼 수 있습니다(주기적으로 값 변경).
-
"Chrome"; v="73", "(Not;Browser"; v="12"
-
-
Chromium 기반 브라우저끼리 동등 클래스를 만들기 위해, Chrome은 렌더링 엔진 및 그 버전을 추가할 수 있습니다.
-
"Chrome"; v="73", "(Not;Browser"; v="12", "Chromium"; v="73"
-
-
정확한 UA sniffing 대신 Chromium 버전 기반 동등 클래스를 사용하게 하고자, Chrome이 자신을 UA 세트에서 완전히 빼는 것도 가능합니다.
-
"(Not;Browser"; v="12", Chromium"; v="73"
-
-
Chromium 기반 브라우저는 비슷한 UA 문자열을 쓰되, 자신의 브랜드도 UA 세트 일부로 보내 사이트가 이를 세어볼 수 있도록 할 수 있습니다.
-
"Chrome"; v="73", "Xwebs mega"; v="60", "Chromium"; v="73", "(Not;Browser"; v="12"
-
User agents는 brands에 1개를 초과하는 값을 반드시 포함해야 하며, 이 중 하나는 임의의 값이어야 합니다.
brands의 값 순서는 시간이 지남에 따라 변해야 하며, 이는 특정 값이 명단 내 위치에 고정되는 것에 의존하지 못하도록 하기 위함입니다.
GREASE 전략을 고를 때, user agents는 캐싱 변동(caching variance)과 분석(analytics) 사용 사례를 고려해 동일 user agent 버전끼리 변동을 최소화해야 합니다.
Note: 캐싱 및 분석에서의 차이를 최소화하는 한 가지 방법은 UA(GREASE) 구성 요소를 빌드 시점에 결정하고, user agent의 significant version 기간 동안 동일하게 유지하는 것이다.
8.3. 'Sec-CH-' 접두사
사용자 영역 JavaScript 코드가 UA-CH 헤더에 영향을 주거나 수정하지 못하도록 제한하는 것은 여러 보안상 이점이 있습니다. 동시에, 그러한 사용자 영역 조작을 정당화하는 사용사례도 없다고 판단됩니다.
따라서 TAG와의 논의 결과,
JavaScript(예: fetch나 서비스 워커 등)에서 이 헤더의 쓰기 접근을 금지하는 것이 합리적이며,
이를 브라우저 제어 클라이언트 힌트로 명확하게 표시하여,
별도 CORS preflight 없이도 요청에 포함시킬 수 있게 설계합니다.
이 명세에서 정의하는 요청 헤더는 Sec-CH- 접두사를 포함합니다.
9. IANA 고려사항
이 문서는 Sec-CH-UA, Sec-CH-UA-Arch,
Sec-CH-UA-Bitness,
Sec-CH-UA-Form-Factors, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile,
Sec-CH-UA-Model,
Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA-WoW64, 그리고
Sec-CH-UA-Full-Version-List HTTP 요청 헤더 필드를 정의 및 영구 메시지
헤더 필드 등록부([RFC3864])에 등록하려 합니다.
또한 User-Agent 헤더 필드의 사용 중단(deprecate)도 함께 명시합니다.
9.1. 'Sec-CH-UA' 헤더 필드
헤더 필드 이름: Sec-CH-UA
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.1 The 'Sec-CH-UA' Header Field)
9.2. 'Sec-CH-UA-Arch' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Arch
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.2 The 'Sec-CH-UA-Arch' Header Field)
9.3. 'Sec-CH-UA-Bitness' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Bitness
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.3 The 'Sec-CH-UA-Bitness' Header Field)
9.4. 'Sec-CH-UA-Form-Factors' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Form-Factors
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.4 The 'Sec-CH-UA-Form-Factors' Header Field)
9.5. 'Sec-CH-UA-Full-Version' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Full-Version
적용 프로토콜: http
상태: 사용 중단(deprecated)
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.5 The 'Sec-CH-UA-Full-Version' Header Field)
9.6. 'Sec-CH-UA-Full-Version-List' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Full-Version-List
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.6 The 'Sec-CH-UA-Full-Version-List' Header Field)
9.7. 'Sec-CH-UA-Mobile' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Mobile
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.7 The 'Sec-CH-UA-Mobile' Header Field)
9.8. 'Sec-CH-UA-Model' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Model
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.8 The 'Sec-CH-UA-Model' Header Field)
9.9. 'Sec-CH-UA-Platform' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Platform
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.9 The 'Sec-CH-UA-Platform' Header Field)
9.10. 'Sec-CH-UA-Platform-Version' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Platform-Version
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.10 The 'Sec-CH-UA-Platform-Version' Header Field)
9.11. 'Sec-CH-UA-WoW64' 헤더 필드
헤더 필드 이름: Sec-CH-UA-WoW64
적용 프로토콜: http
상태: 표준
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 3.11 The 'Sec-CH-UA-WoW64' Header Field)
9.12. 'User-Agent' 헤더 필드
헤더 필드 이름: User-Agent
적용 프로토콜: http
상태: 사용 중단(deprecated)
작성자/변경 제어자: IETF
명세 문서: 본 명세 (§ 8.1 The 'User-Agent' Header), 및 [rfc9110]의 5.5.3절
10. 감사의 말
이 명세에 귀중한 피드백과 기여를 해준 Aaron Tagliaboschi, Ali Beyad, ArkUmbra, Dustin Mitchell, Erik Anderson, jasonwee, Luke Williams, Mike West, Martin Thomson, 그리고 Toru Kobayashi 에게 감사드립니다.