기능 정책 소개

에릭 비델만

요약

기능 정책을 사용하면 웹 개발자가 브라우저에서 특정 API 및 웹 기능의 동작을 선택적으로 사용 설정, 사용 중지, 수정할 수 있습니다. CSP와 비슷하지만 보안을 제어하는 대신 기능을 제어합니다.

기능 정책 자체는 개발자와 브라우저 간의 거의 수신 동의 계약이며, 이는 고품질 웹 앱을 빌드 (및 유지)하는 Google의 목표를 촉진하는 데 도움이 될 수 있습니다.

소개

웹용으로 구축은 어려운 모험입니다. 최고의 성능을 발휘하고 최신 권장사항을 모두 사용하는 최상급 웹 앱을 빌드하기는 쉽지 않습니다. 시간이 지나도 이러한 경험을 훌륭하게 유지하는 것은 더욱 어렵습니다. 프로젝트가 발전함에 따라 개발자가 참여하고 새로운 기능이 추가되고 코드베이스가 증가합니다. 이전에 달성한 훌륭한 경험(TM)이 악화되기 시작하고 UX가 악화되기 시작할 수 있습니다. 기능 정책은 개발자가 문제를 해결할 수 있도록 돕기 위해 마련되었습니다.

기능 정책을 사용하면 브라우저의 일련의 '정책'을 선택하여 사이트 전체에서 사용되는 특정 기능에 시행할 수 있습니다. 이 정책은 사이트에서 특정 기능에 대한 브라우저의 기본 동작을 수정하거나 액세스할 수 있는 API를 제한합니다.

다음은 기능 정책을 사용하여 수행할 수 있는 작업의 예입니다.

  • 모바일 및 서드 파티 동영상에서 autoplay기본 동작을 변경합니다.
  • 사이트에서 camera 또는 microphone와 같은 민감한 API를 사용하지 못하도록 제한합니다.
  • iframe에서 fullscreen API를 사용하도록 허용합니다.
  • 동기 XHR 및 document.write()와 같은 오래된 API의 사용을 차단합니다.
  • 이미지의 크기가 적절한지 (예: 레이아웃 스래싱 방지) 및 표시 영역에 비해 너무 크지 않은지 (예: 사용자의 대역폭 낭비) 확인합니다.

정책은 개발자와 브라우저 간의 계약입니다. 이러한 API는 개발자의 의도를 브라우저에 알리므로, 앱이 도를 넘어서 잘못된 작업을 하려고 할 때 이를 정직하게 유지할 수 있습니다. 사이트 또는 삽입된 서드 파티 콘텐츠가 개발자가 미리 선택한 규칙을 위반하려고 하면 브라우저에서 더 나은 UX로 동작을 재정의하거나 API를 완전히 차단합니다.

기능 정책 사용

기능 정책은 두 가지 방법으로 기능을 제어합니다.

  1. Feature-Policy HTTP 헤더를 통해 전달
  2. iframe에서 allow 속성 사용

기능 정책을 사용하는 가장 쉬운 방법은 Feature-Policy HTTP 헤더를 페이지 응답과 함께 전송하는 것입니다. 이 헤더의 값은 브라우저에서 지정된 출처에 적용할 정책 또는 정책 집합입니다.

Feature-Policy: <feature> <allow list origin(s)>

