WebXR 앵커 모듈

편집자 초안,

이 문서에 대한 자세한 정보
이 버전:
https://immersive-web.github.io/anchors/
이슈 추적:
GitHub
사양 내 인라인
편집자:
(Google)
이전 편집자:
(Google)
참여:
이슈 제출 (열려 있는 이슈)
메일링 리스트 아카이브
W3C의 #immersive-web IRC

초록

하위 시스템이 추적하는 앵커를 생성하는 방법을 설명한다.

이 문서의 상태

이 절은 이 문서가 공개된 시점의 상태를 설명한다. 현재 W3C 공개 문서 목록과 이 기술 보고서의 최신 개정판은 http://www.w3.org/TR/의 W3C 기술 보고서 색인에서 확인할 수 있다.

이 문서는 Immersive Web Working Group에서 편집자 초안으로 공개했다. 이 문서는 W3C 권고안이 되는 것을 목표로 한다. 이 사양에 대한 피드백과 의견을 환영한다. Github 이슈를 사용하기 바란다. 논의는 public-immersive-web-wg@w3.org 아카이브에서도 확인할 수 있다.

편집자 초안으로 공개되었다고 해서 W3C와 그 회원이 이를 승인한다는 의미는 아니다. 이는 초안 문서이며 언제든지 다른 문서로 갱신, 대체 또는 폐기될 수 있다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 부적절하다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했다. W3C는 해당 그룹의 산출물과 관련하여 이루어진 특허 공개의 공개 목록을 관리하며, 이 페이지에는 특허 공개를 위한 지침도 포함되어 있다. 자신이 실제로 알고 있는 특허가 필수 청구항을 포함한다고 믿는 개인은 W3C 특허 정책 제6절에 따라 그 정보를 공개해야 한다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받는다.

1. 소개

WebXR 앵커 모듈은 하위 XR 시스템이 세계에 대한 이해를 변경함에 따라 특정 3차원 포즈(위치와 방향)의 변경을 추적하도록 애플리케이션이 요청할 수 있게 한다. 이를 통해 애플리케이션은 장면에 배치한 가상 객체의 위치를 조정할 수 있으며, 배치된 객체가 사용자의 환경에 실제로 존재한다는 착시를 유지하는 데 도움이 된다.

1.1. 용어

이 문서에서 이해하는 포즈는 3D 공간에서의 위치와 방향을 의미한다.

이 문서에서 이해하는 앵커는 현실 세계에 대해 고정된 포즈를 추적하는 엔티티이며, 애플리케이션이 생성한다.

2. 초기화

2.1. 기능 기술자

애플리케이션이 세션 중 앵커 사용에 대한 관심을 표시하려면, 적절한 기능 기술자와 함께 세션을 요청해야 한다. 문자열 anchors는 이 모듈에서 앵커 기능을 위한 새로운 유효한 기능 기술자로 도입된다.

기기의 추적 시스템이 네이티브 앵커 기능을 노출하는 경우, 그 기기는 앵커 기능을 지원 가능하다. 인라인 XR 기기는 앵커 기능을 지원 가능한 것으로 취급해서는 안 된다. 사용자 에이전트는 모드"immersive-ar"와 같은 세션에 대해 앵커 기능 지원을 시도해야 한다.

참고: 앵커 기능 지원이 필수는 아니지만, 앵커는 AR 지원 애플리케이션이 좋은 사용자 경험을 제공하는 데 필요한 기본 기능 중 하나다. 따라서 사용자 에이전트가 "immersive-ar" 세션에 대해 이를 지원하는 것을 *강력히* 권장한다.

3. 앵커

3.1. XRAnchor

[SecureContext, Exposed=Window]
interface XRAnchor {
  readonly attribute XRSpace anchorSpace;

  Promise<DOMString> requestPersistentHandle();

  undefined delete();
};

XRAnchor는 다른 XRSpaces에 대해 앵커를 위치 지정하는 데 사용할 수 있는 anchorSpace를 포함한다. deletedtrue로 설정되어 있을 때 이 속성에 접근하면, 사용자 에이전트는 InvalidStateError를 던져야 한다.

XRAnchor에는 처음에 false로 설정되는 연관된 deleted 불리언 값이 있다.

XRAnchor에는 연관된 native origin이 있다.

XRAnchor에는 연관된 session이 있다.

native originsession으로부터 새 앵커 객체를 생성하기 위해, 사용자 에이전트는 다음 단계를 실행해야 한다:
  1. anchor를 새로운 XRAnchor로 둔다.

  2. anchornative originnative origin으로 설정한다.

  3. anchorsessionsession으로 설정한다.

  4. anchordeletedfalse로 설정한다.

  5. anchoranchorSpace를, sessionanchorsession으로 설정하고 native originnative origin으로 설정하여 생성한 새로운 XRSpace 객체로 설정한다.

  6. anchor를 반환한다.

requestPersistentHandle() 메서드가 XRAnchor anchor에서 호출되면, 다음 단계를 실행해야 한다:
  1. promise를 이 XRSystem관련 렐름에 있는 새로운 Promise로 둔다.

  2. anchordeletedtrue이면, promiseInvalidStateError거부하고, promise를 반환한 뒤, 이 단계를 중단한다.

  3. sessionanchorsession으로 둔다.

  4. sessionmap of persistent anchorsanchor 값을 포함하면, 다음 단계를 실행한다:

    1. uuidsessionmap of persistent anchors에서 anchor 값에 대한 매핑의 키로 둔다.

    2. promiseuuid해결한다.

    3. promise를 반환한다.

    4. 이 단계를 중단한다.

  5. uuid를 빈 문자열로 둔다.

  6. UUID [RFC9562]를 문자열로 생성하고 이를 uuid에 추가한다.

  7. uuidanchorsessionmap of persistent anchors에 추가한다.

  8. promiseuuid해결한다.

  9. promise를 반환한다.

참고: XRSystem이 고유 ID를 생성할 때, 그 ID는 고유해야 하며 현재 출처에만 알려져야 한다.

4. 앵커 생성

XRSession은 연관된 set of tracked anchors를 포함하도록 확장된다.

XRSession은 UUID 문자열을 키로 하고 XRAnchor에 매핑되는 연관된 map of persistent anchors를 포함하도록 확장된다. 이 맵은 XR device가 채우고 저장하며, origin에서 임의의 XRSession에 의해 생성되었고 아직 파괴되지 않은 영속 앵커의 집합으로만 제한된다. 이 맵의 크기는 사용자 에이전트가 결정한다. 사용자 에이전트는 어떤 이유로든 이 맵에서 항목을 삭제할 수 있다. 예를 들어 모든 출처의 모든 맵에 대한 시스템 앵커의 최대 수에 도달한 경우, 사용자 에이전트는 새로 요청된 앵커를 위한 공간을 만들기 위해 항목 하나를 해제할 수 있다.

XRSessionXRAnchor 객체를 키로 하고 Promise<XRAnchor> 객체에 매핑되는 연관된 map of new anchors를 포함하도록 확장된다.

partial interface XRFrame {
  Promise<XRAnchor> createAnchor(XRRigidTransform pose, XRSpace space);
};

partial interface XRSession {
  readonly attribute FrozenArray<DOMString> persistentAnchors;

  Promise<XRAnchor> restorePersistentAnchor(DOMString uuid);
  Promise<undefined> deletePersistentAnchor(DOMString uuid);
};

partial interface XRHitTestResult {
  Promise<XRAnchor> createAnchor();
};

XRHitTestResult는 연관된 native entity를 포함하도록 확장된다. 하위 시스템이 결과 계산을 일으킨 네이티브 엔티티에 대한 정보를 제공하지 않으면, native entitynull로 설정된 것으로 가정한다.

애플리케이션은 다음 두 가지 방법 중 하나로 앵커를 생성할 수 있다:

프레임에서 앵커를 생성하기 위해, 애플리케이션은 XRFramecreateAnchor(pose, space) 메서드를 호출할 수 있다.

createAnchor(pose, space) 메서드가 XRFrame frame에서 posespace와 함께 호출되면, 다음 단계를 실행해야 한다:
  1. promise새로운 Promise로 둔다.

  2. frameactive 불리언이 false이면, promiseInvalidStateError거부하고, promise를 반환한 뒤, 이 단계를 중단한다.

  3. sessionframesession으로 둔다.

  4. update anchors 알고리즘이 아직 없으면 sessionlist of frame updates에 추가한다.

  5. devicesessionXR device로 둔다.

  6. effective originspaceeffective origin으로 둔다.

  7. anchor native origin을, frametimeeffective origin에 대해 표현된 것으로 해석한 pose를 사용하여 새 앵커를 생성하는 device 호출에서 반환된 새로운 네이티브 원점으로 둔다.

  8. anchor native originsession을 사용하여 새 앵커 객체 생성 anchor를 수행한다.

  9. anchorsessionset of tracked anchors에 추가한다.

  10. anchor에서 promise로의 매핑을 sessionmap of new anchors에 추가한다.

  11. promise를 반환한다.

참고:createAnchor(pose, space) 호출이 반환하는 앵커가 추적하는 물리적 원점이, 해당 메서드가 호출된 프레임이 나타내는 시점의 spacepose의 물리적 위치와 최대한 가깝게 정렬되도록 보장하는 것은 사용자 에이전트의 책임이다. 구체적으로 이는 동적으로 변경되는 공간에 대해 사용자 에이전트가 앱이 지정한 시점에서 그러한 공간의 네이티브 원점을 캡처하려고 시도해야 함을 의미한다. 이 텍스트는 비규범적이지만, 사양 작성자와 기여자의 의도를 표현하므로 서로 다른 공급자 간의 일관된 동작을 보장하기 위해 구현에서 이를 따르는 것을 강력히 권장한다.

persistentAnchors는 알려진 영속 앵커의 목록을 반환한다. 이 목록은 map of persistent anchors의 키를 반영해야 한다.
restorePersistentAnchor(uuid) 메서드가 XRSession session에서 uuid와 함께 호출되면, 다음 단계를 실행해야 한다:
  1. promise를 이 XRSystem관련 렐름에 있는 새로운 Promise로 둔다.

  2. sessionmap of persistent anchorsuuid에서 XRAnchor로의 매핑이 없으면, promiseInvalidStateError거부하고, promise를 반환한 뒤, 이 단계를 중단한다.

  3. sessionended 값이 `true`이면, promiseInvalidStateError거부하고, promise를 반환한 뒤, 이 단계를 중단한다.

  4. anchorsessionmap of persistent anchors에서 uuid에 대한 매핑의 값으로 둔다.

  5. sessionmap of new anchorsanchor에서 promise로의 매핑을 포함하면, 그 promiseInvalidStateError거부하고, promise를 반환한 뒤, 이 단계를 중단한다.

  6. sessionmap of new anchors가 사용자 에이전트 최대 크기에 도달했으면, promiseInvalidStateError거부하고, promise를 반환한 뒤, 이 단계를 중단한다.

  7. anchorsessionset of tracked anchors에 추가한다.

  8. anchor에서 promise로의 매핑을 sessionmap of new anchors에 추가한다.

  9. promise를 반환한다.

deletePersistentAnchor() 메서드가 XRSession session에서 uuid와 함께 호출되면, 다음 단계를 실행해야 한다:
  1. promise를 이 XRSystem관련 렐름에 있는 새로운 Promise로 둔다.

  2. sessionmap of persistent anchorsanchor로의 매핑이 없으면, promiseInvalidStateError거부하고, promise를 반환한 뒤, 이 단계를 중단한다.

  3. anchorsessionmap of persistent anchors에서 uuid에 대한 매핑의 값으로 둔다.

  4. sessionmap of persistent anchors에서 매핑을 제거한다.

  5. anchor에서 delete()를 호출한다.

  6. promise를 반환한다.

히트 테스트 결과에서 앵커를 생성하기 위해, 애플리케이션은 XRHitTestResultcreateAnchor() 메서드를 호출할 수 있다.

createAnchor() 메서드가 XRHitTestResult hitTestResult에서 호출되면, 다음 단계를 실행해야 한다:
  1. promise새로운 Promise로 둔다.

  2. framehitTestResultframe으로 둔다.

  3. frameactive 불리언이 false이면, promiseInvalidStateError거부하고, promise를 반환한 뒤, 이 단계를 중단한다.

  4. sessionframesession으로 둔다.

  5. update anchors 알고리즘이 아직 없으면 sessionlist of frame updates에 추가한다.

  6. devicesessionXR device로 둔다.

  7. nativeEntityhitTestResultnative entity로 둔다.

  8. anchor native origin을, frametimehitTestResultnative origin에 위치하고 nativeEntityattached된 새 앵커를 생성하는 device 호출에서 반환된 새로운 네이티브 원점으로 둔다.

  9. anchor native originsession을 사용하여 새 앵커 객체 생성 anchor를 수행한다.

  10. anchorsessionset of tracked anchors에 추가한다.

  11. anchor에서 promise로의 매핑을 sessionmap of new anchors에 추가한다.

  12. promise를 반환한다.

참고: createAnchor(pose, space) 메서드에 있는 동일한 설명이 여기에도 적용된다.

세션의 "list of frame updates"에는 순서를 지정하는 방법이 필요할 수 있다. 일부 알고리즘은 다른 알고리즘에 의존할 수 있다.

5. 앵커 업데이트

[Exposed=Window]
interface XRAnchorSet {
  readonly setlike<XRAnchor>;
};

partial interface XRFrame {
  [SameObject] readonly attribute XRAnchorSet trackedAnchors;
};

XRAnchorSet 인터페이스는 앵커 컬렉션을 노출하는 방법으로 도입된다.

XRFrame은 프레임에서 아직 추적 중인 모든 앵커를 포함하는 trackedAnchors 속성을 포함하도록 확장된다. XRFrame 생성 시, 이 집합은 처음에는 비어 있으며 update anchors 알고리즘에 의해 채워진다.

frame에 대해 앵커를 업데이트하기 위해, 사용자 에이전트는 다음 단계를 실행해야 한다:
  1. sessionframesession으로 둔다.

  2. devicesessionXR device로 둔다.

  3. sessionset of tracked anchors에 있는 각 anchor에 대해 다음을 실행한다:

    1. anchornative origin 정보에 대해 device의 추적 시스템에 질의한다.

    2. device의 추적 시스템이 더 이상 anchortracks하지 않으면, 다음 단계를 실행한다:

      1. anchorsessionset of tracked anchors에서 제거한다.

      2. sessionmap of new anchorsanchor에서 promise로의 매핑을 포함하면, promise거부하고 매핑을 제거한다.

      3. sessionset of tracked anchors에 있는 다음 항목으로 계속한다.

    3. anchorframetrackedAnchors 집합에 추가한다.

    4. sessionmap of new anchorsanchor에서 promise로의 매핑을 포함하면, promiseanchor해결하고 매핑을 제거한다.

6. 앵커 제거

애플리케이션이 더 이상 앵커 업데이트 수신에 관심이 없으면, delete()를 호출하여 앵커를 삭제할 수 있다.

delete() 메서드가 XRAnchor anchor에서 호출되면, 다음 단계를 실행하여 앵커를 삭제해야 한다:
  1. anchordeletedtrue이면, 이 단계를 중단한다.

  2. anchoranchorSpacenull로 설정한다.

  3. anchordeletedtrue로 설정한다.

  4. sessionanchorsession으로 둔다.

  5. devicesessionXR device로 둔다.

  6. native originanchornative origin으로 둔다.

  7. device의 추적 시스템에 native origin을 더 이상 추적하지 않도록 알린다.

  8. anchorsessionset of tracked anchors에서 제거한다.

7. 네이티브 기기 개념

사용자 에이전트가 앵커 API를 구현할 수 있으려면, 하위 XR 기기가 이 기능에 대한 네이티브 지원을 제공해야 한다. 이 절은 하위 XR 시스템에 부과되는 요구사항을 설명하며, 다양한 프레임워크/기기 위에서 앵커 API를 구현할 수 있도록 필연적으로 덜 명세되어 있다.

7.1. 네이티브 앵커

하위 XR device는 앵커와 관련된 다음 기능을 지원하는 경우 지원 가능anchors 기능이다:

하위 기기가 네이티브 앵커를 지원하지 않는 경우, 사용자 에이전트는 에뮬레이트된 네이티브 앵커를 통해 앵커 API를 구현하기로 결정할 수 있다. 이 접근 방식은 앵커가 일단 생성되면 포즈가 절대 변경되지 않으며, 그 포즈가 XRFramecreateAnchor(pose, space) 또는 XRHitTestResultcreateAnchor()와 같은 앵커 생성 메서드에 애플리케이션이 전달한 포즈라고 가정한다.

참고: 에뮬레이트된 네이티브 앵커 접근 방식은 애플리케이션이 앵커 기능을 직접 에뮬레이트하는 것과 동등하며, 애플리케이션이 처리해야 하는 서로 다른 경우의 수를 줄이는 데 도움이 될 수 있다. 또한 애플리케이션이 "immersive-ar""immersive-vr" 세션에 대해 같은 코드를 재사용할 수 있게 할 수도 있다.

8. 개인정보 보호 및 보안 고려사항

