
Chrome 144에서 <geolocation> 요소를 선보인 데 이어, Chrome 151부터는 카메라와 마이크를 위한 <usermedia> HTML 요소를 사용할 수 있습니다. Capability Elements 제품군에 새롭게 합류한 이 요소는 범용 권한을 요청하던 기존 방식에서 벗어나, 사용자가 필요한 기능을 직접 활성화하는 방식으로의 전환을 보여줍니다.
<usermedia>는 스크립트가 띄우는 권한 프롬프트를 선언적이고 사용자 동작에 기반한 경험으로 대체합니다. 덕분에 반복적인 코드가 줄고 보안이 향상되며, 접근을 거부했던 사용자도 권한을 복구할 수 있습니다. 오랫동안 문제로 남아 있던 권한의 구멍(permission hole)을 효과적으로 해결하게 됩니다.
<usermedia>는 <geolocation>에 이어 Capability Elements 제품군에서 두 번째로 출시되는 기능별 HTML 요소입니다. PEPC(Page-Embedded Permission Control) 이니셔티브에 포함되었던 초기의 범용 <permission> 제안에서 발전한 형태입니다. 기능마다 별도의 요소를 제공하면 브라우저가 각 하드웨어의 고유한 동작과 복잡성을 더 효과적으로 처리할 수 있습니다. 초기 제안에선 허용과 거부 같은 권한 관리에 주로 초점을 맞췄지만, Capability Elements는 데이터 중개자 역할을 합니다.
<geolocation> 요소가 사이트에 위치 객체를 제공한다면, <usermedia>는 카메라와 마이크 접근에 필요한 전체 과정을 관리합니다. 사용자의 선택을 확인하고, 브라우저 권한 프롬프트를 관리한 뒤, 애플리케이션에 MediaStream 객체를 전달합니다. 따라서 getUserMedia()를 별도로 호출할 필요가 없어 구현이 단순해지며, 브라우저도 사용자가 직접 요청한 권한이라는 사실을 알 수 있습니다.
정식 출시에 앞서 실제 사이트에서 시험한 결과, 권한이 필요한 시점에 사용자가 직접 요청하도록 하자 권한 설정 성공률이 크게 높아졌습니다.
<usermedia> 요소를 사용해야 할까?<usermedia>는 <geolocation>에서 확립한 패턴을 바탕으로, 강력한 기능의 권한을 요청할 때 발생하는 핵심 문제를 해결합니다. 기존 미디어 권한 요청은 명령형 자바스크립트 호출에 의존하기 때문에, 사용자가 아직 카메라나 마이크를 사용하려 하지 않았는데도 갑자기 권한을 묻는 상황이 생길 수 있습니다. 사용자가 실수로 권한을 거부하면 이 결정을 되돌리기 위해 브라우저 설정 깊숙한 곳까지 찾아가야 합니다. 이런 권한의 구멍은 결국 사용자가 기능 자체를 포기하게 만들곤 합니다.
<usermedia> 요소는 다음과 같은 방법으로 이 문제를 해결합니다.
| 비교 항목 | getUserMedia() JS API | <usermedia> HTML 요소 |
|---|---|---|
| 권한 프롬프트가 실행되는 시점 | 명령형 스크립트 실행(getUserMedia) | 사용자가 브라우저에서 관리하는 요소를 클릭할 때 |
| 브라우저의 역할 | 상태와 휴리스틱을 바탕으로 프롬프트 표시 여부를 결정 | 데이터 중개자 역할을 수행하며 동의 과정과 스트림 전달을 관리 |
| 사이트의 역할 | 자바스크립트 API를 직접 호출하고 콜백과 오류를 관리 | stream 이벤트를 수신하고 stream 프로퍼티에 접근 |
| 핵심 목표 | 기본적인 카메라·마이크 접근 | 스트림 접근, 권한 관리, 불편을 줄인 권한 복구 |
<usermedia> 요소는 기존 자바스크립트 API보다 훨씬 적은 코드로 통합할 수 있습니다. <geolocation>에서 확립한 선언적 패턴에 따라 HTML에 <usermedia> 태그를 추가하고, setConstraints() 메서드로 필요한 하드웨어 조건을 설정하면 됩니다.
참고: 아래 설명은 브라우저가
<usermedia>요소를 지원한다고 가정합니다. 지원하지 않는 브라우저까지 처리하려면 뒤에서 설명할 직접 폴백을 구현하는 패턴을 참고하세요.
<usermedia id="media-ctrl">
<button>카메라와 마이크 활성화</button>
</usermedia>
const el = document.getElementById("media-ctrl");
// 사용자가 상호작용하기 전에 원하는 하드웨어 조건 지정
el.setConstraints({
video: { width: 1280, height: 720 },
audio: { echoCancellation: true },
});
// 스트림을 성공적으로 가져온 경우.
el.addEventListener("stream", () => {
videoPreview.srcObject = el.stream;
});
// 스트림을 가져오지 못한 경우
el.addEventListener("error", () => {
console.error(`접근 실패: ${el.error?.name}`);
});
// 사용자가 프롬프트를 취소하거나 닫은 경우
el.addEventListener("cancel", () => {
console.log("사용자가 권한 프롬프트를 닫았습니다.");
});
stream: 사용자가 접근을 허용하면 MediaStream 객체를 제공하는 읽기 전용 프로퍼티입니다.setConstraints(): 사용자와 상호작용하기 전에 deviceId나 해상도 같은 하드웨어 조건을 변경할 수 있는 메서드입니다.error: 요청이 실패하거나 닫힌 경우 NotAllowedError와 같은 DOMException을 반환하는 읽기 전용 프로퍼티입니다.onstream: 미디어 트랙을 가져오는 즉시 실행되는 이벤트 핸들러입니다.onerror: 스트림을 가져오려는 시도가 실패하면 실행되는 이벤트 핸들러입니다.oncancel: 스트림을 가져오는 도중 사용자가 권한 프롬프트를 취소하거나 닫으면 실행되는 이벤트 핸들러입니다.요소를 투명하게 만들거나 다른 콘텐츠로 가려 사용자가 의도하지 않은 권한을 허용하게 만드는 일을 막기 위해서 <usermedia> 요소에는 다른 Capability Elements와 마찬가지로 엄격한 스타일 제약이 적용됩니다.
opacity)은 반드시 1로 설정해야 합니다.width, height, font-size에 최솟값과 최댓값을 적용합니다. 요소를 시각적으로 가릴 수 없도록 음수 마진과 음수 outline-offset도 비활성화합니다.transform에는 2D 이동과 비율을 유지하는 확대·축소만 사용할 수 있습니다.:granted 같은 상태 기반 스타일을 지원합니다. :hover, :active와 같은 일반적인 상호작용 상태도 사용할 수 있습니다.<usermedia> 요소는 <geolocation>에서 확립한 설계 패턴에 따라, 지원하지 않는 환경에서도 자연스럽게 기능이 축소되도록 만들어졌습니다. 이 요소를 지원하지 않는 브라우저는 <usermedia>를 HTMLUnknownElement로 취급하고 자식 요소를 렌더링합니다. 덕분에 모든 사용자를 위한 폴백 경험을 제공할 수 있습니다.
먼저 자바스크립트에서 <usermedia> 요소 지원 여부를 감지합니다.
if ("HTMLUserMediaElement" in window) {
// 최신 <usermedia> 요소 사용
} else {
// 기존 getUserMedia() API로 폴백
}
이 감지 로직과 함께 <usermedia> 요소 안에 일반 버튼을 추가하고, 지원하지 않는 환경에서는 기존 getUserMedia() API를 실행하도록 만들 수 있습니다.
<usermedia id="stream-handler">
<button id="fallback-stream-handler">카메라와 마이크 활성화</button>
</usermedia>
// 비디오·오디오 스트림을 처리하는 함수
function handleStream(event) {
/* ... */
}
if ("HTMLUserMediaElement" in window) {
// <usermedia> 요소를 지원하는 경우
const streamHandler = document.getElementById("stream-handler");
streamHandler.addEventListener("stream", (event) => {
handleStream(event);
});
} else {
// <usermedia> 요소를 지원하지 않으므로 기존 API 사용
const fallbackStreamHandler = document.getElementById(
"fallback-stream-handler",
);
fallbackStreamHandler.addEventListener("click", (event) => {
navigator.mediaDevices
.getUserMedia({ video: true, audio: true })
.then(handleStream);
});
}
앞서 시험 운영에 참여해 범용 <permission> 요소를 사용하고 있었다면, 몇 가지만 바꿔 <usermedia>로 전환할 수 있습니다.
<permission type="camera microphone">를 <usermedia>로 교체하세요. 기존 <permission> 요소를 대상으로 하던 모든 선택자도 <usermedia> 요소를 사용하도록 변경해야 합니다.HTMLPermissionElement를 확인하던 코드를 HTMLUserMediaElement로 변경하세요.<usermedia> 요소는 오디오와 비디오를 함께 요청하는 상황을 처리합니다. 향후 Capability Elements에는 다음과 같은 요소도 추가될 예정입니다.
<camera>: 비디오만 필요한 상황을 위한 요소<microphone>: 오디오만 필요한 상황을 위한 요소이처럼 기능별로 나뉜 요소를 활용하면 개발자는 더욱 직관적이고 신뢰할 수 있는 미디어 경험을 만들 수 있습니다. 자세한 내용은 Capability Elements 기술 가이드를 참고하세요.