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)
유저 에이전트는 이러한 문자열을 짧고 명확하게 유지해야 하지만, 서버는 각 값에 대해 임의의 값을 허용해야 합니다. 왜냐하면 모든 값은 유저 에이전트가 임의로 구성하기 때문입니다.
유저 에이전트는 고엔트로피 platform architecture 값을 다음과 같이 매핑해야 합니다:
-
x86 CPU 아키텍처 => "x86"
-
ARM CPU 아키텍처 => "arm"
기타 CPU 아키텍처는 상황에 따라 위 값 중 하나로 매핑하거나 빈 문자열로 매핑할 수 있습니다.
유저 에이전트는 platform architecture 또는 platform bitness에 대해, 다음 두 조건 모두 해당하는 플랫폼이 아닌 경우 빈 문자열 또는 허구의 값을 반환해야 합니다:
-
실행파일 바이너리 다운로드 가능성이 높음.
-
CPU 아키텍처별로 실행파일 리소스가 달라져야 하며, 실제로 다양한 바이너리 리소스가 제공됨.
유저 에이전트는 mobileness가 거짓이면 model에 대해 빈 문자열을 반환해야 합니다. 유저 에이전트는 mobileness가 참이어도 해당 플랫폼에서 일반적으로 모델이 노출되지 않으면 model에 대해 빈 문자열을 반환해야 합니다.
유저
에이전트는 sf-string
타입 힌트에 대해 빈 문자열, sf-boolean
타입 힌트에 대해 false
,
또는 기타 허구의 값을 반환할 수 있습니다. 이는 프라이버시, 호환성, 기타 이유로 full
version, platform architecture, platform bitness, wow64-ness 또는
model 힌트 요청 시 적용할 수
있습니다.
3.1. 'Sec-CH-UA' 헤더 필드
Sec-CH-UA
요청 헤더 필드는 서버에 유저 에이전트의 브랜딩과 주요 버전 정보를 제공합니다. 이는 구조화 헤더로, 값은 반드시 리스트여야 하며 [rfc9651] 참고. 리스트의 각 항목은 문자열이어야 합니다. 각
항목의 값에는 "v" 파라미터가 포함되어 유저 에이전트 버전을 나타내야 합니다.
헤더의 ABNF:
Sec-CH-UA = sf-list
요청에 대해 Sec-CH-UA
값을
반환하려면 다음 단계를 수행합니다:
-
brands를 "significant version"으로 create brands를 실행한 결과로 설정합니다.
-
list를 brands와 "significant version"을 사용하여 create a brand-version list를 실행한 결과로 설정합니다.
-
list로 serializing a list를 실행한 출력을 반환합니다.
참고: 대부분의 Client Hint와 달리, 저엔트로피 힌트 테이블에 포함되어 있으므로,
Sec-CH-UA
헤더는 서버가 Accept-CH
헤더로 옵트인하지 않아도 기본적으로 전송됩니다(단, 정책-제어 Client Hint 기능으로 제어는 가능). 저엔트로피로 간주되는 이유는
유저
에이전트의 브랜드 정보와 주요 버전 번호만 포함되기 때문입니다(둘 다 다른 헤더 구조나 기능 테스트 등으로 쉽게 추측 가능 [Janc2014]
참고).
참고: Sec-CH-UA
는 brands 리스트 내 각 브랜드의 주요 버전을 노출합니다. full version이 필요한 경우 Sec-CH-UA-Full-Version-List
를
참조하세요.
3.2. 'Sec-CH-UA-Arch' 헤더 필드
Sec-CH-UA-Arch
요청 헤더 필드는 서버에 특정 유저
에이전트가 실행되는 플랫폼의 아키텍처 정보를 제공합니다. 구조화 헤더로, 값은 반드시 문자열이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Arch = sf-string
3.3. 'Sec-CH-UA-Bitness' 헤더 필드
Sec-CH-UA-Bitness
요청 헤더 필드는 서버에 특정 platform bitness 정보를 제공합니다. 해당 유저 에이전트가 실행되는 플랫폼의 아키텍처에
대한 정보입니다. 구조화
헤더로, 값은 반드시 문자열이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Bitness = sf-string
3.4. 'Sec-CH-UA-Form-Factors' 헤더 필드
Sec-CH-UA-Form-Factors
요청 헤더 필드는 서버에 유저
에이전트의 form-factors 정보를 제공합니다. 구조화 헤더로, 값은 반드시 리스트이어야 하며 [rfc9651] 참고. 추가 지문 채취 엔트로피를 제공하지 않기 위해, 헤더 값은 반드시 사전순으로
제공되어야 하며 값은 대소문자 구분입니다.
헤더는 장치의 폼팩터를 다음과 같은 일반적인 값 중 하나 이상으로 기술해야 합니다: "Desktop", "Automotive", "Mobile", "Tablet", "XR", "EInk", "Watch". 적용 가능한 모든 폼팩터 값을 포함해야 합니다.
유저 에이전트의 폼팩터는 사용자가 유저 에이전트와 상호작용하는 방식을 설명합니다. 허용된 값의 의미는 다음과 같습니다:
-
"Desktop"은 PC에서 실행되는 유저 에이전트를 의미합니다.
-
"Automotive"는 차량에 내장된 유저 에이전트로, 사용자가 차량 운전에 집중해야 해 세부 조작이 어렵다는 점이 특징입니다.
-
"Mobile"은 사용자가 휴대하는 소형 터치 기반 장치를 의미합니다.
-
"Tablet"은 "Mobile"보다 크지만 일반적으로 휴대하지 않는 터치 기반 장치를 의미합니다.
-
"XR"은 사용자의 환경을 증강 또는 대체하는 몰입형 장치를 의미합니다.
-
"EInk"는 느린 화면 갱신과 제한적 색상 해상도가 특징인 장치를 의미합니다.
-
"Watch"는 화면이 매우 작고(일반적으로 2 인치 미만) 사용자가 빠르게 볼 수 있도록 손목에 착용하는 모바일 장치를 의미합니다.
새로운 폼팩터가 의미 있게 다르게 사용자와 상호작용할 때, 사이트가 해당 장치에서 사용자 경험을 변경하고 싶을 compelling한 사례가 있고, 기존 힌트로 해당 폼팩터를 신뢰성 있게 식별할 방법이 없다면 새로운 값을 명세에 제안·추가해야 합니다.
헤더의 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
요청 헤더 필드는 서버에 유저
에이전트의 full
version 정보를 제공합니다. 구조화 헤더로, 값은 반드시 문자열이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Full-Version = sf-string
3.6. 'Sec-CH-UA-Full-Version-List' 헤더 필드
Sec-CH-UA-Full-Version-List
요청 헤더 필드는
서버에 brands 리스트 내 각 브랜드의 full version 정보를 제공합니다. 구조화 헤더로, 값은 반드시 리스트이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Full-Version-List = sf-list
요청에 대해
Sec-CH-UA-Full-Version-List
값을 반환하려면 다음 단계를 수행합니다:
-
brands를 "full version"으로 create brands를 실행한 결과로 설정합니다.
-
list를 brands와 "full version"을 사용하여 create a brand-version list를 실행한 결과로 설정합니다.
-
list로 serializing a list를 실행한 출력을 반환합니다.
3.7. 'Sec-CH-UA-Mobile' 헤더 필드
Sec-CH-UA-Mobile
요청 헤더 필드는 서버에 유저
에이전트가 "모바일" 사용자 경험을 선호하는지 여부를 제공합니다. 구조화 헤더로, 값은 반드시 불리언이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Mobile = sf-boolean
참고: 위 Sec-CH-UA
와 같이 저엔트로피 힌트 테이블에 포함되어 있으므로,
Sec-CH-UA-Mobile
헤더는 서버가 Accept-CH
헤더로 옵트인하지 않아도 기본적으로 전송됩니다(단, 정책-제어 Client Hint 기능으로 제어는 가능). 저엔트로피로 간주되는
이유는 사용자가 직접 제어할 수 있는 한 비트 정보이기 때문입니다.
3.8. 'Sec-CH-UA-Model' 헤더 필드
Sec-CH-UA-Model
요청 헤더 필드는 서버에 특정 유저
에이전트가 실행되는 장치에 대한 정보를 제공합니다. 구조화 헤더로, 값은 반드시 문자열이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-Model = sf-string
3.9. 'Sec-CH-UA-Platform' 헤더 필드
Sec-CH-UA-Platform
요청 헤더 필드는 서버에 특정 유저
에이전트가 실행되는 플랫폼 정보를 제공합니다. 구조화 헤더로, 값은 반드시 문자열이어야 하며 [rfc9651]
참고. 값은 "Android", "Chrome OS", "Fuchsia", "iOS", "Linux", "macOS",
"Windows", "Unknown" 중 하나와 일치하는 것이어야 합니다.
헤더의 ABNF:
Sec-CH-UA-Platform = sf-string
참고: 위 Sec-CH-UA
와 같이 저엔트로피 힌트 테이블에 포함되어 있으므로, Sec-CH-UA-Platform
헤더는 서버가 Accept-CH
헤더로 옵트인하지 않아도 기본적으로 전송됩니다(단, 정책-제어 Client Hint 기능으로 제어는 가능).
3.10. 'Sec-CH-UA-Platform-Version' 헤더 필드
Sec-CH-UA-Platform-Version
요청 헤더 필드는
서버에 특정 플랫폼 버전 정보를 제공합니다. 해당 유저 에이전트가 실행 중인 플랫폼 버전입니다.
구조화 헤더이며, 값은
반드시 문자열이어야 합니다[rfc9651].
값은 플랫폼 버전
얻기를 platform brand와 함께 실행한 결과입니다.
플랫폼 버전 얻기를 위해, platform 문자열이 주어지면 다음 단계를 실행합니다:
-
platform이 "Linux"인 경우:
-
빈 문자열을 반환합니다.
-
-
platform이 "Android"인 경우:
-
platformReturnedVersionString을 OS의
android.os.Build.VERSION.RELEASE
문자열 쿼리 결과로 설정합니다. -
통합 플랫폼 버전 문자열 생성을 platformReturnedVersionString과 함께 실행한 결과를 반환합니다.
-
-
platform이 "iOS"인 경우:
-
platformReturnedVersionString을
currentDevice
로 반환된UIDevice
객체의systemVersion
읽기 결과로 설정합니다. -
통합 플랫폼 버전 문자열 생성을 platformReturnedVersionString과 함께 실행한 결과를 반환합니다.
-
-
platform이 "Windows"인 경우:
-
가능하다면(즉, Windows 10 이상) platformReturnedVersionString을
Windows.Foundation.UniversalApiContract
정수 버전 쿼리 결과를 문자열로 변환한 값으로 설정합니다. 그렇지 않으면 platformReturnedVersionString을 레거시 Windows 버전 번호 얻기 결과로 설정합니다. -
통합 플랫폼 버전 문자열 생성을 platformReturnedVersionString과 함께 실행한 결과를 반환합니다.
-
-
platformVersionComponentList를 리스트로 설정합니다.
-
platform이 "macOS"인 경우:
-
macOSVersion을
NSProcessInfo
객체의processInfo
정보 agent로 얻은operatingSystemVersion
속성으로 설정합니다. -
Append macOSVersion의
majorVersion
,minorVersion
,patchVersion
컴포넌트(순서대로)를 platformVersionComponentList에 추가합니다.
-
-
기타 platform 값인 경우:
-
platformVersionComponentList를 U+002E FULL STOP(
.
) 구분자로 연결한 결과를 반환합니다.
레거시 Windows 버전 번호 얻기를 위해, 다음 단계를 실행합니다:
-
major를 Win32
GetVersionEx
API로 반환된OSVERSIONINFO
의dwMajorVersion
값으로 설정합니다. -
minor를 Win32
GetVersionEx
API로 반환된OSVERSIONINFO
의dwMinorVersion
값으로 설정합니다. -
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를 input을 U+002E FULL STOP 문자(
.
)로 strictly splitting한 리스트로 설정합니다. -
index가 3 미만인 동안:
-
index가 platformVersionUnprocessedTokenList 길이보다 작으면:
-
platformVersionUnprocessedTokenList[index]가 unsigned integer이면 문자열로 변환해 platformVersionComponentList에 추가합니다.
-
그렇지 않으면 "0"을 platformVersionComponentList에 추가합니다.
-
-
그 외(index가 길이 이상이면):
-
"0"을 platformVersionComponentList에 추가합니다.
-
-
index를 1 증가시킵니다.
-
-
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비트 모드로 실행 중인지 여부를 제공합니다.
구조화 헤더이며,
값은 반드시 불리언이어야 합니다 [rfc9651].
헤더의 ABNF:
Sec-CH-UA-WoW64 = sf-boolean
참고: 다음 client hints token 집합으로 이 클라이언트 힌트들을 활성화할 수 있습니다:
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 ; // deprecated in favor of 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 ;
참고: 유저 에이전트 정보의 고엔트로피 부분은 Promise
를
통해 조회되며,
유저
에이전트가 노출을 잠재적으로 시간 소요가 큰 확인(예: 사용자에게 권한 요청)을 거치게 할 수 있도록 합니다.
4.1. 처리 모델
4.1.1. WindowOrWorkerGlobalScope
각 유저 에이전트는 brands와 연결되어 있으며, 이는 리스트로, create brands를 significant version과 함께 실행해 생성합니다.
모든 WindowOrWorkerGlobalScope
객체는 brands frozen
array와 연결되어 있으며,
FrozenArray<NavigatorUABrandVersion>
입니다.
초기 값은 create frozen array를 유저 에이전트의 brands에 대해 실행한 결과입니다.
또한, 모든 WindowOrWorkerGlobalScope
객체는 full
version list frozen array와 연결되어 있으며,
FrozenArray<NavigatorUABrandVersion>
입니다.
create frozen array를 create brands와 full version을 함께 실행한 결과입니다.
4.1.2. 브랜드 생성
create brands를 version type과 함께 요청받으면, 다음 단계를 실행합니다:
-
list를 리스트로 설정합니다.
-
Assert version type이 "full version" 또는 "significant version"이어야 합니다.
-
brand별로, 해당 유저 에이전트 또는 동등 클래스를 대표하는 각 brand에 대해:
-
version을 문자열로, 다음에 따라 초기화:
-
version type이 "full version"이면 version을 full version에 해당하는 문자열로 설정합니다.
-
version type이 "significant version"이면 version을 significant version에 해당하는 문자열로 설정합니다.
-
-
dict를
NavigatorUABrandVersion
딕셔너리로 새로 생성하고,brand
를 brand로,version
을 version으로 설정합니다. -
dict를 list에 추가합니다.
-
-
유저 에이전트는 다음 단계를 실행해야 합니다:
-
추가로 item 하나를 list에 추가합니다.
NavigatorUABrandVersion
딕셔너리로,brand
를 임의 브랜드로,version
을 임의 버전 생성을 version type과 함께 실행한 결과로 설정합니다. -
list의 item 순서를 랜덤화합니다.
참고: 이러한 임의 컴포넌트 생성 시 캐싱 변동을 최소화하려면, 빌드 시점에 결정하고 유저 에이전트의 significant version 라이프타임 전체에 걸쳐 동일하게 유지하는 방법도 있을 수 있습니다.
참고: 이러한 랜덤화 방식의 타이밍 및 목적에 대해서는 § 7.2 GREASE 유사 UA 브랜드 목록을 참고하세요.
-
-
list를 반환합니다.
동등 클래스는 서로 호환된다고 판단되는 브라우저 그룹을 의미합니다. 예를 들어, 동일 렌더링 엔진을 공유하면 동등 클래스가 될 수 있습니다.
4.1.3. 임의 브랜드 및 버전 값 생성
임의 브랜드 생성을 위해, 유저 에이전트는 다음 단계를 반드시 수행해야 합니다:
-
arbitraryBrand를 문자열로, ASCII 알파벳과 0x20(SP)로 구성합니다. arbitraryBrand는 하나 이상의 0x20(SP) 바이트를 반드시 포함하며, 20 ASCII 바이트 이하로 해야 하며, 시작과 끝이 0x20(SP)로 시작하거나 끝나면 안 됩니다.
-
arbitraryBrandList를 ASCII 공백으로 arbitraryBrand 분할 결과로 설정합니다.
-
greaseyStack을 스택으로 설정합니다.
-
greaseyChars를 다음 ASCII 바이트 리스트 « 0x20(SP), 0x28(왼쪽 괄호), 0x29(오른쪽 괄호), 0x2D(-), 0x2E(.), 0x2F(/), 0x3A(:), 0x3B(;), 0x3D(=), 0x3F(?), 0x5F(_) »로 설정합니다.
-
index를 0으로 설정합니다.
-
index가 arbitraryBrandList 크기 - 1 미만인 동안:
-
greaseyStack에 greaseyChars에서 무작위로 선택한 item을 push합니다.
-
index를 1 증가시킵니다.
-
-
greaseyBrandList를 리스트로 설정하고, index를 0으로 설정합니다.
-
greaseyStack이 비어있지 않으면:
-
arbitraryBrandList[index]를 greaseyBrandList에 추가합니다.
-
item을 greaseyStack에서 pop합니다.
-
item을 greaseyBrandList에 추가합니다.
-
index를 1 증가시킵니다.
-
-
arbitraryBrandList[index]를 greaseyBrandList에 추가합니다.
-
선두 및 후미 ASCII 공백 제거 후 greaseyBrandList를 연결(구분자 없음)한 결과를 반환합니다.
추가적으로, 구조화 헤더가 0x22(") 및 0x5C(\) 이스케이프를 허용하지만, 이 문자들은 방화벽과 호환성 이슈를 유발할 수 있습니다.
임의 버전 생성을 위해 version type이 주어지면, 다음 단계를 수행합니다:
-
version type이 "full version" 또는 "significant version"임을 assert합니다.
-
arbitrary version을 문자열로, 다음에 따라 초기화:
-
version type이 "full version"이면 arbitrary version을 full version의 포맷과 일치하지만 값은 다르게 설정합니다.
-
version type이 "significant version"이면 arbitrary version을 significant version의 포맷과 일치하지만 값은 다르게 설정합니다.
-
-
arbitrary version을 반환합니다.
참고: 유저 에이전트는 버전 체크가 제대로 작동하도록 임의로 낮은 버전을 전송할 수 있으며, 시간이 지남에 따라 버전을 변경해야 합니다.
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
속성의 get 시 this의 관련 글로벌 객체의 brands frozen array를 반환해야 합니다.
mobile
속성의 get 시 유저 에이전트의 mobileness를 반환해야 합니다.
platform
속성의 get 시 유저 에이전트의 platform brand를 반환해야 합니다.
4.1.6. getHighEntropyValues
메서드
getHighEntropyValues(hints)
메서드는 반드시 다음 단계를 실행해야 합니다:
-
p를 현재 realm에서 생성된 새로운 promise로 설정합니다.
-
uaData를 새
UADataValues
로 설정합니다. -
uaData["
brands
"] 를 this의 관련 글로벌 객체의 brands frozen array로 설정합니다. -
uaData["
mobile
"] 를 유저 에이전트의 mobileness로 설정합니다. -
uaData["
platform
"] 를 유저 에이전트의 platform brand로 설정합니다. -
this의 관련 글로벌 객체의 연결된 Document가 ch-ua-high-entropy-values 기능을 사용할 수 없다면, p를 uaData로 resolve 합니다.
-
그 외에는 다음 단계를 병렬로 실행합니다:
-
hints에 "architecture"가 포함되면, uaData["
architecture
"] 를 유저 에이전트의 platform architecture로 설정합니다. -
hints에 "bitness"가 포함되면, uaData["
bitness
"] 를 유저 에이전트의 platform bitness로 설정합니다. -
hints에 "formFactors"가 포함되면, uaData["
formFactors
"] 를 유저 에이전트의 form-factors로 설정합니다. -
hints에 "fullVersionList"가 포함되면, uaData["
fullVersionList
"] 를 this의 관련 글로벌 객체의 full version list frozen array로 설정합니다. -
hints에 "model"이 포함되면, uaData["
model
"] 를 유저 에이전트의 model로 설정합니다. -
hints에 "platformVersion"이 포함되면, uaData["
platformVersion
"] 를 platform version 얻기를 platform brand와 함께 실행한 결과로 설정합니다. -
hints에 "uaFullVersion"이 포함되면, uaData["
uaFullVersion
"] -
hints에 "wow64"가 포함되면, uaData["
wow64
"] 를 유저 에이전트의 wow64-ness로 설정합니다. -
permission task source에서 resolve p를 uaData로 큐에 넣습니다.
-
-
p를 반환합니다.
4.1.7. toJSON
메서드
toJSON()
메서드는 반드시 다음 단계를 실행해야 합니다:
-
uaLowEntropyData를 새
UALowEntropyJSON
으로 설정합니다. -
uaLowEntropyData["
brands
"] 를 this의 관련 글로벌 객체의 brands frozen array로 설정합니다. -
uaLowEntropyData["
mobile
"] 를 유저 에이전트의 mobileness로 설정합니다. -
uaLowEntropyData["
platform
"] 를 유저 에이전트의 platform brand로 설정합니다. -
uaLowEntropyData를 반환합니다.
5. Permissions-Policy 통합
이 명세는 문자열
"ch-ua-high-entropy-values
"로
식별되는 정책 제어 기능을 정의합니다.
기본 허용 목록은 '*'
입니다. 이 값은 특정 문서가
getHighEntropyValues()
API를 통해 고엔트로피 client hint 값을 반환할 수 있는지 결정합니다.
참고: 특정 문서가 "ch-ua-high-entropy-values"
기능을
사용할 수 없으면, getHighEntropyValues()
API는 편의를 위해 계속 저엔트로피 값을 반환합니다.
6. 보안 및 개인정보 보호 고려사항
6.1. 보안 전송
Client Hint는 비보안 엔드포인트로 전달되지 않습니다([RFC8942] 2.2.1절의 보안 전송 요구사항 참고). 즉, 유저 에이전트 정보는 평문 채널로 유출되지 않아 네트워크 공격자가 특정 에이전트의 행동 프로파일을 구축할 기회를 줄입니다.
6.2. 위임
Client Hint는 Permissions Policy ([permissions-policy-1])를 통해 최상위 페이지에서 위임됩니다. 이는 유저 에이전트 정보가 하위 리소스 요청에 함께 전달될 가능성을 줄이며, 수동 지문 채취 위험을 줄입니다.
이 위임은 append client hints to request의 일부로 정의됩니다.
6.3. 지문 채취
User Agent Client Hints의 주요 목표는 User-Agent 헤더 필드를 통해 웹에 기본적으로 노출되는 엔트로피 양을 줄이는 것이며, 이는 수동 지문 채취에 사용될 수 있습니다.
유저 에이전트는 어떤 힌트를 제공할지 결정할 수 있으며, 비편집된 User-Agent 헤더 필드에 포함될 정보 이상의 추가 정보를 제공하지 않는다는 기대가 있습니다. 유저 에이전트는 제공을 원하지 않는 값에 대해 빈 문자열을 주거나 힌트 반환 자체를 거부할 수 있습니다.
하지만 일부 또는 모든 힌트가 1차 또는 위임된 3차 당사자에 의해 능동 지문 채취에 사용될 수 있습니다. § 6.4 접근 제한에서 언급한 바와 같이, 유저 에이전트는 사용자 지문 채취를 적극적으로 수행하는 당사자에 대한 접근 정책을 검토해야 합니다.
유저 에이전트는 개별 사용자 또는 소수 사용자에게만 고유한 GREASE 유사 브랜드 목록을 통해 지문 채취 벡터가 생기지 않도록 주의해야 합니다. 오히려, 임의 브랜드를 많은 사용자(예: 해당 major version 전체 사용자)에게 공유하는 전략을 채택해야 합니다.
6.4. 접근 제한
위에서 정의한 Client Hint 정보는 유저 에이전트 및 실행 기기에 대한 많은 정보를 공개합니다. 유저 에이전트는 이 정보 접근을 허가하기 전 반드시 판단을 해야 하며, 앞서 언급한 보안 전송 및 위임 요구사항 이상으로 추가 제한을 적용할 수 있습니다. 예를 들어, 유저 에이전트는 다운로드 의도가 있는 요청에만 platform architecture 또는 platform bitness를 공개해 서버가 적합한 바이너리를 제공하도록 할 수 있습니다. 또한 사용자가 서버에 공개할 값에 대해 직접 제어하거나 명시적 사용자 상호작용(권한 프롬프트 또는 설정 인터페이스)을 통해 접근을 제한할 수 있습니다.
7. 구현 고려사항
7.1. 'User-Agent' 헤더
유저
에이전트는 정보 구체성을 줄여 이 문서의 Client Hint 모델을 우선함으로써 User-Agent
헤더 사용을 점진적으로 폐기해야 합니다. 헤더는 단기간
내 완전히 제거하기는 불가능할 것이며, 기존 사이트의 콘텐츠 협상 코드가 여전히 필요로 하기 때문입니다(최근 브라우저의 어려움 예시는 [Rossi2015] 참고).
권장될 수 있는 한 가지 접근법은 각 유저 에이전트가 User-Agent
헤더 값을 고정하고, "like Gecko" 및
"AppleWebKit/537.36" 등의 오래된 선언을 계속 유지하여 하위 호환성을 확보하는 것입니다. 버전 번호를 먼저 고정하고, 이후 플랫폼 및 모델 정보를 더 일반적으로 변경하여 헤더가
제공하는 지문을 줄일 수 있습니다.
7.2. GREASE 유사 UA 브랜드 목록
역사는 유저 에이전트가 사이트의 sniffing 스크립트를 우회하고 UA 기반 허용/차단 리스트로 사용자가 차단되지 않게 하려고 브랜드 정보를 거짓으로 보내는 유인이 크다는 점을 보여줍니다.
기대치 재설정은 브랜드 리스트 남용을 단기적으로 억제할 수 있지만, 장기적으로는 효과가 없을 수 있습니다. 네트워크 프로토콜 세계는 GREASE 개념을 도입했습니다([I-D.ietf-tls-grease]). 이 개념을 차용해 문제를 해결할 수 있습니다.
유저 에이전트의 brands가 한 개 이상일 경우 브랜드 리스트의 표준화된 처리를 장려할 수 있습니다. 랜덤하게 추가된 의도적으로 잘못된, 콤마로 구분된 항목들이 포함되면, 특정 값이 특정 위치에 고정되는 현상을 줄일 수 있습니다.
예시를 살펴봅시다:
-
알 수 없는 브라우저를 allow list에서 차단하지 않게 하려면, 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은 셋에서 자신을 완전히 제외할 수도 있습니다.
-
"(Not;Browser"; v="12", Chromium"; v="73"
-
-
Chromium 기반 브라우저는 유사한 UA 문자열을 사용하지만, 셋에 자체 브랜드를 추가해 사이트에서 카운트할 수 있게 합니다.
-
"Chrome"; v="73", "Xwebs mega"; v="60", "Chromium"; v="73", "(Not;Browser"; v="12"
-
유저 에이전트는 brands에 하나 이상의 값을 반드시 포함해야 하며, 그 중 하나는 임의 값이어야 합니다.
brands의 값 순서는 시간이 지남에 따라 바뀌어야 하며, 헤더 수신자가 특정 값이 특정 위치에 있다고 가정하는 것을 방지해야 합니다.
GREASE 전략 선택 시, 유저 에이전트는 캐싱 변동성과 분석 활용 사례를 고려해 동일 유저 에이전트 버전 간 변동성을 최소화해야 합니다.
참고: 캐싱 및 분석 변동성을 최소화하려면 UA 셋의 GREASE 부분을 빌드 시점에 결정하여 해당 유저 에이전트의 significant version 라이프타임 전체에 동일하게 유지하는 방법도 있습니다.
7.3. 'Sec-CH-' 접두어
유저랜드 JavaScript 코드가 UA-CH 헤더에 영향을 주거나 수정하지 못하게 하면 다양한 보안상의 이점이 있습니다. 동시에, 사용 사례 중에서도 사용자가 직접 헤더를 수정해야 할 정당한 사례는 없는 것 같습니다.
따라서 TAG와의 논의에 따라, JavaScript(예:
fetch
또는 Service
Workers)를 통한 쓰기 접근을 금지하고, 브라우저 제어 Client Hint로 구분하여 CORS preflight 없이 요청에 포함·문서화할 수 있도록 하는 것이 합리적입니다.
따라서 이 명세에서 정의한 요청 헤더는 Sec-CH-
접두어를 포함합니다.
8. 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)을 의도합니다.
8.1. 'Sec-CH-UA' 헤더 필드
헤더 필드 이름: Sec-CH-UA
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.1 'Sec-CH-UA' 헤더 필드)
8.2. 'Sec-CH-UA-Arch' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Arch
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.2 'Sec-CH-UA-Arch' 헤더 필드)
8.3. 'Sec-CH-UA-Bitness' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Bitness
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.3 'Sec-CH-UA-Bitness' 헤더 필드)
8.4. 'Sec-CH-UA-Form-Factors' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Form-Factors
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.4 'Sec-CH-UA-Form-Factors' 헤더 필드)
8.5. 'Sec-CH-UA-Full-Version' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Full-Version
적용 프로토콜: http
상태: 사용 중단됨(deprecated)
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.5 'Sec-CH-UA-Full-Version' 헤더 필드)
8.6. 'Sec-CH-UA-Full-Version-List' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Full-Version-List
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.6 'Sec-CH-UA-Full-Version-List' 헤더 필드)
8.7. 'Sec-CH-UA-Mobile' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Mobile
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.7 'Sec-CH-UA-Mobile' 헤더 필드)
8.8. 'Sec-CH-UA-Model' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Model
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.8 'Sec-CH-UA-Model' 헤더 필드)
8.9. 'Sec-CH-UA-Platform' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Platform
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.9 'Sec-CH-UA-Platform' 헤더 필드)
8.10. 'Sec-CH-UA-Platform-Version' 헤더 필드
헤더 필드 이름: Sec-CH-UA-Platform-Version
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.10 'Sec-CH-UA-Platform-Version' 헤더 필드)
8.11. 'Sec-CH-UA-WoW64' 헤더 필드
헤더 필드 이름: Sec-CH-UA-WoW64
적용 프로토콜: http
상태: 표준
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 3.11 'Sec-CH-UA-WoW64' 헤더 필드)
8.12. 'User-Agent' 헤더 필드
헤더 필드 이름: User-Agent
적용 프로토콜: http
상태: 사용 중단됨(deprecated)
작성자/변경 관리자: IETF
명세 문서: 본 명세서 (§ 7.1 'User-Agent' 헤더), 그리고 [rfc9110] 5.5.3절
9. 감사의 글
다음 분들께 본 명세서에 대한 소중한 피드백과 기여에 감사드립니다: Aaron Tagliaboschi, Ali Beyad, ArkUmbra, Dustin Mitchell, Erik Anderson, jasonwee, Luke Williams, Mike West, Martin Thomson, 그리고 Toru Kobayashi.