새 HTML <permission> 요소에 대한 오리진 트라이얼

웹 앱에서 위치 정보 액세스와 같은 강력한 기능을 사용할 권한을 요청하는 여러 명령형 메서드가 있습니다. 이러한 방법에는 여러 가지 문제가 있으므로 Chrome 권한팀은 전용 HTML <permission> 요소인 새로운 선언적 방법을 실험하고 있습니다. 이 요소는 Chrome 126부터 오리진 트라이얼에 있으며 최종적으로 표준화되기를 바랍니다.

권한 요청을 위한 명령형 메서드

웹 앱에서 강력한 기능에 액세스해야 하는 경우 권한을 요청해야 합니다. 예를 들어 Google 지도에서 위치정보 API를 사용하여 사용자의 위치를 요구하는 경우 브라우저에서 사용자에게 메시지를 표시하며, 이 결정을 저장하는 옵션도 제공합니다. 이는 권한 사양에서 잘 정의된 개념입니다.

처음 사용할 때 암시적으로 묻기 vs. 미리 명시적으로 요청하기

위치정보 API는 강력한 API이며 첫 사용 시 암시적으로 묻는 방식을 사용합니다. 예를 들어 앱이 navigator.geolocation.getCurrentPosition() 메서드를 호출하면 첫 번째 호출 시 권한 메시지가 자동으로 표시됩니다. 또 다른 예는 navigator.mediaDevices.getUserMedia()입니다.

알림 API 또는 기기 방향 및 동작 API와 같은 다른 API에는 일반적으로 Notification.requestPermission() 또는 DeviceMotionEvent.requestPermission()과 같은 정적 메서드를 통해 권한을 요청하는 명시적인 방법이 있습니다.

권한 요청을 위한 명령형 메서드의 문제점

권한 스팸

이전에는 웹사이트가 로드될 때 웹사이트에서 navigator.mediaDevices.getUserMedia() 또는 Notification.requestPermission()과 같은 메서드를 호출할 수 있었을 뿐만 아니라 navigator.geolocation.getCurrentPosition()도 즉시 호출할 수 있었습니다. 사용자가 웹사이트와 상호작용하기 전에 권한 메시지가 표시됩니다. 이를 권한 스팸이라고도 하며, 첫 사용 시 암시적으로 요청하는 방식과 미리 명시적으로 요청하는 방식 모두에 영향을 미칩니다.

웹사이트를 로드할 때 표시되는 마이크 권한 메시지

브라우저 완화 및 사용자 동작 요구사항

권한 스팸으로 인해 브라우저 공급업체는 권한 메시지를 표시하기 전에 버튼 클릭이나 keydown 이벤트와 같은 사용자 동작을 요구했습니다. 이 접근 방식의 문제는 브라우저가 특정 사용자 동작으로 인해 권한 메시지가 표시되어야 하는지 여부를 파악하기가 매우 어렵다는 것입니다. 페이지 로드에 너무 오래 걸려 사용자가 답답한 마음에 페이지를 아무 곳이나 클릭했을 수도 있고, 실제로 내 위치 찾기 버튼을 클릭했을 수도 있습니다. 일부 웹사이트는 사용자에게 콘텐츠를 클릭하도록 유도하여 프롬프트를 트리거하는 데 매우 능숙해졌습니다.

또 다른 완화 방법은 처음부터 기능을 완전히 차단하거나 모달이 아닌 덜 방해적인 방식으로 권한 프롬프트를 표시하는 등 프롬프트 악용 완화 조치를 추가하는 것입니다.

Chrome 브라우저에

권한 컨텍스트화

특히 대형 화면에서 또 다른 문제는 권한 메시지가 일반적으로 표시되는 방식입니다. 즉, 죽음의 선 위에 표시됩니다. 즉, 앱이 그릴 수 있는 브라우저 창 영역 외부에 표시됩니다. 사용자가 창 하단의 버튼을 클릭했을 때 브라우저 창 상단의 메시지를 놓치는 것은 드문 일이 아닙니다. 이 문제는 브라우저 스팸 완화 조치가 적용된 경우 악화되는 경우가 많습니다.

위치 정보 액세스 권한 프롬프트가 열린 Google 지도 프롬프트를 트리거한 위치 액세스 버튼이 멀리 떨어져 있습니다.

간단하게 실행취소할 수 없음

마지막으로 사용자가 막다른 길로 쉽게 이동할 수 있습니다. 예를 들어 사용자가 기능에 대한 액세스를 차단한 후에는 권한을 재설정하거나 차단된 권한을 다시 사용 설정할 수 있는 사이트 정보 드롭다운을 알아야 합니다. 최악의 경우 두 옵션 모두 업데이트된 설정이 적용될 때까지 페이지를 완전히 새로고침해야 합니다. 사이트는 사용자가 기존 권한 상태를 변경할 수 있는 쉬운 바로가기를 제공할 수 없으며 다음 Google 지도 스크린샷 하단에 표시된 것처럼 사용자에게 설정을 변경하는 방법을 세심하게 설명해야 합니다.

Google 지도에서 Chrome 사이트 제어를 사용하여 권한을 취소합니다.

권한이 환경에 중요한 경우(예: 화상 회의 애플리케이션의 마이크 액세스) Google Meet과 같은 앱은 사용자에게 권한 차단을 해제하는 방법을 안내하는 방해적인 대화상자를 표시합니다.

Chrome 사이트 제어 기능을 여는 방법에 관한 Google Meet 안내

선언적 <permission> 요소

이 게시물에 설명된 문제를 해결하기 위해 Chrome 권한 팀에서는 새로운 HTML 요소인 <permission>의 오리진 트라이얼을 시작했습니다. 이 요소를 사용하면 개발자가 현재 웹사이트에서 사용할 수 있는 강력한 기능의 하위 집합을 사용하기 위한 권한을 선언적으로 요청할 수 있습니다. 가장 간단한 형태에서는 다음 예와 같이 사용합니다.

<permission type="camera" />

<permission>이 void 요소여야 하는지 여부는 아직 활발하게 논의되고 있습니다. void 요소는 하위 노드를 가질 수 없는 HTML의 자체 닫힘 요소입니다. HTML에서는 종료 태그가 없을 수 있습니다.

type 속성

type 속성에는 요청하는 권한의 공백으로 구분된 목록이 포함됩니다. 이 글을 작성하는 시점에 허용되는 값은 'camera', 'microphone', camera microphone입니다 (공백으로 구분). 이 요소는 기본적으로 최소한의 사용자 에이전트 스타일이 적용된 버튼과 유사하게 렌더링됩니다.

카메라, 마이크, 카메라와 마이크 권한이 있는 다양한 권한 요소 버튼

type-ext 속성

추가 매개변수를 허용하는 일부 권한의 경우 type-ext 속성은 공백으로 구분된 키-값 쌍을 허용합니다(예: 위치정보 권한의 경우 precise:true).

lang 속성

버튼 텍스트는 브라우저에서 제공되며 일관성을 유지해야 하므로 직접 맞춤설정할 수 없습니다. 브라우저는 문서 또는 상위 요소 체인의 상속된 언어 또는 선택적 lang 속성을 기반으로 텍스트의 언어를 변경합니다. 즉, 개발자가 <permission> 요소를 직접 현지화할 필요가 없습니다. <permission> 요소가 오리진 트라이얼 단계를 넘어 진행되면 유연성을 높이기 위해 각 권한 유형에 여러 문자열이나 아이콘이 지원될 수 있습니다. <permission> 요소를 사용하고 싶고 특정 문자열이나 아이콘이 필요한 경우 문의하세요.

동작