출처 허용 목록은 다음과 같은 여러 값을 사용할 수 있습니다.

  • *: 이 기능은 최상위 탐색 컨텍스트 및 중첩된 탐색 컨텍스트 (iframe)에서 허용됩니다.
  • 'self': 이 기능은 최상위 탐색 컨텍스트 및 동일 출처 중첩 탐색 컨텍스트에서 허용됩니다. 중첩된 탐색 컨텍스트의 교차 출처 문서에서는 허용되지 않습니다.
  • 'none': 이 기능은 최상위 탐색 컨텍스트에서 허용되지 않고 중첩된 탐색 컨텍스트에서는 허용되지 않습니다.
  • <origin(s)>: 정책을 사용 설정할 특정 출처입니다 (예: https://example.com).

모든 콘텐츠가 사이트에서 Geolocation API를 사용하지 못하도록 차단한다고 가정해 보겠습니다. 그렇게 하려면 geolocation 기능에 'none'의 엄격한 허용 목록을 전송하면 됩니다.

Feature-Policy: geolocation 'none'

코드 또는 iframe에서 Geolocation API를 사용하려고 하면 브라우저에서 이를 차단합니다. 사용자가 이전에 위치 공유 권한을 부여한 경우에도 마찬가지입니다.

설정된 위치정보 정책 위반
설정된 위치정보 정책 위반

경우에 따라 이 정책을 약간 완화하는 것이 좋습니다. 자체 출처에서 Geolocation API를 사용하도록 허용하지만 허용 목록에서 'self'를 설정하여 서드 파티 콘텐츠의 액세스를 차단할 수 있습니다.

Feature-Policy: geolocation 'self'

iframe allow 속성

기능 정책을 사용하는 두 번째 방법은 iframe 내에서 콘텐츠를 제어하는 것입니다. allow 속성을 사용하여 삽입된 콘텐츠의 정책 목록을 지정합니다.

<!-- Allow all browsing contexts within this iframe to use fullscreen. -->
<iframe src="https://example.com..." allow="fullscreen"></iframe>

<!-- Equivalent to: -->
<iframe src="https://example.com..." allow="fullscreen *"></iframe>

<!-- Allow only iframe content on a particular origin to access the user's location. -->
<iframe
  src="https://another-example.com/demos/..."
  allow="geolocation https://another-example.com"
></iframe>

기존 iframe 속성은 어떻게 되나요?

일부 기능 정책에 의해 제어되는 기능에는 동작을 제어하는 기존 속성이 있습니다. 예를 들어 <iframe allowfullscreen>는 iframe 콘텐츠가 HTMLElement.requestFullscreen() API를 사용하도록 허용하는 속성입니다. Payment Request APIgetUserMedia()를 각각 허용하는 allowpaymentrequest 속성과 allowusermedia 속성도 있습니다.

가능한 경우 이러한 이전 속성 대신 allow 속성을 사용해 보세요. 동등한 기존 속성과 함께 allow 속성을 사용하여 이전 버전과의 호환성을 지원해야 하는 경우에는 아무 문제가 없습니다 (예: <iframe allowfullscreen allow="fullscreen">). 다만 좀 더 제한적인 정책이 우선합니다. 예를 들어 다음 iframe은 allow="fullscreen 'none'"allowfullscreen보다 더 제한적이므로 전체 화면으로 전환될 수 없습니다.

<!-- Blocks fullscreen access if the browser supports feature policy. -->
<iframe allowfullscreen allow="fullscreen 'none'" src="..."></iframe>

한 번에 여러 정책 제어

;로 구분된 정책 지시어 목록과 함께 HTTP 헤더를 전송하여 여러 기능을 동시에 제어할 수 있습니다.

Feature-Policy: unsized-media 'none'; geolocation 'self' https://example.com; camera *;

또는 각 정책에 대해 별도의 헤더를 전송합니다.

Feature-Policy: unsized-media 'none'
Feature-Policy: geolocation 'self' https://example.com
Feature-Policy: camera *;

이 예에서는 다음을 실행합니다.

  • 모든 탐색 컨텍스트에 unsized-media를 사용하는 것을 허용하지 않습니다.
  • 페이지의 자체 출처와 https://example.com를 제외한 모든 탐색 컨텍스트에 geolocation를 사용하는 것을 허용하지 않습니다.
  • 모든 탐색 컨텍스트에 camera 액세스를 허용합니다.

- 하나의 iframe에 여러 정책 설정

<!-- Blocks the iframe from using the camera and microphone
     (if the browser supports feature policy). -->
<iframe allow="camera 'none'; microphone 'none'"></iframe>

JavaScript API

Chrome 60에서는 iframe에 Feature-Policy HTTP 헤더 및 allow 속성 지원이 추가되었지만 Chrome 74에는 JavaScript API가 추가되었습니다.

이 API를 사용하면 클라이언트 측 코드가 페이지, 프레임 또는 브라우저에서 허용되는 기능을 확인할 수 있습니다. 기본 문서의 경우 document.featurePolicy, iframe의 경우 frame.featurePolicy에서 항목에 액세스할 수 있습니다.

아래 예는 https://example.com 사이트에 Feature-Policy: geolocation 'self' 정책을 전송한 결과를 보여줍니다.

/* @return {Array<string>} List of feature policies allowed by the page. */
document.featurePolicy.allowedFeatures();
// → ["geolocation", "midi",  "camera", "usb", "autoplay",...]

/* @return {boolean} True if the page allows the 'geolocation' feature. */
document.featurePolicy.allowsFeature('geolocation');
// → true

/* @return {boolean} True if the provided origin allows the 'geolocation' feature. */
document.featurePolicy.allowsFeature(
  'geolocation',
  'https://another-example.com/'
);
// → false

/* @return {Array<string>} List of feature policies allowed by the browser
regardless of whether they are in force. */
document.featurePolicy.features();
// → ["geolocation", "midi",  "camera", "usb", "autoplay",...]

/* @return {Array<string>} List of origins (used throughout the page) that are
   allowed to use the 'geolocation' feature. */
document.featurePolicy.getAllowlistForFeature('geolocation');
// → ["https://example.com"]

정책 목록

그렇다면 기능 정책을 통해 제어할 수 있는 기능은 무엇일까요?

현재 구현되는 정책과 정책 사용 방법에 관한 문서가 없습니다. 또한 다양한 브라우저에서 사양을 채택하고 다양한 정책을 구현하므로 시간이 지남에 따라 목록이 늘어납니다. 기능 정책은 움직이는 목표이므로 유용한 참고 서류가 반드시 필요합니다.

지금은 두 가지 방법으로 어떤 기능을 제어할 수 있는지 확인할 수 있습니다.

  • 데모의 기능 정책 키친 싱크를 확인하세요. Blink에서 구현된 각 정책의 예가 나와 있습니다.
  • 기능 이름 목록은 Chrome 소스를 확인하세요.
  • about:blank에서 document.featurePolicy.allowedFeatures()를 쿼리하여 목록을 찾습니다.
        ["geolocation",
         "midi",
         "camera",
         "usb",
         "magnetometer",
         "fullscreen",
         "animations",
         "payment",
         "picture-in-picture",
         "accelerometer",
         "vr",
        ...
  • chromestatus.com에서 Blink에서 구현되었거나 고려 중인 정책을 확인하세요.

이러한 정책을 사용하는 방법을 확인하려면 사양의 GitHub 저장소를 확인하세요. 일부 정책에 대한 몇 가지 설명이 포함되어 있습니다.

FAQ

기능 정책은 언제 사용하나요?

모든 정책은 선택 사항이므로, 필요한 경우 기능 정책을 사용하세요. 예를 들어 앱이 이미지 갤러리인 경우 maximum-downscaling-image 정책을 사용하면 모바일 표시 영역으로 거대한 이미지를 전송하지 않을 수 있습니다.

document-writesync-xhr와 같은 다른 정책은 더 주의해서 사용해야 합니다. 사용 설정하면 광고와 같은 서드 파티 콘텐츠가 손상될 수 있습니다. 반면에 기능 정책은 직감적으로 확인하여 페이지에서 이러한 심각한 API를 사용하지 않도록 할 수 있습니다.

개발 또는 프로덕션에서 기능 정책을 사용하나요?

둘 다 개발 중에는 정책을 사용 설정하고 프로덕션 단계에서는 정책을 활성 상태로 유지하는 것이 좋습니다. 개발 중에 정책을 사용 설정하면 올바른 방법으로 시작할 수 있습니다. 이를 통해 예기치 않은 회귀가 발생하기 전에 포착할 수 있습니다 프로덕션에서 정책을 사용 설정된 상태로 유지하여 사용자에게 특정 UX를 보장합니다.

내 서버에 정책 위반을 신고할 수 있는 방법이 있나요?

Reporting API작업 중입니다. 사이트에서 CSP 위반 또는 지원 중단에 관한 보고서를 수신하도록 선택하는 방법과 마찬가지로, 기능 정책 위반에 관한 보고서를 실제로 받을 수 있습니다.

iframe 콘텐츠에 대한 상속 규칙은 무엇인가요?

스크립트 (퍼스트 파티 또는 서드 파티)는 탐색 컨텍스트의 정책을 상속합니다. 즉, 최상위 스크립트는 기본 문서의 정책을 상속합니다.

iframe는 상위 페이지의 정책을 상속합니다. iframeallow 속성이 있으면 상위 페이지와 allow 목록 사이의 더 엄격한 정책이 우선합니다. iframe 사용에 관한 자세한 내용은 iframe의 allow 속성을 참고하세요.

아니요. 정책의 전체 기간은 단일 페이지 탐색 응답과 적용됩니다. 사용자가 새 페이지로 이동하는 경우 정책을 적용하려면 Feature-Policy 헤더가 새 응답에서 명시적으로 전송되어야 합니다.

어떤 브라우저에서 기능 정책을 지원하나요?

브라우저 지원에 관한 최신 세부정보는 caniuse.com을 참고하세요.

현재 Chrome에서만 기능 정책을 지원합니다. 하지만 전체 API 노출 영역이 선택되거나 기능을 감지할 수 있으므로 기능 정책은 점진적인 개선에 적합합니다.

결론

기능 정책은 더 나은 UX와 우수한 성능을 향한 명확한 경로를 제공하는 데 도움이 될 수 있습니다. 이 방법은 코드베이스에 침투하기 전에 잠재적인 풋건을 방지하는 데 도움이 되므로 앱을 개발하거나 유지보수할 때 특히 유용합니다.

추가 리소스: