차근차근/JAVA Script

navigator.platform

예쁜꽃이피었으면 2021. 12. 15. 10:01

//PC 및 모바일 접속 확인 실시

    if(navigator.platform){

     }

navigator.platform 이 값이 궁금하다.

 

 

https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform

 

Navigator.platform - Web APIs | MDN

Returns a string representing the platform of the browser. The specification allows browsers to always return the empty string, so don't rely on this property to get a reliable answer.

developer.mozilla.org

https://kkh0977.tistory.com/873

 

63. (javascript/자바스크립트) navigator platform 사용해 pc 및 모바일 접속 확인, navigator userAgent 사용해

/* =========================== */ [ 개발 환경 설정 ] ​ 개발 툴 : Edit++ 개발 언어 : javascript /* =========================== */ ​ /* =========================== */ [소스 코드] /* ===============..

kkh0977.tistory.com

window.onload : 웹브라우저 로딩 완료 상태를 확인
navigator.platform : 브라우저가 실행되는 플랫폼 정보를 반환
navigator.userAgent : 웹 브라우저 전반에 대한 정보를 제공하는 객체
    <script>
        	
    	/* html 최초 로드 및 이벤트 상시 대기 실시 */
    	window.onload = function() {
    		console.log("");
    		console.log("[window onload] : [start]");
    		console.log("");
    		
    		//PC 및 모바일 접속 확인 실시
    		checkPcAndMobile();
    	};
    	
    	
    	/* 브라우저 및 모바일 접속 체크 실시 */
    	function checkPcAndMobile(){
    		console.log("");
    		console.log("[checkPcAndMobile] : [start]");
    		console.log("");
    		
    		//운영체제 종류 선언
    		var filterOs = "win16|win32|win64|mac|macintel";
    		
    		//PC 및 모바일 접속 확인 실시
    		if(navigator.platform){
    			if(0 > filterOs.indexOf(navigator.platform.toLowerCase())){
    				console.log("");
    				console.log("[checkPcAndMobile] : [platform] : [Mobile]");
    				console.log("");
    				
    				//모바일 기기 종류 확인 함수 호출
    				checkMobileDevice();    				
    			}
    			else {
    				console.log("");
    				console.log("[checkPcAndMobile] : [platform] : [PC]");
    				console.log("");
    				
    				alert("PC");    				
    			}    			    				    			
    		}
    		else {
    			console.log("");
    			console.log("[checkPcAndMobile] : [platform] : [none]");
    			console.log("");
    			
    			alert("none");        		
    		}    		
    	};
    	
    	
    	/* 모바일 기기 체크 실시 */
    	function checkMobileDevice(){    		
    		console.log("");
    		console.log("[checkMobileDevice] : [start]");
    		console.log("");
    		
    		//모바일 기종 종류 선언    		
    		var mobileArray = new Array();
    		mobileArray.push("iPhone");
    		mobileArray.push("iPod");
    		mobileArray.push("BlackBerry");
    		mobileArray.push("Android");
    		mobileArray.push("Windows CE");
    		mobileArray.push("LG");
    		mobileArray.push("MOT");
    		mobileArray.push("SAMSUNG");
    		mobileArray.push("SonyEricsson");
    		mobileArray.push("webOS");
    		mobileArray.push("IEMobile");
    		mobileArray.push("Opera Mini");
    		    		
    		//반복문 수행 실시
    		for(var mobile in mobileArray){
    			if(navigator.userAgent.match(mobileArray[mobile]) != null){
    				console.log("");
    				console.log("[checkMobileDevice] : " + mobileArray[mobile]);
    				console.log("");
    				
    				alert(mobileArray[mobile]);
    				break;    				
    			}
    		}    		
    	};	    	
    	
    </script>

 

https://d2.naver.com/helloworld/6532276

 

User-Agent Client Hints의 도입, UA 프리징을 대비하라

2020.10.12|21961

이 글에서는 클라이언트 입장에서 User-Agent Client Hints를 다룹니다.

지금까지 웹 서비스는 User-Agent HTTP 헤더에 포함된 User-Agent string에서 브라우저, OS, 사용자의 기기 정보 등 사용자 에이전트 정보를 얻을 수 있었습니다. User-Agent string을 이용하는 이유는 주로 다음과 같습니다.

  1. 특정 버전의 버그
  2. OS의 동작 차이
  3. 버전에 따른 동작 차이
  4. 사용자 에이전트에 따라 보여줄 콘텐츠 협상

우리는 위와 같은 다양한 이유로 User-Agent string을 사용해 왔지만 User-Agent string에는 많은 엔트로피(정보량)가 담겨 있어 개인정보 침해 문제가 있을 수 있습니다.

그래서 Chrome은 개인정보 보호를 위한 샌드박스 프로젝트  Client Hints 도입을 시도했습니다. Client Hints를 쉽게 말하자면 클라이언트 및 에이전트의 정보라고 할 수 있으며 가져올 정보를 명시합니다. 그렇기 때문에 사용자는 서버 및 클라이언트가 어떤 정보를 요구하는지 알 수 있습니다. 지금까지의 Client Hints 관련 Chrome 릴리즈 사항은 다음과 같습니다.

  • Chrome 46 - HTTP Client Hints 실험적 도입
  • Chrome 77 - Freeze-User-Agent 플래그 추가
  • Chrome 82, 83 (2020.05) - User-Agent Client Hints 실험적 도입
  • Chrome 84 (2020.07) - User-Agent Client Hints 인터페이스 변경

이 글에서는 이에 따라 앞으로 어떤 변화가 있을지, 이 변화에 어떻게 대응해야 할지 알아보겠습니다.

UA 프리징

Chrome 83부터 User-Agent Client Hints가 실험적으로 도입되었고 가장 큰 이슈는 바로 User-Agent string 프리징(이하 UA 프리징)이다. UA 프리징으로 달라지는 점은 다음과 같다.

  • 다음 속성값이 고정된다.
  • Chrome에서 안드로이드를 제외한 모든 운영체제는 윈도우 10으로 변한다.
  • 동기 방식으로 OS 이름, OS 버전, 모델명을 알 수 없다.
  • navigator.userAgent 대신 navigator.userAgentData을 사용해야 한다.
    • 브라우저 버전은 메이저 버전만 나타난다.
    • OS 이름, 버전, 모델명, 브라우저의 풀버전은 비동기 방식으로 알 수 있다.

UA 프리징은 다음 플래그를 활성화하면 테스트할 수 있다.

  • chrome://flags/#enable-experimental-web-platform-features
  • chrome://flags/#freeze-user-agent

UA 프리징 테스트 결과 navigator.userAgent를 사용하여 얻은 User-Agent string 값은 다음과 같다.

  • Galaxy Z Flip, Android 10, Chrome 85.0.4183.81
    • 전: Mozila/5.0 (Linux; Android 10; SM-F700N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.81 Mobile Safari/537.36
    • 후: Mozila/5.0 (Linux; Android 9; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.0.0 Mobile Safari/537.36
  • Mac OS X 10.15.4, Chrome Canary 87.0.4243.0
    • 전: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4243.0 Safari/537.36
    • 후: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.0.0 Safari/537.36

UA 프리징 결과 기기명, OS의 정보, 브라우저의 버전이 불분명해진 것을 확인할 수 있다. 앞으로 User-Agent string을 고정된 값으로 제공하기 위해 값은 점점 더 간소해질 수 있다.

UA 프리징 대응 방안

User-Agent Data

UA 프리징의 대응 방안으로 User-Agent string을 세분화해 Object 형식으로 나타낸 User-Agent Data를 사용할 수 있다. 인터페이스는 다음과 같다.

dictionary NavigatorUABrandVersion {  
  DOMString brand;
  DOMString version;
};

dictionary UADataValues {  
  DOMString platform;
  DOMString platformVersion;
  DOMString architecture;
  DOMString model;
  DOMString uaFullVersion;
};

[Exposed=(Window,Worker)]
interface NavigatorUAData {  
  readonly attribute FrozenArray<NavigatorUABrandVersion> brands;
  readonly attribute boolean mobile;
  Promise<UADataValues> getHighEntropyValues(sequence<DOMString> hints);
};

interface mixin NavigatorUA {  
  [SecureContext] readonly attribute NavigatorUAData userAgentData;
};

Navigator includes NavigatorUA;  
WorkerNavigator includes NavigatorUA;  

navigator.userAgentData에 접근하면 brands(84 이전 버전에서는 uaList)과 mobile 속성이 있으며 getHighEntropyValues 메서드를 사용할 수 있다.

그림 Chrome Canary 87.0.4243.0의 navigator.userAgentData

그림 Edge 85.0.564.44의 navigator.userAgentData

  • brands는 사용자 에이전트의 상업명과 버전의 이름이 담긴 리스트이다. 87 버전을 기준으로 Chromium을 사용하는 브라우저에서는 브라우저 브랜드, Chromium 브랜드, GREASE 브랜드 3개의 값이 임의의 순서로 있다.
  • mobile은 사용자 에이전트의 기기가 모바일인지를 나타내는 값이다.
  • getHighEntropyValues 메서드는 높은 엔트로피에 해당하는 값을 가져온다. brands(브라우저 이름과 메이저 버전)와 mobile은 낮은 엔트로피로 분류되기 때문에 동기 방식으로 값을 가져올 수 있지만 그 외 정보는 높은 엔트로피로 분류되어 getHighEntropyValues 메서드로 가져와야 한다. 또한 User-Agent string처럼 모든 정보를 가져오는 게 아니라 자신에게 필요한 정보만 가져올 수 있다.
navigator.userAgentData.getHighEntropyValues([  
  "architecture",
  "model",
  "platform",
  "platformVersion",
  "uaFullVersion",
]).then(info => {
  console.log(info);
});

그림 Mac OS X 10.15.4, Chrome Canary 87.0.4243.0의 navigator.userAgentData.getHighEntropyValues 호출 결과

아직은 Editor's draft 상태이며 Chrome 85에서는 권한 요청 프롬프트가 나타나지 않는다. 하지만 사용자 권한이 필요한 메서드이기 때문에 추후에는 권한 요청 프롬프트가 나타날 수 있고 사용자들은 이 사이트에서 어떤 정보를 수집하는지 알 수 있게 된다.

navigator.userAgentData.getHighEntropyValues를 통해 비동기 방식으로 정보를 가져오면 기존 User-Agent string으로 얻은 정보와 동일한 정보를 얻을 수 있다. 하지만 모든 코드를 비동기 방식으로 바꾸기 어려울뿐더러 다음 코드와 같이 상수로 사용하는 사람도 있을 것이다.

const userAgent = navigator.userAgent;

// check Mac
export const isMac = userAgent.indexOf("Mac") > -1;

// check iOS
export const isIOS = (isMac || userAgent.indexOf("iPhone") > -1 || userAgent.indexOf("iPad") > -1) && !!navigator.maxTouchPoints && navigator.maxTouchPoints > 0;

// check Chrome
export const isChrome = userAgent.indexOf("Chrome") > -1;  

네이버 서비스가 사용하고 있는 agent 모듈 @egjs/agent navigator.userAgent를 통해 브라우저 및 OS 정보를 가져오고 있다. 그렇기 때문에 UA 프리징에 대한 대비가 필요했다. @egjs/agent에서는 navigator.userAgentData를 이용해 어떻게 문제에 대응했는지 알아보겠다.

동기 방식의 대응 방안

먼저 동기 방식으로 해결할 수 있다면 기존 코드와 크게 달라지지 않기 때문에 최선의 해결책일 것이다. 그럼에도 불구하고 동기 방식으로 해결할 수 없는 문제라면 비동기 방식으로 전환을 고려해야 한다.

동기 방식으로 확인할 수 있는 정보는 다음과 같다.

  • navigator.userAgentData.brands: 브라우저의 이름과 메이저 버전, Chromium 정보
  • navigator.userAgentData.mobile: 모바일 여부
  • navigator.platform: Android Chrome(Linux armv8l) 여부
  • User-Agent Client Hints를 지원하지 않는 브라우저의 OS, OS 버전(Chrome 84의 지원 범위: Android 5.0 이상, Mac OS X 10.10 이상, 윈도우 7 이상)

다음은 동기 방식으로 사용자 에이전트 정보를 확인하는 예시 코드이다.

import getAgent from "@egjs/agent";

const agent = getAgent();

// Android 확인
export const IS_ANDROID = agent.os.name === "android";

// 브라우저 IE11 확인
export const IS_IE11 = agent.browser.name === "ie" && agent.browser.majorVersion === 11;

// User-Agent Client Hints를 지원하지 않는 Android 4 확인
export const IS_ANDROID4 = IS_ANDROID && agent.os.majorVersion === 4;

// User-Agent Client Hints를 지원하지 않는 iOS 10 확인
export const IS_IOS10 = agent.os.name === "ios" && agent.os.majorVersion === 10;  

Safari 추측

Safari(Safari 14, AppleWebkit 605 기준)는 아직 User-Agent Client Hints를 지원하지 않기 때문에 brand 리스트에 무슨 값이 있을지 알 수 없다. 또한 iOS 정책상 문제로 다른 브라우저 엔진을 사용하고 있는 기존의 브라우저(Chrome, Whale, Edge, Firefox)는 iOS 버전에서는 Safari를 사용한다. 그럼 Safari에서 User-Agent Client Hints가 도입된다면 brand 리스트에는 어떤 값이 있을까? iOS Chrome을 기준으로 다음과 같이 추측할 수 있다.

  • [Safari, Chrome]
  • [Safari, CriOS]
  • [AppleWebkit, Chrome]
  • [AppleWebkit, CriOS]

Safari 기반의 브라우저는 Safari 또는 AppleWebkit brand 정보가 있을 거라 추측하고 있다. 또한 Safari 기반 브라우저의 OS는 Mac 또는 iOS만 해당하기 때문에 다음과 같이 OS를 추측할 수 있다.

  • Safari 기반이고 mobile이면 iOS이다.
  • Safari 기반이고 mobile이 아니면 Mac이다.

즉, 다음과 같이 사용자 에이전트 정보를 확인할 수 있을 것이다.

import getAgent from "@egjs/agent";

const agent = getAgent();

// iOS 추측 가능
export const IS_IOS = agent.os.name === "ios";

// MAC Safari 추측 가능
export const IS_MAC_SAFARI = agent.os.name === "mac" && agent.browser.name === "safari";  

비동기 방식으로 전환

동기 방식으로 확인할 수 없는 정보는 비동기 방식으로 에이전트 값을 얻은 후에 코드가 실행되어야 한다. 동기 방식으로 확인할 수 없는 정보는 다음과 같다.

  • Android, iOS, Mac Safari를 제외한 OS 정보
  • 특정 OS 버전
  • 브라우저의 풀버전
import getAgent from "@egjs/agent";

const agent = getAgent();

// Windows를 확인할 수 없다.
export const IS_WINDOWS = agent.os.name === "window";

// Safari를 제외한 mac OS를 확인할 수 없다.
export const IS_MAC = agent.os.name === "mac";  

다음은 navigator.userAgentData.getHighEntropyValues 메서드로 정확한 agent 값을 얻을 수 있도록 만든 getAccurateAgent 비동기 함수이다.

import { getAccurateAgent } from "@egjs/agent";

async function start() {  
  const agent = await getAccurateAgent();

  const isWindows = agent.os.name === "window";
  const isMac = agent.os.name === "mac";
}

마치며

매일 3천만 명 이상이 네이버 서비스를 이용하고 있으며 모든 서비스에서 @egjs/agent 또는 navigator.userAgent를 사용하고 있기 때문에 네이버는 User-Agent Client Hints 도입에 주목하고 있다. 갑자기 User-Agent Client Hints가 도입된다면 서비스뿐만 아니라 agent 모듈을 사용하고 있는 Component들도 큰 타격을 입을 것이므로 네이버 FE Platform 팀은 User-Agent Client Hints를 리서치하고 @egjs/agent를 통해 지원하기로 했다.

User-Agent Client Hints는 아직 Editor's Draft 상태(2020.09.18)이며 언제든지 인터페이스 및 동작이 바뀔 수 있기 때문에 계속 주시하고 있고 Chromium뿐만 아니라 Webkit 코드도 확인하면서 빠르게 대응하고자 한다. 여러분도 함께 준비하는 데 이 글이 도움이 되길 바란다.

 

반응형

'차근차근 > JAVA Script' 카테고리의 다른 글

pagecontext.request.contextpath  (0) 2021.12.15
클립보드 복사 execCommand  (0) 2021.12.15
자바스크립트 위치..?  (0) 2021.12.07
[Vue.js] v-cloak  (0) 2021.12.06
[Vue.js] Vue.js란 (5) - Vue 컴포넌트  (0) 2021.12.06