사용자가 <permission> 요소와 상호작용하면 다음과 같은 다양한 단계를 순환할 수 있습니다.

  • 이전에 기능을 허용하지 않은 경우 방문할 때마다 허용하거나 현재 방문에 대해 허용할 수 있습니다.

    이번에 또는 방문할 때마다 기능을 허용하라는 권한 메시지

  • 이전에 기능을 허용한 경우 계속 허용하거나 허용을 중지할 수 있습니다.

    계속 허용하거나 허용 중지하라는 권한 메시지

  • 이전에 기능을 허용하지 않은 경우 계속 허용하지 않거나 이번에는 허용할 수 있습니다.

    계속 허용하지 않거나 이번에만 허용하라는 권한 메시지

<permission> 요소의 텍스트는 상태에 따라 자동으로 업데이트됩니다. 예를 들어 기능을 사용할 권한이 부여된 경우 텍스트가 기능이 허용되었다고 표시됩니다. 권한을 먼저 부여해야 하는 경우 텍스트가 변경되어 사용자에게 기능을 사용하도록 안내합니다. 이전 스크린샷과 다음 스크린샷을 비교하여 두 상태를 확인하세요.

텍스트가 포함된 권한 버튼

CSS 디자인

사용자가 강력한 기능에 액세스하는 서피스로 버튼을 쉽게 인식할 수 있도록 <permission> 요소의 스타일은 제한됩니다. 스타일 지정 제한이 사용 사례에 맞지 않는 경우 그 이유와 방법을 알려주세요. 모든 스타일 요구사항을 수용할 수는 없지만, 오리진 트라이얼이 끝난 후 <permission> 요소의 스타일을 더 많이 지정할 수 있는 안전한 방법을 찾고 있습니다. 다음 표에서는 제한사항이나 특별 규칙이 적용되는 속성을 자세히 설명합니다. 규칙을 위반하는 경우 <permission> 요소가 사용 중지되어 상호작용할 수 없습니다. 이와 상호작용하려고 하면 JavaScript로 포착할 수 있는 예외가 발생합니다. 오류 메시지에는 감지된 위반에 관한 자세한 내용이 포함됩니다.

속성 규칙

color, background-color

각각 텍스트와 배경 색상을 설정하는 데 사용할 수 있습니다. 두 색상 간의 대비는 텍스트를 명확하게 읽을 수 있을 만큼 충분해야 합니다 (대비율이 3 이상). 알파 채널은 1이어야 합니다.

font-size, zoom

smallxxxlarge에 해당하는 값으로 설정해야 합니다. 그렇지 않으면 요소가 사용 중지됩니다. font-size를 계산할 때 확대/축소가 고려됩니다.

outline-offset

음수 값은 0로 수정됩니다.
margin(전체) 음수 값은 0로 수정됩니다.

font-weight

200 미만의 값은 200로 수정됩니다.

font-style

normalitalic 이외의 값은 normal로 수정됩니다.

word-spacing

0.5em을 초과하는 값은 0.5em으로 수정됩니다. 0 미만의 값은 0로 수정됩니다.

display

inline-blocknone 이외의 값은 inline-block로 수정됩니다.

letter-spacing

0.2em을 초과하는 값은 0.2em으로 수정됩니다. -0.05em 미만의 값은 -0.05em로 수정됩니다.

min-height

기본값은 1em입니다. 제공된 경우 기본값과 제공된 값 사이의 최대 계산 값이 고려됩니다.

max-height

기본값은 3em입니다. 제공된 경우 기본값과 제공된 값 사이의 최소 계산 값이 고려됩니다.

min-width

기본값은 fit-content입니다. 제공된 경우 기본값과 제공된 값 사이의 최대 계산 값이 고려됩니다.

max-width

기본값은 fit-content의 3배입니다. 제공된 경우 기본값과 제공된 값 사이의 최소 계산 값이 고려됩니다.

padding-top

heightauto로 설정된 경우에만 적용됩니다. 이 경우 1em을 초과하는 값은 1em로 수정되고 padding-bottompadding-top 값으로 설정됩니다.

padding-left

widthauto로 설정된 경우에만 적용됩니다. 이 경우 5em을 초과하는 값은 5em로 수정되고 padding-rightpadding-left. 값으로 설정됩니다.

transform

왜곡된 시각 효과는 허용되지 않습니다. 현재는 2D 변환과 비례 업스케일링만 허용됩니다.

다음 CSS 속성은 정상적으로 사용할 수 있습니다.

  • font-kerning
  • font-optical-sizing
  • font-stretch
  • font-synthesis-weight
  • font-synthesis-style
  • font-synthesis-small-caps
  • font-feature-settings
  • forced-color-adjust
  • text-rendering
  • align-self
  • anchor-name aspect-ratio
  • border (및 모든 border-* 속성)
  • clear
  • color-scheme
  • contain
  • contain-intrinsic-width
  • contain-intrinsic-height
  • container-name
  • container-type
  • counter-*
  • flex-*
  • float
  • height
  • isolation
  • justify-self
  • left
  • order
  • orphans
  • outline-* (outline-offset에 대해 이전에 언급한 예외 적용)
  • overflow-anchor
  • overscroll-behavior-*
  • page
  • position
  • position-anchor
  • content-visibility
  • right
  • scroll-margin-*
  • scroll-padding-*
  • text-spacing-trim
  • top
  • visibility
  • x
  • y
  • ruby-position
  • user-select
  • width
  • will-change
  • z-index

또한 논리적으로 동일한 모든 속성을 해당 속성과 동일한 규칙에 따라 사용할 수 있습니다 (예: inline-sizewidth과 동일).

의사 클래스

상태에 따라 <permission> 요소를 스타일 지정할 수 있는 두 가지 특수 의사 클래스가 있습니다.

  • :granted: :granted 의사 클래스를 사용하면 권한이 부여된 경우 특별한 스타일을 지정할 수 있습니다.
  • :invalid: :invalid 가상 클래스를 사용하면 요소가 잘못된 상태일 때(예: 교차 출처 iframe에서 제공되는 경우) 특별한 스타일을 지정할 수 있습니다.
permission {
  background-color: green;
}

permission:granted {
  background-color: light-green;
}

/* Not supported during the origin trial. */
permission:invalid {
  background-color: gray;
}

자바스크립트 이벤트

<permission> 요소는 권한 API와 함께 사용해야 합니다. 수신 대기할 수 있는 이벤트는 다음과 같습니다.

  • onpromptdismiss: 이 이벤트는 요소에 의해 트리거된 권한 메시지가 사용자에 의해 닫힐 때 (예: 닫기 버튼을 클릭하거나 메시지 외부를 클릭) 발생합니다.

  • onpromptaction: 이 이벤트는 요소에 의해 트리거된 권한 메시지가 사용자가 메시지 자체에 대해 어떤 조치를 취함으로써 해결된 경우에 발생합니다. 이는 권한 상태가 변경되었다는 의미는 아닙니다. 사용자가 현 상태를 유지하는 작업을 실행했을 수 있습니다 (예: 권한을 계속 허용).

  • onvalidationstatuschange: 이 이벤트는 요소가 "valid"에서 "invalid"로 전환될 때 발생합니다. 사용자가 클릭할 경우 브라우저가 신호의 무결성을 신뢰하면 요소가 "valid"로 간주되고, 그렇지 않으면(예: 요소가 다른 HTML 콘텐츠에 의해 부분적으로 가려진 경우) "invalid"로 간주됩니다.

다음 예와 같이 HTML 코드(<permission type="…" onpromptdismiss="alert('The prompt was dismissed');" />)에서 직접 인라인으로 또는 <permission> 요소에서 addEventListener()을 사용하여 이러한 이벤트의 이벤트 리스너를 등록할 수 있습니다.

<permission type="camera" />
<script>
  const permission = document.querySelector('permission');
  permission.addEventListener('promptdismiss', showCameraWarning);

  function showCameraWarning() {
    // Show warning that the app isn't fully usable
    // unless the camera permission is granted.
  }

  const permissionStatus = await navigator.permissions.query({name: "camera"});
  
  permissionStatus.addEventListener('change', () => {
    // Run the check when the status changes.
    if (permissionStatus.state === "granted") {
      useCamera();
    }
  });

  // Run the initial check.
  if (permissionStatus.state === "granted") {
    useCamera();
  }
</script>

기능 감지

브라우저가 HTML 요소를 지원하지 않으면 표시되지 않습니다. 즉, HTML 코드에 <permission> 요소가 있는 경우 브라우저가 이를 인식하지 못하면 아무 일도 일어나지 않습니다. 예를 들어 일반 <button> 클릭을 통해 트리거되는 권한 프롬프트를 만들기 위해 JavaScript를 사용하여 지원을 감지할 수 있습니다.

if ('HTMLPermissionElement' in window) {
  // The `<permission>` element is supported.
}

오리진 트라이얼

실제 사용자를 대상으로 사이트에서 <permission> 요소를 사용해 보려면 오리진 트라이얼에 가입하세요. 오리진 트라이얼 시작하기를 읽고 오리진 트라이얼을 사용하도록 사이트를 준비하는 방법을 알아보세요. 오리진 트라이얼은 Chrome 126~131 (2025년 2월 19일)에서 실행됩니다.

데모

데모를 살펴보고 GitHub에서 소스 코드를 확인하세요. 지원되는 브라우저의 환경을 보여주는 스크린샷입니다.

권한 버튼 3개를 보여주는 권한 요소 데모

의견

<permission>가 사용 사례에 어떻게 적용되는지 알려주세요. 저장소의 문제 중 하나에 응답하거나 새 문제를 제출하세요. <permission> 요소의 저장소에 있는 공개 신호를 통해 Google 및 기타 브라우저에 관심이 있음을 알릴 수 있습니다.

FAQ

  • 권한 API와 페어링된 일반 <button>보다 나은 점은 무엇인가요? <button> 클릭은 사용자 동작이지만 브라우저에서는 권한 요청과 연결되어 있는지 확인할 방법이 없습니다. 사용자가 <permission>를 클릭한 경우 브라우저는 클릭이 권한 요청과 관련이 있다고 확신할 수 있습니다. 이를 통해 브라우저는 그렇지 않으면 훨씬 더 위험한 흐름을 촉진할 수 있습니다. 예를 들어 사용자가 권한 차단을 쉽게 실행취소할 수 있도록 허용합니다.
  • 다른 브라우저에서 <permission> 요소를 지원하지 않으면 어떻게 되나요? <permission> 요소는 점진적 개선으로 사용할 수 있습니다. 지원되지 않는 브라우저에서는 기존 권한 흐름을 사용할 수 있습니다. 예를 들어 일반 <button>의 클릭을 기반으로 합니다. 권한팀에서도 폴리필을 작업하고 있습니다. 준비가 완료되면 알림을 받으려면 GitHub 저장소에 별표를 표시하세요.
  • 다른 브라우저 공급업체와 이 문제를 논의했나요? <permission> 요소는 2023년 W3C TPAC에서 브레이크아웃 세션을 통해 적극적으로 논의되었습니다. 공개 세션 메모를 읽을 수 있습니다. Chrome팀은 두 공급업체에 공식 표준 입장을 요청했습니다(관련 링크 섹션 참고). <permission> 요소는 다른 브라우저와 계속 논의 중인 주제이며 표준화되기를 바랍니다.
  • 이 요소가 실제로 빈 요소여야 하나요? <permission>이 void 요소여야 하는지 여부는 아직 활발하게 논의되고 있습니다. 의견이 있으면 문제에 참여하세요.

감사의 말씀

이 문서는 발라즈 엔게디, 토마스 응우옌, 페넬로피 맥라클란, 마리안 하르바흐, 데이비드 워런, 레이첼 앤드루의 검토를 거쳤습니다.