앵커 API는 사용자 환경에 대한 정보 접근을 직접 노출하지 않는다. 세션이 hit-test 지원이 활성화된 상태로 생성되었고 기기가 움직이는 객체 추적을 지원하는 경우, 애플리케이션은 예를 들어 주변으로 운반되는 객체의 앵커 포즈 변화를 관찰하여 사용자 환경의 레이아웃을 추론할 수 있을 수 있다. 이는 hit-testing API와 유사한 수준의 사용자 환경 정보를 제공한다. 앵커 기능은 XR 세션 생성 시 선언되어야 하며, 이를 통해 사용자 에이전트는 웹사이트가 앵커 API 사용을 허용하는 것의 잠재적 개인정보 보호 영향을 사용자에게 알릴 수 있다.

움직이는 일반 객체 추적을 지원하는 기기를 나는 알지 못한다. 이런 기기를 사양에서 전혀 고려해야 하는가? 그런 기기의 예가 있는가?

9. 감사의 말

다음 개인들이 WebXR Anchors 사양의 설계에 기여했다:

준수

문서 관례

준수 요구사항은 설명적 단언과 RFC 2119 용어의 조합으로 표현된다. 이 문서의 규범 부분에서 쓰이는 핵심어 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, 그리고 “OPTIONAL”은 RFC 2119에 설명된 대로 해석해야 한다. 그러나 가독성을 위해, 이 사양에서는 이러한 단어들이 모두 대문자로 표시되지는 않는다.

명시적으로 비규범으로 표시된 절, 예제, 참고를 제외한 이 사양의 모든 텍스트는 규범적이다. [RFC2119]

이 사양의 예제는 “예를 들어”라는 말로 도입되거나 class="example"으로 규범 텍스트와 구분되어 표시된다. 다음과 같다:

이는 정보 제공용 예제의 예다.

정보 제공용 참고는 “참고”라는 말로 시작하며 class="note"로 규범 텍스트와 구분되어 표시된다. 다음과 같다:

참고, 이는 정보 제공용 참고다.

준수 알고리즘

알고리즘의 일부로 명령형으로 표현된 요구사항 (예: "선행 공백 문자를 제거한다" 또는 "false를 반환하고 이 단계를 중단한다")은 알고리즘을 도입할 때 사용된 핵심어 ("must", "should", "may" 등)의 의미로 해석해야 한다.

알고리즘 또는 특정 단계로 표현된 준수 요구사항은 최종 결과가 동등하다면 어떤 방식으로든 구현할 수 있다. 특히, 이 사양에서 정의하는 알고리즘은 이해하기 쉽게 만드는 것을 의도하며 성능을 의도한 것이 아니다. 구현자는 최적화할 것을 권장한다.

색인

이 사양에서 정의하는 용어

참조로 정의된 용어

참고문헌

규범 참고문헌

[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC9562]
K. Davis; B. Peabody; P. Leach. Universally Unique IDentifiers (UUIDs). May 2024. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9562
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Device API. URL: https://immersive-web.github.io/webxr/
[WEBXR-AR-MODULE-1]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Augmented Reality Module - Level 1. URL: https://immersive-web.github.io/webxr-ar-module/

IDL 색인

[SecureContext, Exposed=Window]
interface XRAnchor {
  readonly attribute XRSpace anchorSpace;

  Promise<DOMString> requestPersistentHandle();

  undefined delete();
};

partial interface XRFrame {
  Promise<XRAnchor> createAnchor(XRRigidTransform pose, XRSpace space);
};

partial interface XRSession {
  readonly attribute FrozenArray<DOMString> persistentAnchors;

  Promise<XRAnchor> restorePersistentAnchor(DOMString uuid);
  Promise<undefined> deletePersistentAnchor(DOMString uuid);
};

partial interface XRHitTestResult {
  Promise<XRAnchor> createAnchor();
};

[Exposed=Window]
interface XRAnchorSet {
  readonly setlike<XRAnchor>;
};

partial interface XRFrame {
  [SameObject] readonly attribute XRAnchorSet trackedAnchors;
};

이슈 색인

세션의 "list of frame updates"에는 순서를 지정하는 방법이 필요할 수 있다. 일부 알고리즘은 다른 알고리즘에 의존할 수 있다.
움직이는 일반 객체 추적을 지원하는 기기를 나는 알지 못한다. 이런 기기를 사양에서 전혀 고려해야 하는가? 그런 기기의 예가 있는가?
MDN

XRAnchor/anchorSpace

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRAnchor/delete

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRAnchorSet

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRFrame/createAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRFrame/trackedAnchors

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRHitTestResult/createAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?