User-Agent 축소는 사용자 에이전트(UA) 문자열에서 제공되는 프라이버시에 민감한 정보의 양을 줄이기 위한 광범위하게 받아들여진 브라우저 이니셔티브예요.
이 문서는 User-Agent 축소의 결과로 UA 문자열의 차이점을 보여주고, 필요할 때 축소된 UA 정보와 추가 UA 정보에 모두 접근하는 방법을 설명해요.
사용자 에이전트(UA) 문자열 – User-Agent HTTP 헤더와 Navigator.userAgent, Navigator.appVersion, Navigator.platform과 같은 관련 API 기능에서 사용 가능해요 – 은 서버와 네트워크 피어가 요청하는 사용자 에이전트의 애플리케이션, 운영 체제, 공급업체 및/또는 버전을 식별할 수 있게 해줘요.
이론적으로 UA 문자열은 브라우저를 감지하고 브라우저별 버그를 해결하거나 기능 지원 부족을 해결하기 위한 코드를 제공하는 데 유용해요. 하지만 이것은 신뢰할 수 없고 권장되지 않아요:
다음은 버그와 다른 브라우저 지원을 해결하기 위한 훨씬 더 신뢰할 수 있는 전략들이에요:
다른 브라우저에 다른 콘텐츠를 제공하는 것이 일반적으로 나쁜 이유에 대한 자세한 정보는 사용자 에이전트를 사용한 브라우저 감지도 참조하세요.
💡 강사 팁: 제가 코드 리뷰를 하면서 가장 많이 발견하는 안티 패턴 중 하나가 바로 브라우저 감지예요. "이 기능이 IE에서 작동하지 않으니 IE를 감지해서 다른 코드를 실행하자"는 접근은 정말 위험해요. 왜냐하면 나중에 다른 브라우저에서도 같은 문제가 발생할 수 있고, 감지 로직을 계속 업데이트해야 하거든요. 대신 'IntersectionObserver' in window처럼 기능 자체를 감지하면 어떤 브라우저든 그 기능을 지원하는지 정확히 알 수 있어요!
또한 UA 문자열에 노출되는 정보는 역사적으로 프라이버시 우려를 제기해왔어요 – 특정 사용자 에이전트를 식별하는 데 사용될 수 있고, 따라서 핑거프린팅에 사용될 수 있어요.
이러한 우려를 완화하기 위해, 지원 브라우저는 사용자 에이전트 축소를 구현해요. 이는 User-agent 헤더와 관련 API 기능을 업데이트하여 축소된 정보 세트를 제공하죠.
💡 강사 팁: 핑거프린팅은 생각보다 심각한 프라이버시 침해예요. UA 문자열, 화면 해상도, 설치된 폰트, 캔버스 렌더링 결과 등을 조합하면 사용자를 거의 유일하게 식별할 수 있어요. 이게 쿠키 없이도 사용자를 추적할 수 있는 이유죠. User-Agent 축소는 이런 핑거프린팅을 어렵게 만들기 위한 노력의 일환이에요!
지원 브라우저에서 User-Agent 축소는 UA 문자열에서 세 가지 정보를 제거해요 – 정확한 플랫폼/OS 버전, 기기 모델, 그리고 마이너 브라우저 버전이에요.
예제를 살펴보면 어떻게 보이는지 알 수 있어요. 이전에는 Android에서 실행되는 Chrome의 UA 문자열이 다음과 같았어요:
Mozilla/5.0 (Linux; Android 16; Pixel 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.12.45 Mobile Safari/537.36
User-Agent 축소 업데이트 후에는 이제 다음과 같아요:
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36
아래 섹션에서는 각 US 문자열 변경에 대한 자세한 정보를 제공해요.
플랫폼 버전과 기기 모델은 항상 고정된 값으로 표시돼요:
Android 10; KMacintosh; Intel Mac OS X 10_15_7Windows NT 10.0; Win64; x64X11; CrOS x86_64 14541.0.0X11; Linux x86_64💡 강사 팁: 이 변경사항이 특히 중요한 이유는 과거에 많은 개발자들이 모바일 기기 감지를 위해 UA 문자열을 파싱했기 때문이에요. "Pixel 9"이나 "Galaxy S24" 같은 기기명을 찾아서 특정 스타일을 적용하는 식이었죠. 이제는 모두 "K"로 통일되어서 이런 접근이 불가능해요. 대신 미디어 쿼리나 기능 감지를 사용해야 해요!
메이저 브라우저 버전 번호는 올바르게 표시되지만, 마이너 버전 번호는 항상 0으로 표시돼요 – 0.0.0.
💡 강사 팁: 이 변경은 보안 측면에서도 중요해요. 과거에는 "Chrome 142.0.5815.99"처럼 정확한 버전을 알 수 있어서, 공격자가 특정 버전의 알려진 취약점을 타겟팅하기 쉬웠어요. 이제는 메이저 버전만 알 수 있어서 이런 공격이 더 어려워졌죠!
여전히 상세한 UA 문자열 데이터에 의존하는 코드가 있을 수 있고, 이를 기능 감지나 점진적 향상을 사용하도록 변환할 수 없을 수도 있어요. 예를 들어 세밀한 로깅, 사기 방지 조치, 또는 사용자의 기기 유형에 따라 다른 콘텐츠를 제공하는 소프트웨어 도움말 사이트 같은 거죠.
이런 경우라면, 여전히 Sec-CH-UA-* 헤더(User-Agent 클라이언트 힌트라고도 알려져 있어요)를 통해 상세한 UA 문자열 데이터에 접근할 수 있어요. 이 헤더들은 그러한 정보를 보내는 더 안전하고 프라이버시를 더 보존하는 방법을 제공해요. 왜냐하면 서버가 User-Agent 문자열을 통해 항상 전송되는 것이 아니라 원하는 정보 조각에 옵트인해야 하기 때문이에요. 또한 더 광범위한 정보 선택에 대한 접근을 제공해요.
자세한 정보는 User-Agent 클라이언트 힌트를 참조하세요.
💡 강사 팁: 클라이언트 힌트는 정말 영리한 설계예요. 기본적으로 최소한의 정보만 보내고, 서버가 "이 정보가 필요해"라고 명시적으로 요청할 때만 추가 정보를 보내는 거죠. 예를 들어 Accept-CH: Sec-CH-UA-Model 헤더를 보내면 브라우저가 다음 요청부터 기기 모델 정보를 포함시켜요. 이렇게 하면 필요한 곳에서만 상세한 정보를 얻을 수 있어서 프라이버시와 기능성의 균형을 맞출 수 있어요!
User-Agent Client Hints API를 사용하면 JavaScript를 통해 클라이언트 힌트 정보에 접근할 수 있어요. Navigator.userAgentData 속성은 낮은 엔트로피 클라이언트 힌트를 나타내는 속성들을 포함하는 NavigatorUAData 객체에 대한 접근을 제공해요.
Sec-CH-UA-Model과 Sec-CH-UA-Form-Factors 같은 높은 엔트로피 힌트에 접근하려면, NavigatorUAData.getHighEntropyValues() 메서드를 사용해야 해요.
자세한 정보는 User-Agent Client Hints API를 참조하세요.
💡 강사 팁: JavaScript에서 클라이언트 힌트를 사용할 때 주의할 점이 있어요. getHighEntropyValues()는 Promise를 반환하고, 일부 브라우저에서는 사용자 권한이 필요할 수 있어요. 또한 모든 브라우저가 지원하는 건 아니어서 폴백 로직이 필요해요. 실무에서는 다음과 같이 사용해요:
if (navigator.userAgentData) {
// 클라이언트 힌트 지원
navigator.userAgentData.getHighEntropyValues(['model', 'platformVersion'])
.then(ua => {
console.log('기기 모델:', ua.model);
console.log('플랫폼 버전:', ua.platformVersion);
});
} else {
// 폴백: 기존 navigator.userAgent 사용
console.log('레거시 UA:', navigator.userAgent);
}