Googlebook 식별

Googlebooks는 Android 기술 스택을 기반으로 하며 ChromeOS의 데스크톱 기반과 페어링됩니다. 대부분의 웹 애플리케이션은 다른 데스크톱 기기에서와 마찬가지로 Googlebooks에서 동일하게 실행되며 ChromeOS와 동일한 사용자 에이전트 문자열을 표시합니다.

Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0; Safari/537.36

예를 들어 분석을 위해 Google 도서를 더 정확하게 식별하거나 사용자가 호환되는 Android 앱을 다운로드하도록 안내하려면 Platform 및 Mobile 클라이언트 힌트라는 두 개의 사용자 에이전트 클라이언트 힌트를 요청해야 합니다. 둘 다 엔트로피가 낮은 힌트이므로 User-Agent 문자열과 마찬가지로 추가 요청이나 권한 없이 가져올 수 있습니다. 기존 감지에 직접 통합할 수 있습니다.

UA-CH 헤더 Google 도서 값
Sec-CH-UA-Platform "Android"
Sec-CH-UA-Mobile ?0 (False)

브라우저에서 이를 감지하려면 navigator.userAgentData API를 사용하세요.

const isGooglebook = window?.navigator?.userAgentData?.platform === 'Android' && window?.navigator?.userAgentData?.mobile === false;

사용자 에이전트 축소로 인해 Googlebook 전용 플랫폼이 Platform 클라이언트 힌트 또는 사용자 에이전트 문자열에 추가되지 않았으므로 Googlebook과 이전 버전의 ChromeOS를 구분하기 위해 클라이언트 힌트가 "Android"로 변경되어 Googlebook이 Android 앱과 호환됨을 반영합니다.

서버 측 감지

이 두 가지는 모두 엔트로피가 낮은 클라이언트 힌트이므로 클라이언트의 초기 요청 시 서버로 전송되며 다음 방법 중 하나로 수신할 수 있습니다.

Node.js

const platform = req.headers['sec-ch-ua-platform'] || 'Not Sent';
const mobile = req.headers['sec-ch-ua-mobile'] || 'Not Sent';

const cleanPlatform = platform.replace(/"/g, '');
const isGooglebook = cleanPlatform === 'Android' && mobile === '?0';

자바

String platform = exchange.getRequestHeaders().getFirst("Sec-CH-UA-Platform");
 if (platform == null) platform = "Not Sent";

String mobile = exchange.getRequestHeaders().getFirst("Sec-CH-UA-Mobile");
if (mobile == null) mobile = "Not Sent";

String cleanPlatform = platform.replace("\"", "");
boolean isGooglebook = cleanPlatform.equals("Android") && mobile.equals("?0");

Ruby

mobile = req['Sec-CH-UA-Mobile'] || 'Not Sent'

clean_platform = platform.gsub('"', '')
is_googlebook = clean_platform == 'Android' && mobile == '?0'

Python

platform = self.headers.get('Sec-CH-UA-Platform', 'Not Sent')
mobile = self.headers.get('Sec-CH-UA-Mobile', 'Not Sent')

clean_platform = platform.replace('"', '')
is_googlebook = clean_platform == 'Android' and mobile == '?0'

PHP

$mobile = $_SERVER['HTTP_SEC_CH_UA_MOBILE'] ?? 'Not Sent';

$cleanPlatform = str_replace('"', '', $platform);
$isGooglebook = ($cleanPlatform === 'Android' && $mobile === '?0');

Go

platform := r.Header.Get("Sec-CH-UA-Platform")
if platform == "" {
  platform = "Not Sent"
}
mobile := r.Header.Get("Sec-CH-UA-Mobile")
if mobile == "" {
  mobile = "Not Sent"
}

cleanPlatform := strings.ReplaceAll(platform, "\"", "")
isGooglebook := cleanPlatform == "Android" && mobile == "?0"

기타 유용한 클라이언트 힌트

Platform 및 Mobile 클라이언트 힌트만으로도 사용자가 Googlebook을 사용하고 있음을 알 수 있지만 기기에 관한 더 많은 정보가 필요할 수 있습니다. [Sec-CH-UA](https://developer.mozilla.org/docs/Web/HTTP/Reference/Headers/Sec-CH-UA) 클라이언트 힌트는 주요 브라우저 버전과 기기와 연결된 기타 브랜드의 쉼표로 구분된 목록을 반환하므로 사용자 에이전트 문자열에서 파싱하는 것보다 더 간단합니다. Form Factors 클라이언트 힌트(Sec-CH-UA-Form-Factors)도 있습니다. 이는 지정된 기기의 폼 팩터(데스크톱, 태블릿, 모바일, 자동차 등)의 쉼표로 구분된 목록을 제공하는 엔트로피가 높은 힌트입니다. 이는 단일 폼 팩터인 경우가 많지만 적용 가능한 모든 폼 팩터가 포함될 수 있으므로 분리형 기기는 예를 들어 "Desktop", "Tablet"를 반환할 수 있습니다. 사용자가 어떤 폼 팩터를 사용하고 있는지 정확하게 파악하는 것이 중요하고 모바일 Android 기기가 아닌지 여부만 파악하는 것이 중요하지 않다면 Critical-CH 헤더를 사용하면 됩니다.

GET / HTTP/1.1
Host: example.com

HTTP/1.1 200 OK
Content-Type: text/html
Accept-CH: Sec-CH-UA-Form-Factors
Vary: Sec-CH-UA-Form-Factors
Critical-CH: Sec-CH-UA-Form-Factors

클라이언트가 Accept-CH 헤더를 처리한 후 중요한 힌트를 포함한 경우 요청을 다시 시도합니다. 이렇게 하면 초기 응답 대신 최적화된 페이지를 제공할 수 있습니다. 이렇게 하면 추가 왕복이 발생하므로 중요한 정보가 필요한 의미 있는 페이지 변경사항에만 사용하세요.