Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
Compute Pressure API는 웹사이트가 대상 장치의 CPU 부하 변화에 반응하여, 웹사이트가 리소스를 조율함으로써 더 나은 사용자 경험을 제공할 수 있도록 합니다.
이 섹션은 문서가 발행된 시점에서의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정본은 W3C 표준 및 초안 색인에서 https://www.w3.org/TR/에서 확인할 수 있습니다.
이 명세가 CR 단계를 벗어나기 위해서는, 명세에서 정의한 모든 기능이 각각 최소 2개의 독립적인 구현으로 구현 보고서에 문서화되어야 합니다.
이 문서는 디바이스 및 센서 워킹 그룹에서 권고안 절차를 사용하여 후보 권고안 초안으로 발행한 것입니다.
후보 권고안으로 발행된다고 해서 W3C 및 회원의 승인을 의미하지는 않습니다. 후보 권고안 초안은 워킹 그룹이 다음 후보 권고안 스냅샷에 포함하려는 이전 후보 권고안의 변경사항을 통합합니다.
이 문서는 초안이며, 언제든지 갱신, 대체 또는 폐기될 수 있습니다. 진행 중인 작업 이외의 용도로는 인용에 적합하지 않습니다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 제작되었습니다. W3C는 해당 그룹 산출물과 관련하여 이루어진 공개 특허 공개 목록 을 관리합니다. 해당 페이지에는 특허 공개 방법에 관한 안내도 포함되어 있습니다. 특정 특허가 필수 청구항 을 포함한다고 실제로 알고 있는 개인은 W3C 특허 정책 6항에 따라 공개해야 합니다.
이 문서는 2023년 11월 3일자 W3C 프로세스 문서의 적용을 받습니다.
이 섹션은 비규범적입니다.
최신 애플리케이션은 즐겁고 현대적인 사용자 경험을 제공하기 위해 시스템의 컴퓨팅 자원을 최대한 활용하는 것의 장점과 단점을 균형 있게 고려해야 합니다.
예를 들어, 많은 애플리케이션들이 다양한 수준의 정교함으로 비디오 효과를 렌더링할 수 있습니다. 이러한 애플리케이션들은 최고의 사용자 경험을 제공하면서도 사용자의 디바이스가 높은 부하 상태에 들어가지 않도록 주의합니다.
처리 유닛의 활용도가 100%에 근접하거나 도달할 경우, 여러 작업이 처리 시간을 두고 경쟁하게 되어 사용성 저하가 발생할 수 있습니다. 이는 특히 입력 지연에서 두드러지는 느려짐으로 이어질 수 있습니다. 또한, 오랜 시간 동안 100%에 가까운 활용도가 지속되면 처리 유닛이 지속적인 부스트로 인해 과열되고, 이는 쓰로틀링을 야기해 더욱 좋지 않은 사용자 경험을 남길 수 있습니다.
열적 한계로 인해 많은 스마트폰, 태블릿, 노트북이 만졌을 때 불편할 정도로 뜨거워질 수 있습니다. 노트북과 데스크탑의 팬 소음은 대화나 사용자 집중을 방해할 정도로 커질 수 있습니다.
많은 경우, 높은 부하 속의 디바이스는 응답하지 않는 것처럼 보일 수 있는데, 운영체제가 사용자가 기다리는 작업을 진행시키는 스레드의 스케줄링에 실패할 수 있기 때문입니다. 더 자세한 내용은 사용 사례를 참고하세요.
이 섹션은 비규범적입니다.
기능 탐지는 확립된 웹 개발 모범 사례입니다. 관련 자료는 온오프라인에 풍부하게 존재하며, 이 절의 목적은 해당 주제를 자세히 다루는 것이 아니라, 하드웨어 의존 기능 탐지의 맥락에 두고 설명하는 데 있습니다.
아래의 기능 탐지 예시를 고려해보세요:
본 명세는 다음과 같은 개념을 정의합니다:
컴퓨팅 디바이스는 중앙 처리 장치(CPU), 그래픽 처리 장치(GPU) 및 다양한 특화된 처리 유닛과 같은 처리 유닛으로 구성됩니다. 후자의 경우 머신러닝이나 컴퓨터 비전 등 특정 작업을 가속화하도록 설계된 유닛이 점점 더 대중화되고 있습니다.
본 명세는 유효한 소스 타입을 중앙 처리 유닛, 즉 CPU로 정의하고 있습니다. 명세의 미래 레벨에서는 추가적인 소스 타입이 도입될 수 있습니다.
PressureSource 열거형은 유효한 소스
타입을 나타냅니다:
요청된 샘플링 간격은 하드웨어에서 샘플을 얻는 간격을 밀리초(ms) 단위로 지정합니다.
간격과 주파수는 서로 역수 관계이므로, 요청된 샘플링 간격은 1000을 해당 값으로 나누어 헤르츠(초당 회전수) 단위의 요청된 샘플링 주기로도 표현할 수 있습니다.
샘플링 주기는 플랫폼 콜렉터가 하위 플랫폼에서 텔레메트리 데이터를 얻는 주기를 정의하며, pressure observer의 요청된 샘플링 주기와 다를 수 있습니다. 속도는 헤르츠(Hz) 단위로 측정됩니다.
pressure observer의 보고 주기란 데이터 수집 단계를 수행하는 주기를 의미하며, 이 값은 샘플링 주기를 초과하지 않습니다.
샘플링 주기는 요청된 샘플링 주기와 다를 수 있으며, 요청된 샘플링 주기가 하위 플랫폼 및 User Agent가 지원하거나 허용하는 범위를 벗어날 경우에 해당됩니다†.
† 명세에서는 11.2.2 주기 난독화 조항에 따라 주기도 추가로 난독화합니다.
사용자가 샘플링 주기를 명시적으로 요청하지 않은 경우, 샘플링 주기는 구현 정의(implementation-defined)입니다.
프레셔 소스는 하드웨어 카운터 또는 기본 프레임워크에 대한 추상적이고 구현 정의
인터페이스로, 소스 타입에 대한 텔레메트리 데이터를 제공합니다.
PressureSource에서 정의합니다. 프레셔 소스는
더 정확한 결과를 제공할 수 있는 경우
다른 소스의 데이터와 데이터 퓨전을 활용할 수 있습니다.
프레셔 소스가 제공하는 텔레메트리 데이터는 본 명세에서 프레셔 소스 샘플로 나타내며, 다음 항목으로 구성된 구조체입니다:
PressureState
입니다.
프레셔 소스는 최신 샘플을 가집니다. 이는 프레셔 소스 샘플 또는 null이며, 기본값은 null입니다.
플랫폼 콜렉터는 프레셔 소스로부터 텔레메트리 샘플을 획득하고, 이를 프레셔 상태로 변환하여 user agent에 제공하는 추상 인터페이스입니다.
플랫폼 콜렉터는 다음과 같은 연관 데이터를 가집니다:
프레셔 소스가 제공하고 최신 샘플의 data에 저장된 텔레메트리 데이터의 형식은 구현 정의이며, 플랫폼 콜렉터가 이를 프레셔 상태로 변환하는 과정 역시 구현 정의입니다.
본 명세의 목적상, 플랫폼 콜렉터는 글로벌 객체에 플랫폼 콜렉터 매핑으로 범위가 지정됩니다.
자동화 목적상, 플랫폼 콜렉터는 가상 프레셔 소스에 연결되고, 해당 data를 원시 플랫폼 데이터가 아닌, 프레셔 상태로서 사용할 수 있어야 하며, 이것을 조정된 프레셔 상태로 변환할 필요가 없습니다.
텔레메트리 데이터 수집은 일반적으로 하드웨어 카운터를 폴링하는 작업이기 때문에, 무료로 이루어지는 작업이 아니므로 관찰하는 사람이 없는 경우에는 발생해서는 안 됩니다. 자세한 내용은 10.5 수명 주기 및 가비지 컬렉션을 참고하십시오.
플랫폼 콜렉터는 특정 주기로 데이터를 샘플링합니다. user agent는(가능한 경우) 개인정보 보호를 위해 이 주기를 조정하거나, 특정 측정값을 무시·합칠 수 있습니다.
user agent가 프레셔 옵저버가 활성 상태임을 사용자에게 보여주고, 사용자가 진행 중인 동작을 차단하거나 단순히 알림을 닫을 수 있는 수단을 제공하는 등 어떤 형태로든 사용자 가시적 알림을 표시하는 것이 권장됩니다(RECOMMENDED).
Compute Pressure API는 "compute-pressure" 토큰으로 식별되는 정책 제어 기능을 정의합니다.
기본 허용 목록(default
allowlist)은
'self'입니다.
워커(dedicated 및 shared 워커)는 자신을 소유한 문서의 권한 정책을 따릅니다.
공유 워커(shared worker)는 여러 소유 문서를 가질 수 있으며, 동일 출처(same origin)의 다른 문서에서도 획득될 수 있습니다. 이 경우, 모든 소유 문서는 본 명세에서 정의하는 사용 허용(allowed to use)을 받아야 하며, 정책 제어 기능이 허용되어야 합니다.
전용 워커(dedicated worker)는 다른 워커에서 생성될 수 있으며, 이 경우 최초 소유 문서(또는 공유 워커의 경우 소유 문서들)의 권한 정책이 소유 체인 상위까지 적용됩니다.
각 글로벌 객체는 다음을 가집니다:
PressureObserver 객체)로 구성됩니다.
user agent는 다음을 가집니다:
PressureSource 값입니다.
생성된 PressureObserver 객체는 다음 내부 슬롯을 가집니다:
PressureUpdateCallback 타입.
PressureSource 문자열,
프로미스는 Promise 객체입니다.
PressureRecord 객체의 큐(queue), 기본값은 빈큐.
PressureSource에서 최신 PressureRecord로의
정렬 맵.
PressureSource에서 양수로 매핑되는
정렬 맵. 소스 타입별 샘플 간격을 나타냄.
주기 난독화(rate obfuscation) 완화책을 위해
생성된 PressureObserver 객체는 다음 내부 슬롯도 가집니다:
PressureSource로 키가 되는 정렬 맵. 해당
소스 타입에 대한 현재 프레셔 상태로의 전환을 트리거한 경우
상태 변경 횟수를 나타냄.
정렬 맵의 값은 시간창 내 상태 변화 횟수의 정수값.
PressureSource로 키가 되는 정렬 맵. 최근
PressureRecord의 소스 타입을 나타냅니다.
정렬 맵 값은 PressureRecord입니다.
프레셔 상태는 웹사이트가 계산 및 시스템 부담 변화에 반응하여 품질·서비스 또는 사용자 경험 저하를 최소화할 수 있는 최소 유용 상태 집합을 나타냅니다.
WebIDLenum PressureState { "nominal", "fair", "serious", "critical" };
PressureState 열거형은 다음과 같은 프레셔 상태를 나타냅니다:
nominal": 대상 디바이스 조건이 허용 가능한 수준이며 사용자에게 눈에
띄는 부정적 영향이 없습니다.
fair": 대상 디바이스의 부하, 온도, 에너지 사용량이 약간 상승하여 배터리
수명 감소, 팬(또는 팬이 있는 시스템)의 활성화 및 소음 가능성이 있습니다. 그 외에는 디바이스가 원활하게 동작하며 추가 작업도 가능합니다.
serious": 대상 디바이스의 부하, 온도, 에너지 사용이 지속적으로
매우 높아집니다. 시스템은 열을 낮추기 위한 대책으로 쓰로틀링할 수 있습니다.
critical": 대상 디바이스 또는 시스템의 온도가 매우 높아져 문제
발생 방지를 위해 냉각이 필요합니다.
기여 요소란 현재 프레셔 상태에 기여하는 기저 하드웨어 및 운영체제 메트릭을 의미하며, 구현 정의일 수 있습니다.
조정된 프레셔 상태는 소스 타입 및 구현 정의 데이터 등을 입력 받아, 프레셔 상태를 결정하는 구현 정의 알고리즘이며, MUST 결정을 임의화(비결정적)해야 break calibration 완화책이 효과적입니다.
기여 요소 변화가 중대한 경우 단계는 아래와 같습니다:
PressureUpdateCallback 콜백WebIDLcallback PressureUpdateCallback = undefined (
sequence<PressureRecord> changes,
PressureObserver observer
);
이 콜백은 압력 상태가 변경될 때 호출됩니다.
PressureObserver 객체
PressureObserver는 압력 상태의 변화를 관찰하는 데 사용할 수 있습니다.
WebIDL[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureObserver {
constructor(PressureUpdateCallback callback);
Promise<undefined> observe(PressureSource source, optional PressureObserverOptions options = {});
undefined unobserve(PressureSource source);
undefined disconnect();
sequence<PressureRecord> takeRecords();
[SameObject] static readonly attribute FrozenArray<PressureSource> knownSources;
};
PressureObserver 인터페이스는 PressureObserver를 나타냅니다.
new PressureObserver(callback)
생성자의 단계는 다음과 같습니다:
[[Callback]]을 callback으로 설정합니다.
observe(source, options)
메서드의 단계는 다음과 같습니다:
NotAllowedError로
반환합니다.
[[SampleIntervalMap]][source]
를 options의 sampleInterval로
설정합니다.
[[PendingObservePromises]]에
추가합니다.
[[PendingObservePromises]]에서
제거합니다.
NotSupportedError로
거부한 뒤 이 단계를 중단합니다.
unobserve(source)
메서드의 단계는 다음과 같습니다:
NotSupportedError"를
던집니다.
[[QueuedRecords]]에서
records 중 source와 연관된 모든 항목을 제거합니다.
[[SampleIntervalMap]][source]를 제거합니다.
[[LastRecordMap]][source]를 제거합니다.
[[AfterPenaltyRecordMap]][source]를 제거합니다.
[[PendingObservePromises]]에서,
source가 promiseSource와 같다면 거부로 pendingPromise를 AbortError로 거부합니다.
disconnect() 메서드의
단계는 다음과 같습니다:
[[QueuedRecords]]를
비웁니다.
[[SampleIntervalMap]]을 비웁니다.
[[LastRecordMap]]을
비웁니다.
[[AfterPenaltyRecordMap]]을 비웁니다.
[[PendingObservePromises]]에서
거부로 pendingPromise를 AbortError로 거부합니다.
takeRecords()
메서드의 단계는 다음과 같습니다:
[[QueuedRecords]]의 복제로
설정합니다.
[[QueuedRecords]]를
비웁니다.
knownSources 게터의 단계는 다음과 같습니다:
WebIDL[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureRecord {
readonly attribute PressureSource source;
readonly attribute PressureState state;
readonly attribute DOMHighResTimeStamp time;
[Default] object toJSON();
};
생성된 PressureRecord 객체는
다음 내부 슬롯을 가집니다:
PressureSource 유형의 [[Source]] 값. 현재의
소스 유형을 나타냅니다.
PressureState 유형의 [[State]] 값. 현재 압력 상태를
나타냅니다.
DOMHighResTimeStamp 유형의 [[Time]] 값.
이는 시스템으로부터 데이터를 얻은 시점을 나타내며,
시간 원점을 기준으로 합니다. 해당 시간
원점은
알림을 생성한
PressureObserver
인스턴스와 연결된 전역 객체의 것입니다.
source 게터
단계는 그 [[Source]] 내부 슬롯을 반환하는 것입니다.
PressureRecord.toJSON이 호출되면, Web IDL
Standard의 기본 toJSON 단계를 실행합니다.
WebIDLdictionary PressureObserverOptions {
[EnforceRange] unsigned long sampleInterval = 0;
};
sampleInterval 멤버는
밀리초로 표현된 요청된 샘플링 간격을 나타냅니다. 값이 0으로
설정된 경우,
시스템은 PressureUpdateCallback을
PressureState에 변화가 있을 때만 호출합니다.
각 글로벌 객체는 그들의 등록된 관찰자에 강한 참조를 가집니다. 이는 등록된 관찰자 목록 (소스별로 하나씩) 안에 있습니다.
이 섹션은 사양을 구현할 때 사용자 에이전트가 수행해야 하는 단계를 설명합니다.
observer 인수를 받아 관찰 창 재설정 단계를 다음과 같이 수행합니다:
[[ObservationWindow]]를
구현 정의된 범위 내에서
밀리초 단위의 구현 정의된 랜덤 정수 값으로 설정합니다.
[[MaxChangesThreshold]]를
구현 정의된 범위 내에서
observationWindow 동안 허용되는 최대 변경 수에 대한 랜덤 정수 값으로 설정합니다.
[[PenaltyDuration]]을
구현 정의된 범위 내에서
밀리초 단위의 랜덤 정수 값으로 설정합니다.
[[ChangesCountMap]]
맵을 비웁니다.
[[ObservationWindow]]
시간이 경과하면 다른 랜덤 값으로 단계를 다시 실행하도록 합니다.
관련 글로벌 객체 relevantGlobal에 대한 소유 문서 집합을 결정하려면:
Window라면, 추가로 relevantGlobal의 연결된 문서를
owningDocumentSet에 추가합니다.
WorkerGlobalScope의
relevantGlobal의 소유자 집합 안에서:
Document라면, 추가로 owner를
owningDocumentSet에 추가합니다.
WorkerGlobalScope라면,
owningDocumentSet을 합집합으로 설정하며,
owningDocumentSet과 owner의 소유 문서 집합의 합집합입니다.
document 인수를 받아 문서에 암시적 포커스가 있음 단계를 다음과 같이 수행합니다:
observer 인수를 받아 데이터를 수신할 수 있음 단계를 다음과 같이 수행합니다:
Window 객체인 경우:
WorkerGlobalScope
객체인 경우:
[[LastRecordMap]][source]가 존재하지 않으면, true를 반환합니다.
[[LastRecordMap]][source]로 설정합니다.
[[SampleIntervalMap]][source]로 설정합니다.
[[Time]]로
설정합니다.
[[SampleIntervalMap]][source] > 0이면, true를 반환합니다.
[[LastRecordMap]][source]가 존재하지 않으면, true를 반환합니다.
[[LastRecordMap]][source]로 설정합니다.
[[State]]가
state와 같지 않다면, true를 반환합니다.
[[ChangesCountMap]][source]를 증가시킵니다.
[[ChangesCountMap]][source] ≤ observer의 [[MaxChangesThreshold]]를 반환합니다.
소스 유형 source와 relevantGlobal을 받아 가상 압력 소스를 가져오기를 다음과 같이 수행합니다. 이는 가상 압력 소스 또는 null을 반환합니다.
Window 객체라면:
DedicatedWorkerGlobalScope
객체라면:
소스 유형 source와 relevantGlobal을 받아 데이터 수집 활성화를 다음과 같이 수행합니다:
소스 유형 source와 relevantGlobal을 받아 데이터 수집 비활성화를 다음과 같이 수행합니다:
relevantGlobal, source, platformCollector를 받아 데이터 수집 단계를 다음과 같이 수행합니다:
PressureState로 설정합니다.
PressureRecord 객체로 설정하며,
그 [[Source]]는
source,
[[State]]는 state,
[[Time]]는
timeValue로 설정합니다.
[[AfterPenaltyRecordMap]][source]가
존재한다면:
[[AfterPenaltyRecordMap]][source]를
record로 설정합니다.
[[AfterPenaltyRecordMap]][source]를
record로 설정합니다.
[[ChangesCountMap]][source]를
0으로 설정합니다.
[[PenaltyDuration]] 기간의
타이머를 생성하고
다음 콜백을 설정합니다:
[[AfterPenaltyRecordMap]][source]가
존재한다면:
[[AfterPenaltyRecordMap]][source]로
설정합니다.
[[AfterPenaltyRecordMap]][source]를
제거합니다.
observer, source, record 인수를 받아 레코드 큐에 추가를 다음과 같이 실행합니다:
[[QueuedRecords]]의 크기가
최대 큐 대기 레코드 수보다 크다면, 제거로 첫 번째 항목을 제거합니다.
[[QueuedRecords]]에
추가합니다.
[[LastRecordMap]][source]를 record로
설정합니다.
PressureObserver 작업 소스는 작업을 예약하여 10.6.5 Pressure Observer에 알림을 수행하는 데 사용되는 작업 소스입니다.
relevantGlobal을 입력으로 받아 Pressure Observer 작업 큐에 추가를 다음과 같이 실행합니다:
relevantGlobal을 입력으로 받아 Pressure Observer에 알림을 다음과 같이 실행합니다:
[[QueuedRecords]]의 복제로 설정합니다.
[[QueuedRecords]]를 비웁니다.
[[Callback]]을 호출합니다.
인수는 « records, observer »이며
"report"로 호출합니다.
이 사양은 다음 문서 언로드 정리 단계를 정의합니다.
Document document에 대해:
WorkerGlobalScope
relevantGlobal의
종료 중 플래그가 true로 설정될 때마다,
다음 단계를 수행합니다:
동일 same origin이 아닌 사이트들에서, 출처를 공유하지 않는 사이트들이 동시에 고유하거나 매우 정밀한 값을 접근할 수 있다면 사용자를 식별할 가능성이 있습니다. 이 공격은 11.2.1 데이터 최소화, 11.2.2 속도 난독화, 그리고 11.2.7 동일 오리진 제한으로 완화됩니다.
컴퓨터 보안에서 은닉 채널(covert channel)은 원래 통신이 허용되지 않은 프로세스 간에 정보를 전송할 수 있는 능력을 만들어냅니다. 현대의 다중 프로세스 웹 엔진에서는 일반적으로 각 창이나 탭이 자체 프로세스에서 동작합니다 (문서가 same origin이거나 same site인 경우 보통 동일한 프로세스를 공유). 이 API를 사용하면 탭 A의 사이트가 CPU 상태를 조작한 뒤 채널 C로 먼저 브로드캐스트하고, 이어서 다른 탭의 사이트 B(사이트 A와 same site가 아님)가 이 API를 사용해 채널 C에서 브로드캐스트된 데이터를 읽어 CPU 상태 변경 시점을 알아내는 식으로, 크로스 사이트 은닉 채널 C를 만들 수 있습니다. 이 과정은 사이트 A와 B 모두에서 스크립트가 실행되는 한 반복될 수 있습니다.
이 공격은 11.2.2 속도 난독화와 11.2.5 보정 방해로 완화됩니다. 구현자들은 장시간 실행되는 스크립트에 대해 이러한 모든 완화를 고려하는 것이 권장됩니다.
표적 익명성 해제 공격은 사용자의 익명성을 위협하는 중대한 위협 범주에 해당합니다. 이러한 공격은 악의적이거나 일부가 손상된 웹사이트(“악성 사이트”)가 방문자가 이메일 주소나 소셜 미디어 핸들 같은 특정 공개 식별자를 보유하고 있는지를 파악할 수 있게 합니다.
익명성은 일부에게 사치일 수 있으나, 어떤 이들에게는 생존과 직결된 문제입니다. 예컨대 정치적 시위에 참여하거나 민감한 주제를 다루는 기자 등은 그 사례가 될 수 있습니다.
예를 들어, 공격자는 공개 리소스 공유 서비스(“피해자 사이트”)를 이용해 대상에게 비공개로 리소스를 공유하고, 사이드 채널을 통해 리소스를 로드할 때의 부수 효과(성공적인 접근을 나타냄)를 측정할 수 있습니다. 로그인된 방문자가 포함된 리소스에 성공적으로 접근할 수 있다면, 현재 방문이 실제로 의도된 대상임을 나타냅니다.
구체적으로, 전체 CPU 압력에 대한 신뢰할 수 있는 정보를 노출하면 교차 출처 탐색의 대상(예: 다른 사이트의 iframe 또는 팝업 창)이 CPU 집약적 작업을 수행했는지 공격 사이트가 파악할 수 있습니다.
pop-under 및 tab-under 같은 기법을 사용해 사용자로부터 로딩을 숨길 수 있습니다.
가능한 한 가지 공격은 악성 웹사이트가 사용자가 로그인한 피해자 사이트의 리소스(예: 동영상 스트리밍 사이트나 온라인 문서 편집기)를 가리키는 팝업을 열고, 특정 사용자들과 공유된 리소스를 대상으로 하는 것입니다.
리소스를 로드하면 CPU에 가해지는 압력이 증가한다고 가정할 때, 이는 사이드 채널을 형성하여 사용자가 해당 리소스에 접근 권한이 있는 계정으로 로그인했는지 공격 사이트에 드러내어 사용자의 익명성을 해제할 수 있습니다.
최신 CPU가 높은 압력 상태에서 빠르게 회복된다는 점을 고려하면, 가능한 완화 전략 중 하나로 팝업 및 iframe 콘텐츠 로드 직후 몇 초 동안 판독을 일시적으로 비활성화하는 방법이 있을 수 있습니다.
본 사양은 기본 플랫폼의 저수준 세부사항과 관련된 데이터 노출을 높은 가치의 사용 사례를 해결하는 데 필요한 최소한으로 제한하기 위해 일반적인 데이터 최소화 원칙을 따릅니다. 여기에는 디바이스 식별 정보의 노출 제한에 대한 고려도 포함됩니다.
본 사양의 맥락에서 데이터 최소화 원칙의 구체적 적용은 11.2.2 속도 난독화와 11.2.7 동일 오리진 제한에서 논의됩니다.
본 사양은 rate obfuscation 완화를 구현하도록 요구합니다. 이는 구현 정의의 슬라이딩 관찰 창 동안 압력 변화 횟수를 추적하고, 압력 변화 횟수가 구현 정의 임계를 초과하는 경우 플래그를 설정합니다. 마찬가지로, 여러 상태에 걸친 높은 압력 상태 변화 횟수와 같은 비정상 활동을 관찰하고 동일하게 플래그를 설정하는 것도 구현에 권장됩니다.
이 플래그가 설정되면, 구현은 압력 관찰자에 대해 페널티를 부여하여 평소처럼 스크립트에 압력 상태 변화를 알릴 수 없도록 하는 것이 권장됩니다. 페널티 기간은 구현 정의이며 무작위화하는 것이 권장됩니다. 페널티 이후 압력 관찰자에게 알림이 다시 동작을 재개할 때에는, 플랫폼 콜렉터로부터 페널티 동안 수신된 중간 상태 정보는 무시하고 최신 압력 상태만 보고합니다.
구현 경험에 근거하여, 구현자들은 다음을 사용해야 합니다:
[[MaxChangesThreshold]] 내부 슬롯은
50~100 변경 범위.
[[PenaltyDuration]]
내부 슬롯은 5000밀리초~10000밀리초 범위.
이 절은 비규범적입니다.
구현 경험에 근거하여, 구현자들은 다음을 사용하는 것이 권장됩니다:
[[ObservationWindow]] 내부 슬롯은
300000밀리초(5분)~600000밀리초(10분) 범위.
보정(calibration) 과정에서 공격자는 CPU를 조작하여 이 API가 조작된 워크로드가 가하는 압력에 반응해 특정 압력 상태로 전이했다고 보고할 확률을 최대화하려고 시도합니다. 이 break calibration 완화는 런타임에 이러한 압력 상태 전이에 기여하는 구현 정의 저수준 하드웨어 지표를 약간 변경함으로써 이 보정 과정을 지연시키거나 실패하게 만들 수 있습니다. 초기 보정이 성공하더라도, 이 완화가 지속적으로 동작하는 동안 런타임에서 그 결과는 무효화됩니다. 재보정 시도 역시 유사하게 완화됩니다.
이 절은 비규범적입니다.
구현 경험에 근거하여, 구현자들은 120000밀리초(2분)에서 240000밀리초(4분) 사이의 범위에서 무작위화된 시간 값으로 완화를 적용하는 것이 권장됩니다.
기본적으로 데이터 전달은 initiator of an active picture-in-picture-session과 동일 오리진에서 제공되는 문서, capturing 중인 문서, 또는(있다면) system focus를 가진 문서로 제한됩니다.
위 규칙에 따라 데이터 전달 자격을 갖춘 문서는 child navigables의 문서에 이를 위임할 수 있습니다.
이 기능은 오직 선언된 정책을 통해서만 iframe 등의 서드파티 컨텍스트로 확장될 수 있습니다.
공유 워커는 최상위 문서와 연관된 iframe 등 여러 문서 간에 공유될 수 있습니다. owner set에 속한 문서 중 하나라도 위 데이터 전달 요건을 통과한다면, 공유 워커는 데이터 전달 자격을 갖추게 됩니다. 이는 포함된 iframe이 데이터를 상위(임베딩) 문서로 전달할 수 있음을 의미합니다.
The Compute Pressure API는 사용자 경험 개선에 중점을 둡니다. 이 API를 기반으로 구축된 애플리케이션이 접근성에 긍정적인 영향을 미칠 수 있는 방법은 두 가지가 있습니다.
API 소비자로서 이 두 가지 기회를 모두 고려하는 것이 중요합니다. 다음은 몇 가지 예입니다:
The Compute Pressure API는 테스트 작성자에게 도전 과제를 제시합니다. 인터페이스를 완전히 실행하려면 예측 가능한 방식으로 반응하는 물리적 하드웨어 장치가 필요하기 때문입니다.
이 문제를 해결하기 위해 이 문서는 [WEBDRIVER2] extension commands를 정의하여 실제 장치처럼 동작하고 특정 속성을 가질 수 있으며 그 측정값을 전적으로 사용자가 정의할 수 있는 가상 압력 소스들을 정의하고 제어할 수 있게 합니다.
A 가상 압력 소스는 압력 소스로서 제어된 방식으로 실제 장치의 동작을 시뮬레이션합니다. 이 소스는 연결된 0개 이상의 플랫폼 수집기들에게 압력 변화를 보고합니다.
그러나 실제 압력 소스와 달리, 가상 압력 소스는 플랫폼 수집기가 압력 상태로 처리해야 하는 implementation-defined 값 대신에 압력 상태 값을 직접 보고합니다. 다시 말해, 가상 압력 소스의 압력 소스 샘플의 데이터는 PressureState입니다.
모든 압력 소스와 관련된 데이터(예: 압력 소스 샘플) 외에도, 각 가상 압력 소스는 다음을 가집니다:
각 최상위 트래버서블은 가상 압력 소스 매핑을 가지며, 이는 정렬된 맵으로 소스 타입들을 가상 압력 소스에 매핑합니다.
| HTTP Method | URI Template |
|---|---|
| POST | /session/{session id}/pressuresource |
이 extension command는 지정된
가상 압력 소스를 생성합니다. 동일한
소스 타입의 observe() 호출은
이 가상 압력 소스가 그들의 백업
압력 소스로 사용되게 하며, 이는 13.1.1.2
Delete virtual pressure source가 실행될 때까지 지속됩니다.
| Parameter name | Value type | Required |
|---|---|---|
| type | String | yes |
| supported | Boolean | no |
주어진 session, URL variables 및 parameters에 대한 원격 엔드 단계는 다음과 같습니다:
| HTTP Method | URI Template |
|---|---|
| DELETE | /session/{session id}/pressuresource/{type} |
이 extension command는 주어진 가상 압력 소스를 삭제합니다. 이는 해당 소스 타입에 대한 데이터가 가능하다면 비가상 방식으로(기존 방식으로) 전달된다는 것을 의미합니다.
주어진 session, URL variables 및 parameters에 대한 원격 엔드 단계는 다음과 같습니다:
| HTTP Method | URI Template |
|---|---|
| POST | /session/{session id}/pressuresource/{type} |
이 extension command는 새로운 압력 소스 샘플을 푸시하여 가상 압력 소스의 상태를 업데이트할 수 있게 합니다.
| Parameter name | Value type | Required |
|---|---|---|
| sample |
PressureState
|
yes |
주어진 session, URL variables 및 parameters에 대한 원격 엔드 단계는 다음과 같습니다:
PressureState 타입이 아니면, error를 WebDriver error code invalid argument와 함께 반환합니다.
이 섹션은 비규범적입니다.
const samples = [];
function pressureChange(records, observer) {
for (const record of records) {
samples.push(record.state);
// We only want 20 samples.
if (samples.length == 20) {
observer.disconnect();
return;
}
}
}
const observer = new PressureObserver(pressureChange);
observer.observe("cpu");
다음 예제에서는 압력이 critical 상태가 되면 동시 비디오 스트림 수를 줄이려고 합니다. 단순성을 위해 이 하나의 상태만 고려합니다.
스트림 수를 줄인다고 해서 반드시 critical 상태에서 벗어나거나 즉시 벗어나는 것은 아닐 수 있으므로, critical 상태에 있는 동안에는 30초마다 한 번씩씩 스트림을 하나씩 줄이는 전략을 사용합니다.
이를 위해 콜백이 실제로 상태가 변경될 때 또는 적어도 30초에 한 번 이상 호출되도록 보장합니다. 상태가 변경되면 인터벌 타이머를 재설정합니다.
let timerId = -1;
function pressureChange(records) {
// Clear timer every time we are called, either by an actual state change,
// or when called by setTimeout (see below).
if (timerId > 0) {
clearTimeout(timerId);
}
// When entering critical state, we want to recheck every 30sec if we are
// still in critical state and if so, further reduce our concurrent streams.
// For this reason we create a timer for 30 seconds that will call us back
// with the last result in there were no change.
const lastRecordArray = [records.at(records.length - 1)];
timerId = setTimeout(pressureChange.bind(this, lastRecordArray), 30_000);
for (const record of records) {
if (record.state == "critical") {
let streamsCount = getStreamsCount();
setStreamsCount(streamsCount--);
}
}
}
const observer = new PressureObserver(pressureChange);
observer.observe("cpu");
다음 예제에서는 takeRecords()
의 사용법을 보여주고자 하며, 콜백이 마지막으로 호출된 이후 누적된 남은 records를 가져옵니다.
이것은 disconnect()를 호출하기 전에 하는 것이
권장됩니다. 그렇지 않으면 disconnect()가 이들 레코드를 지우고
영구히 손실됩니다.
예를 들어, 벤치마크 워크로드 동안 압력을 측정하고자 하여 워크로드의 정확한 기간 동안의 압력 텔레메트리를 원할 수 있습니다. 이는 작업이 완료되면 즉시 모든 옵저버를 disconnect하고, 이벤트 루프 사이클의 일부로 아직 전달되지 않았을 수 있는 보류 중인 압력 텔레메트리를 수동으로 요청하는 것을 의미합니다.
function logWorkloadStatistics(records) {
// do something with records.
}
const observer = new PressureObserver(logWorkloadStatistics);
observer.observe("cpu");
// Read pending state change records, otherwise they will be cleared
// when we disconnect.
const records = observer.takeRecords();
logWorkloadStatistics(records);
observer.disconnect();
다음 예제에서는 source를 인수로 하여 unobserve()를 호출함으로써 옵저버에게 특정
소스의 관찰을 중지하도록 지시하는 방법을 보여줍니다.
const observer = new PressureObserver(records => { /* do something with records. */ });
observer.observe("cpu");
observer.observe("gpu");
// Callback now gets called whenever the pressure state changes for 'cpu' or 'gpu'.
observer.unobserve("gpu");
// Callback now only gets called whenever the pressure state changes for 'cpu'.
다음 예제에서는 disconnect()를 호출하여 옵저버가 모든
상태 변화를 더 이상 관찰하지 않도록 하는 방법을 보여줍니다. disconnect()를 호출하면 이전의 모든
observe() 호출로 관찰하던 모든 소스에 대한
관찰이 중지됩니다.
또한 마지막 콜백이 호출된 이후 수집된 모든 보류 중인 레코드를 지웁니다.
const observer = new PressureObserver(records => { // do something with records. });
observer.observe("cpu");
observer.observe("gpu");
// some time later...
observer.disconnect();
// records will be an empty array, because of the previous disconnect().
const records = observer.takeRecords();
비규범적(Non-normative)으로 표시된 섹션들뿐만 아니라, 이 사양의 모든 작성 가이드라인, 다이어그램, 예제 및 주석은 비규범적입니다. 이 사양의 나머지 모든 부분은 규범적(normative)입니다.
문서에서 핵심 단어인 MAY, MUST, 및 RECOMMENDED는 모두 대문자로 나타나는 경우에 한해 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석됩니다.
이 사양은 하나의 제품에 대한 적합성 기준을 정의합니다: 이 사양에 포함된 인터페이스들을 구현하는 사용자 에이전트.
이 섹션은 비규범적입니다.
다음 분들의 소중한 피드백과 조언에 깊이 감사드립니다: Anssi Kostiainen, Asaf Yaffe, Benjamin VanderSloot, Chen Xing, Evan Shrubsole, Florian Scholz, François Beaufort, Jan Gora, Jesse Barnes, Joshua Bell, Kamila Hasanbega, Matt Menke, Moh Haghighat, Nicolás Peña Moreno, Opal Voravootivat, Paul Jensen, Peter Djeu, Reilly Grant, Ulan Degenbaev, Victor Miura, Wei Wang, 그리고 Zhenyao Mo
개인 정보 검토, 피드백 및 제안된 교차 사이트 은밀 채널 공격과 그 완화책에 대해 W3C Privacy Interest Group (PING)과 특히 Peter Snyder에게 감사드립니다. 유사하게, 개인 브라우징의 프라이버시 및 이 사양에 대한 관련 기여에 대해 Ehsan Toreini에게도 감사드립니다.
Zoom 엔지니어링 팀의 Amanda Zhao, Fidel Tian, Zhiliang Wang 및 다른 분들께도 실무적 실험과 피드백으로 이 API가 실제 시나리오에서 개선되는 데 도움을 주신 점 특별히 감사드립니다.
이 섹션은 비규범적입니다.
[[AfterPenaltyRecordMap]] (PressureObserver의 내부 슬롯)
§7.
[[Callback]] (PressureObserver의 내부 슬롯)
§7.
[[ChangesCountMap]] (PressureObserver의 내부 슬롯)
§7.
constructor()
(PressureObserver용)
§10.2.1
"cpu" (PressureSource의 열거 값)
§3.2
"critical" (PressureState의 열거 값)
§8.
disconnect()
(PressureObserver용 메서드)
§10.2.4
"fair" (PressureState의 열거 값)
§8.
knownSources
(PressureObserver 속성)
§10.2.6
[[LastRecordMap]] (PressureObserver의 내부 슬롯)
§7.
[[MaxChangesThreshold]]
(PressureObserver의 내부 슬롯)
§7.
"nominal" (PressureState의 열거 값)
§8.
[[ObservationWindow]]
(PressureObserver의 내부 슬롯)
§7.
observe() (PressureObserver 메서드)
§10.2.2
[[PenaltyDuration]] (PressureObserver의 내부 슬롯)
§7.
[[PendingObservePromises]] (PressureObserver의 내부 슬롯)
§7.
PressureObserver 인터페이스
§10.2
PressureObserverOptions 딕셔너리
§10.4
PressureRecord 인터페이스
§10.3
PressureSource 열거형
§3.2
PressureState 열거형
§8.
PressureUpdateCallback
§10.1
[[QueuedRecords]] (PressureObserver의 내부 슬롯)
§7.
sampleInterval 멤버
(PressureObserverOptions용)
§10.4.1
[[SampleIntervalMap]]
(PressureObserver의 내부 슬롯)
§7.
"serious" (PressureState의 열거 값)
§8.
source (PressureRecord의 속성)
§10.3.1
[[Source]] (PressureRecord의 내부 슬롯)
§10.3
state (PressureRecord의 속성)
§10.3.2
[[State]] (PressureRecord의 내부 슬롯)
§10.3
takeRecords()
(PressureObserver 메서드)
§10.2.5
time (PressureRecord의 속성)
§10.3.3
[[Time]] (PressureRecord의 내부 슬롯)
§10.3
toJSON (PressureRecord의 메서드)
§10.3.4
unobserve() (PressureObserver의 메서드)
§10.2.3
Document 인터페이스
Node 용)
ECMAScript 용)
globalThis 속성 ( globalThis
용)
DOMHighResTimeStamp
WorkerGlobalScope 용)
DedicatedWorkerGlobalScope 인터페이스
Document 용)
iframe 요소
WorkerGlobalScope 용)
WorkerGlobalScope
용)
Document 용)
Window 인터페이스
WorkerGlobalScope 인터페이스
AbortError 예외
[Default] 확장 속성
[EnforceRange] 확장 속성
[Exposed] 확장 속성
FrozenArray 인터페이스
NotAllowedError 예외
NotSupportedError 예외
object
타입
Promise 인터페이스
promise 용)
[SameObject] 확장 속성
[SecureContext] 확장 속성
TypeError 예외
undefined 타입
unsigned long 타입
WebIDLenum PressureSource { "cpu" };
enum PressureState { "nominal", "fair", "serious", "critical" };
callback PressureUpdateCallback = undefined (
sequence<PressureRecord> changes,
PressureObserver observer
);
[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureObserver {
constructor(PressureUpdateCallback callback);
Promise<undefined> observe(PressureSource source, optional PressureObserverOptions options = {});
undefined unobserve(PressureSource source);
undefined disconnect();
sequence<PressureRecord> takeRecords();
[SameObject] static readonly attribute FrozenArray<PressureSource> knownSources;
};
[Exposed=(DedicatedWorker,SharedWorker,Window), SecureContext]
interface PressureRecord {
readonly attribute PressureSource source;
readonly attribute PressureState state;
readonly attribute DOMHighResTimeStamp time;
[Default] object toJSON();
};
dictionary PressureObserverOptions {
[EnforceRange] unsigned long sampleInterval = 0;
};
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: