HTTP/Guides/User-Agent reduction

김동현·2026년 3월 22일

User-Agent 축소

User-Agent 축소는 사용자 에이전트(UA) 문자열에서 제공되는 프라이버시에 민감한 정보의 양을 줄이기 위한 광범위하게 받아들여진 브라우저 이니셔티브예요.

이 문서는 User-Agent 축소의 결과로 UA 문자열의 차이점을 보여주고, 필요할 때 축소된 UA 정보와 추가 UA 정보에 모두 접근하는 방법을 설명해요.

이 문서의 내용

배경

사용자 에이전트(UA) 문자열 – User-Agent HTTP 헤더와 Navigator.userAgent, Navigator.appVersion, Navigator.platform과 같은 관련 API 기능에서 사용 가능해요 – 은 서버와 네트워크 피어가 요청하는 사용자 에이전트의 애플리케이션, 운영 체제, 공급업체 및/또는 버전을 식별할 수 있게 해줘요.

브라우저 감지

이론적으로 UA 문자열은 브라우저를 감지하고 브라우저별 버그를 해결하거나 기능 지원 부족을 해결하기 위한 코드를 제공하는 데 유용해요. 하지만 이것은 신뢰할 수 없고 권장되지 않아요:

  • 향후 브라우저는 버그를 수정하고 새로운 기능에 대한 지원을 추가할 거예요. 그래서 브라우저 감지 코드는 실제로 테스트하려는 기능을 지원하는 브라우저를 잠그지 않도록 정기적으로 업데이트해야 해요. 기능 감지가 훨씬 더 신뢰할 수 있는 전략이에요.
  • 이 속성에서 광고하는 사용자 에이전트가 실제로 사이트가 로드된 브라우저라는 보장이 전혀 없어요. 브라우저 공급업체는 기본적으로 UA 문자열로 원하는 대로 할 수 있고, 역사적으로 일부 웹사이트에서 잠기지 않기 위해 이러한 속성에서 가짜 값을 반환하곤 했어요.
  • 일부 브라우저는 사용자가 원한다면 이 필드의 값을 변경할 수 있게 해요(UA 스푸핑).

다음은 버그와 다른 브라우저 지원을 해결하기 위한 훨씬 더 신뢰할 수 있는 전략들이에요:

  • 기능 감지: 브라우저 버전이 아닌 기능에 대한 지원을 감지하는 거예요.
  • 점진적 향상: 가능한 한 많은 사용자에게 필수 콘텐츠와 기능의 기준선을 제공하면서, 필요한 모든 코드를 실행할 수 있는 브라우저에 가능한 최상의 경험을 제공하는 거예요.

다른 브라우저에 다른 콘텐츠를 제공하는 것이 일반적으로 나쁜 이유에 대한 자세한 정보는 사용자 에이전트를 사용한 브라우저 감지도 참조하세요.

💡 강사 팁: 제가 코드 리뷰를 하면서 가장 많이 발견하는 안티 패턴 중 하나가 바로 브라우저 감지예요. "이 기능이 IE에서 작동하지 않으니 IE를 감지해서 다른 코드를 실행하자"는 접근은 정말 위험해요. 왜냐하면 나중에 다른 브라우저에서도 같은 문제가 발생할 수 있고, 감지 로직을 계속 업데이트해야 하거든요. 대신 'IntersectionObserver' in window처럼 기능 자체를 감지하면 어떤 브라우저든 그 기능을 지원하는지 정확히 알 수 있어요!

프라이버시 우려

또한 UA 문자열에 노출되는 정보는 역사적으로 프라이버시 우려를 제기해왔어요 – 특정 사용자 에이전트를 식별하는 데 사용될 수 있고, 따라서 핑거프린팅에 사용될 수 있어요.

이러한 우려를 완화하기 위해, 지원 브라우저는 사용자 에이전트 축소를 구현해요. 이는 User-agent 헤더와 관련 API 기능을 업데이트하여 축소된 정보 세트를 제공하죠.

💡 강사 팁: 핑거프린팅은 생각보다 심각한 프라이버시 침해예요. UA 문자열, 화면 해상도, 설치된 폰트, 캔버스 렌더링 결과 등을 조합하면 사용자를 거의 유일하게 식별할 수 있어요. 이게 쿠키 없이도 사용자를 추적할 수 있는 이유죠. User-Agent 축소는 이런 핑거프린팅을 어렵게 만들기 위한 노력의 일환이에요!

축소 후 UA 문자열 변경사항

지원 브라우저에서 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 문자열 변경에 대한 자세한 정보를 제공해요.

플랫폼/OS 버전 및 기기 모델

플랫폼 버전과 기기 모델은 항상 고정된 값으로 표시돼요:

  • Android에서는 Android 10; K
  • macOS에서는 Macintosh; Intel Mac OS X 10_15_7
  • Windows에서는 Windows NT 10.0; Win64; x64
  • ChromeOS에서는 X11; CrOS x86_64 14541.0.0
  • Linux에서는 X11; Linux x86_64

💡 강사 팁: 이 변경사항이 특히 중요한 이유는 과거에 많은 개발자들이 모바일 기기 감지를 위해 UA 문자열을 파싱했기 때문이에요. "Pixel 9"이나 "Galaxy S24" 같은 기기명을 찾아서 특정 스타일을 적용하는 식이었죠. 이제는 모두 "K"로 통일되어서 이런 접근이 불가능해요. 대신 미디어 쿼리나 기능 감지를 사용해야 해요!

마이너 브라우저 버전

메이저 브라우저 버전 번호는 올바르게 표시되지만, 마이너 버전 번호는 항상 0으로 표시돼요 – 0.0.0.

💡 강사 팁: 이 변경은 보안 측면에서도 중요해요. 과거에는 "Chrome 142.0.5815.99"처럼 정확한 버전을 알 수 있어서, 공격자가 특정 버전의 알려진 취약점을 타겟팅하기 쉬웠어요. 이제는 메이저 버전만 알 수 있어서 이런 공격이 더 어려워졌죠!

클라이언트 힌트를 통해 UA 정보 요청하기

여전히 상세한 UA 문자열 데이터에 의존하는 코드가 있을 수 있고, 이를 기능 감지나 점진적 향상을 사용하도록 변환할 수 없을 수도 있어요. 예를 들어 세밀한 로깅, 사기 방지 조치, 또는 사용자의 기기 유형에 따라 다른 콘텐츠를 제공하는 소프트웨어 도움말 사이트 같은 거죠.

이런 경우라면, 여전히 Sec-CH-UA-* 헤더(User-Agent 클라이언트 힌트라고도 알려져 있어요)를 통해 상세한 UA 문자열 데이터에 접근할 수 있어요. 이 헤더들은 그러한 정보를 보내는 더 안전하고 프라이버시를 더 보존하는 방법을 제공해요. 왜냐하면 서버가 User-Agent 문자열을 통해 항상 전송되는 것이 아니라 원하는 정보 조각에 옵트인해야 하기 때문이에요. 또한 더 광범위한 정보 선택에 대한 접근을 제공해요.

자세한 정보는 User-Agent 클라이언트 힌트를 참조하세요.

💡 강사 팁: 클라이언트 힌트는 정말 영리한 설계예요. 기본적으로 최소한의 정보만 보내고, 서버가 "이 정보가 필요해"라고 명시적으로 요청할 때만 추가 정보를 보내는 거죠. 예를 들어 Accept-CH: Sec-CH-UA-Model 헤더를 보내면 브라우저가 다음 요청부터 기기 모델 정보를 포함시켜요. 이렇게 하면 필요한 곳에서만 상세한 정보를 얻을 수 있어서 프라이버시와 기능성의 균형을 맞출 수 있어요!

JavaScript를 통해 클라이언트 힌트 접근하기

User-Agent Client Hints API를 사용하면 JavaScript를 통해 클라이언트 힌트 정보에 접근할 수 있어요. Navigator.userAgentData 속성은 낮은 엔트로피 클라이언트 힌트를 나타내는 속성들을 포함하는 NavigatorUAData 객체에 대한 접근을 제공해요.

Sec-CH-UA-ModelSec-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);
}
profile
프론트에_가까운_풀스택_개발자

0개의 댓글