Copyright © 2026 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 명세는 시각, 청각 또는 촉각 매체를 통해 검증 가능한 자격 증명을 표현하는 데 사용할 수 있는 검증 가능한 자격 증명 데이터 모델의 확장 메커니즘을 설명합니다. 이는 검증 가능한 자격 증명을 물리적 문서, 디지털 이미지, 스크린 리더 또는 점자 출력으로 렌더링하는 것을 다룹니다.
이 절은 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 다음 W3C 표준 및 초안 색인에서 확인할 수 있습니다.
이것은 실험적 명세이며 정기적으로 개정되고 있습니다. 이는 프로덕션 배포에 적합하지 않습니다.
이 문서는 검증 가능한 자격 증명 작업 그룹이 권고안 트랙을 사용하여 작업 초안으로 발행했습니다.
작업 초안으로 발행되었다고 해서 W3C 및 그 회원의 승인을 의미하지는 않습니다.
이것은 초안 문서이며 언제든지 다른 문서로 업데이트, 대체 또는 폐기될 수 있습니다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 적절하지 않습니다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹이 작성했습니다. W3C는 해당 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지합니다. 이 페이지에는 특허 공개를 위한 지침도 포함되어 있습니다. 자신이 믿기에 필수 청구항을 포함하는 특허에 대해 실제 지식을 가진 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 합니다.
이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받습니다.
렌더링 메서드는 발급자가 검증 가능한 자격 증명을 시각적, 청각적 또는 촉각적 메커니즘을 통해 관찰자에게 표현하고자 하는 특정한 방식이 있을 때 사용할 수 있다. 예를 들어, 직원 배지 자격 증명의 발급자는 회사 로고의 풍부한 이미지와 직원 정보를 배지의 특정 영역에 구체적으로 배치한 내용을 포함하고자 할 수 있다. 또한 시력과 관련된 접근성 요구가 있는 개인을 위해 배지의 중요한 측면을 음성으로 읽어 주는 기능을 제공하고자 할 수도 있다.
이 문서 전체에서 사용되는 일부 용어는 검증 가능한 자격 증명 데이터 모델 v2.1 명세의 용어 절에 정의되어 있다.
비규범적으로 표시된 섹션뿐만 아니라, 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적이다. 이 명세의 그 밖의 모든 내용은 규범적이다.
이 문서의 핵심어 MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED 및 SHOULD는 여기에 표시된 것처럼 모두 대문자로 나타나는 경우에만 BCP 14 [RFC2119] [RFC8174] 에 설명된 대로 해석해야 한다.
적합한 렌더링 메서드는 이 명세의 규범적 문장을 준수하는 데이터 모델의 모든 구체적인 표현을 말한다. 특히 이 문서의 섹션 2. 데이터 모델 및 3. 알고리즘에 있는 관련된 모든 규범적 문장은 MUST 시행되어야 한다.
적합한 프로세서는 적합한 렌더링 메서드를 생성하거나 소비하는 소프트웨어 및/또는 하드웨어로 구현된 모든 알고리즘을 말한다. 적합한 프로세서는 MUST 비적합 문서를 소비할 때 오류를 생성해야 한다.
이 문서에는 JSON 및 JSON-LD 콘텐츠가 포함된 예제도 있다. 이러한
예제 중 일부에는 인라인 주석(//) 및 예제에 거의 가치를 더하지 않는
정보를 나타내기 위한 줄임표(...) 사용과 같이 JSON에서 유효하지 않은 문자가
포함되어 있다. 구현자는 이 정보를 유효한 JSON 또는
JSON-LD로 사용하고자 하는 경우 이러한 콘텐츠를 제거하도록 주의해야
한다.
다음 섹션에서는 렌더링 메서드에 대해 이 명세에서 사용하는 데이터 모델을 설명한다.
renderMethod 속성은
검증
가능한 자격 증명 데이터 모델
v2.1 명세의 예약된 확장 지점이다. 발급자는 이 속성을
검증 가능한
자격 증명에서
사용하여 하나 이상의 선호 렌더링 방법을 표현할 수 있다.
renderMethod 속성의 값은 소프트웨어가 시각적, 청각적 또는 촉각적 메커니즘을 사용하여
검증
가능한
자격 증명을 표현하는 데 사용할 수 있는 하나 이상의 렌더링 메서드를 반드시
지정해야 한다. 각
renderMethod 값은 예를 들어
TemplateRenderMethod와 같은 type을 반드시
지정해야 한다. 각 렌더링 힌트의 정확한 내용은 해당
renderMethod type
정의에 따라 결정된다.
발급자가
검증 가능한
자격 증명에
대해 템플릿 기반 렌더링 지침을 지정하려는 경우,
아래에 설명된 데이터 모델을 사용하는 renderMethod 속성을 추가할 수 있다.
| 속성 | 설명 | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| id | URL 표준을 따르며 가져왔을 때 렌더링 템플릿을 역참조하는 선택 사항인 문자열. | ||||||||
| type |
값이 TemplateRenderMethod여야 하는 필수 문자열.
|
||||||||
| renderSuite | 구체적인 렌더링을 생성하는 데 사용되는 알고리즘을 식별하는 필수 문자열. | ||||||||
| name | 수행될 렌더링 유형에 대한 힌트를 제공하기 위해 표시할 수 있는 선택 사항인 사람이 읽을 수 있는 문자열. 이 속성은 개인이 여러 프레젠테이션 모드 중 하나를 선택할 수 있도록 하는 그래픽 인터페이스에서 사용될 수 있다. | ||||||||
| description |
특정 렌더링이 언제 유용할 수 있는지에 대해 name보다
더 자세한 설명을 제공하는 선택 사항인 사람이 읽을 수 있는 문자열.
|
||||||||
| renderProperty |
이 특정 렌더링 메서드를 사용할 때 검증 가능한
자격 증명에서 어떤 속성이 노출되는지를 지정하는
JavaScript Object Notation (JSON)
포인터 구문을 각각 따르는 문자열 값의 선택 사항인
목록.
renderProperty가 제공되지 않으면, 렌더링 메서드를 사용할 때 전체 검증 가능한
자격 증명이
공유되는 것으로 간주한다.
|
||||||||
| template |
렌더링을 수행하는 데 사용할 템플릿을 제공하거나 참조하는
선택 사항인 URL 또는 맵.
값이 URL인 경우,
템플릿 코드를 포함하는 data: URL [RFC2397]일 수 있다.
값이 맵인 경우, 다음 규칙을 반드시 준수해야 한다.
|
||||||||
| digestMultibase |
id가 지정된 경우 참조되는 렌더링 메서드의
multibase로 인코딩된 선택 사항인 Multihash.
multibase 값은 u
(base64url-nopad)여야 하며, multihash
값은 256비트 출력의 SHA-2(0x12)여야 한다.
|
card 렌더 스위트는 JSON 템플릿을 사용하여
검증
가능한
자격 증명을 표준화된 데이터 표시 형식으로 변환합니다. 이 형식을
사용하면 지갑에서 주요 데이터가 강조되고 추가 필드를 구성할 수 있는 반응형 카드 레이아웃으로 자격 증명을
표시할 수 있습니다. 이 메서드를 구현하는 지갑은 표준화된 JSON 출력을 자체 카드 UI
디자인으로 렌더링할 수 있으므로, 지갑에서 특정 자격 증명 유형을
기본적으로 지원하지 않는 경우에도 자격 증명을 표시할 수 있습니다.
템플릿과 렌더링된 출력은 모두 아래에 제시된 단일 정의인 카드 객체를 공유하는 JSON 객체입니다. 템플릿의 문자열 값은 JavaScript 객체 표기법(JSON) 포인터에 명시된 JSON 포인터 문자열일 수 있으며, 이는 검증 가능한 자격 증명의 값을 참조합니다. 템플릿을 처리할 때 JSON 포인터 문자열은 자격 증명 데이터를 기준으로 평가되고 해석된 값으로 대체됩니다. 템플릿과 그 결과로 생성되는 출력은 모두 카드 객체 정의를 준수해야 합니다. 여러 필드에 걸친 복합 데이터는 지원되지 않으며, 각 필드는 단일 JSON 포인터를 참조합니다.
카드 객체는 아래에 정의된 멤버를 가진 JSON 객체 [RFC8259]입니다.
동일한 정의가 템플릿과 렌더링된 출력에 적용됩니다. 템플릿에서
문자열로 정의된 모든 멤버의 값에는 대신 사용할 수 있습니다
하나의
JSON 포인터 문자열(JavaScript 객체 표기법(JSON)
포인터에 명시된 대로 /로 시작)로서
검증 가능한
자격 증명의 값을 참조하는 것을 사용할 수 있으며,
필드 객체의 label 및 value 멤버에 대해 별도로 명시된 경우는 제외합니다. 렌더링된 출력에서는
모든 JSON 포인터가 해석된 값으로 대체됩니다.
namedescriptionicondata: URL
[RFC2397]을 포함하는 선택
사항 문자열입니다.
themeprimaryColoraccentColorfieldslabelvalue"/issuer")이어야 합니다.
languagedirectionvalidFromvalidUntil템플릿은 처리하기 전에 위의 카드 객체 정의에 따라 검증하는 것이 좋습니다. 카드 템플릿을 위한 비규범적 JSON 스키마는 C. 카드 템플릿 JSON 스키마에 제공됩니다.
다음 예제는 JSON 포인터
문자열을 사용하는 유효한 card 템플릿을 보여 줍니다.
{
"name": "/credentialSubject/degree/name",
"description": "대학교 학위 자격 증명",
"icon": "/credentialSubject/icon",
"theme": {
"primaryColor": "#1a5490",
"accentColor": "/credentialSubject/theme/accentColor"
},
"fields": [
{
"label": "기관",
"value": "/issuer"
},
{
"label": "학위 유형",
"value": "/credentialSubject/degree/type"
},
{
"label": "발급일",
"value": "/validFrom"
}
],
"validFrom": "/validFrom",
"validUntil": "/validUntil"
}
다음 예제는 유효한 card 출력을 보여 줍니다.
{
"name": "이학 및 문학 학사",
"description": "대학교 학위 자격 증명",
"icon": "https://example.edu/icons/degree.svg",
"theme": {
"primaryColor": "#1a5490",
"accentColor": "#4a90e2"
},
"fields": [
{
"label": "기관",
"value": "예시 대학교"
},
{
"label": "학위 유형",
"value": "BachelorDegree"
},
{
"label": "졸업일",
"value": "2010-05-15"
}
],
"validFrom": "2010-01-01T19:23:24Z",
"validUntil": null
}
아래 예제에서는 JSON 템플릿이
검증 가능한
자격 증명에 data: URL [RFC2397]로 직접 포함됩니다.
{
...
"renderMethod": {
"type": "TemplateRenderMethod",
"renderSuite": "card",
// JSON 템플릿은 VC에 포함됩니다
"template": "data:application/json;base64,eyJuYW1lIjogIi9jcmVkZW50aWFsU3ViamVjdC9kZWdyZWUvbmFtZSIsICJkZXNjcmlwdGlvbiI6ICJVbml2ZXJzaXR5IERlZ3JlZSBDcmVkZW50aWFsIiwgImZpZWxkcyI6IFt7ImxhYmVsIjogIkluc3RpdHV0aW9uIiwgInZhbHVlIjogIi9pc3N1ZXIifV19"
}
}
다음 예제는 웹의 JSON 템플릿에 연결하고 digestMultibase 속성을
사용하여 수정되지 않도록 보호합니다.
{
...
"renderMethod": {
"type": "TemplateRenderMethod",
"renderSuite": "card",
"template": {
// 이 JSON 템플릿은 웹에서 가져옵니다
"id": "https://degree.example/credential-templates/bachelors.json",
"mediaType": "application/json",
"digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR"
}
}
다음 예제는 웹의 렌더링 템플릿에 연결하고
digestMultibase 속성을 사용하여 보호합니다.
{
...
"renderMethod": {
// 이 렌더 메서드는 웹에서 가져옵니다
"id": "https://degrees.example/bachelors-card.jsonld",
"mediaType": "application/ld+json",
"type": "TemplateRenderMethod",
"renderSuite": "card",
"digestMultibase": "zQmG270iEu5h6JqWAPdhyxz2dRerWC85Wg6wFl9znFCwYxAp"
}
html 렌더링 제품군을 사용하면 템플릿 작성자가
검증
가능한
자격 증명을 렌더링하기 위한 HTML 템플릿을 제공할 수 있다. HTML은
template 또는
template.id(template의
값이 객체인 경우)의 값으로 원격에서 참조하거나 data: URL을 통해 참조할 수 있다.
HTML 조각 내의 JavaScript는 HTML 템플릿과 함께 샌드박스된 iframe에서
호스팅되는 HTML 데이터 블록
(즉, <script type="application/vc"></script>)을 통해 제공된
필터링된 검증 가능한
자격 증명 데이터를 렌더링하는 역할을 한다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"type": [
"VerifiableCredential",
"NameCredential"
],
"issuer": {
"id": "did:example:1234",
"name": "발급자"
},
"credentialSubject": {
"name": "예제 이름",
"notRendered": "표시되지 않아야 함"
},
"renderMethod": {
"type": "TemplateRenderMethod",
"renderSuite": "html",
"renderProperty": [
"/issuer/name",
"/credentialSubject/name"
],
"template": {
"id": "https://test.example/credential-templates/NameCredential.html",
"mediaType": "text/html",
"digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR"
},
"outputPreference": {
"accessMode": [
"visual"
],
"mediaType": "application/html",
"style": {
"width": "800px",
"height": "800px"
}
}
}
}
구현은 필터링된 검증 가능한
자격 증명 데이터를 사용하여 JavaScript가 HTML 템플릿을 안전하게
렌더링할 수 있는 환경을 반드시 제공해야 한다.
또한 호스트 페이지는 Oblivious HTTP [RFC9458]
또는 보호 릴레이를 사용하여 요청 클라이언트를 요청된 출처로부터 분리하는
다른 수단을 사용함으로써 이루어지는 모든 요청(예: template.id 역참조)의 개인정보 보호를
보호하는 것이 권장된다.
이 환경을 설명하기 위해 다음 용어를 사용한다:
최소한 이 환경은 추적 및 기타 개인정보 보호 피해를 방지하기 위해 탐색, 외부 콘텐츠 로드, 호스트 페이지에 대한 접근을 반드시 방지해야 한다.
환경은 또한 사용자의 환경에서 사용할 수 있는 모든
국제화 및 접근성 설정을 템플릿 코드에
노출해야 합니다.
이를 통해 템플릿은 개인이 이미 자신의
사용자 에이전트 또는 운영 체제에 표현한 언어, 텍스트 크기,
대비 및 모션 환경 설정을 따를 수 있습니다. 이러한 설정의 예로는
rem 단위 및
prefers-contrast, prefers-reduced-motion, forced-colors와 같은
미디어 쿼리처럼 CSS에 반영되는 설정과,
Intl 및 Navigator.language에서 제공하는 로케일 정보처럼
JavaScript에서 사용할 수 있는
설정이 있습니다.
예를 들어 브라우저 기반 구현은
호스트 페이지에 대한 Content Security Policy [CSP3] 제한,
HTML 템플릿을 호스팅하는 iframe의 샌드박싱 및
HTML 템플릿을 래핑하여 추가 CSP 제한을 적용하고
호스트 페이지와 준비 및 오류 이벤트 통신을
제공하는 래퍼 코드를 조합하여 이러한 환경을 제공할 수 있습니다.
샌드박스 처리된 iframe은 기본적으로 위의 국제화 및 접근성
요구 사항을 충족합니다. 이 섹션에서 설명한 샌드박스 및 CSP 제한은
CSS 미디어 쿼리나 Intl 및 Navigator.language와 같은 JavaScript API를
방해하지 않습니다. 모바일 플랫폼의 WebView와 같이
html 렌더 스위트를 위한 대체 렌더링 환경도 사용할 수 있습니다.
호스트 페이지(일반적으로 지갑 또는 검증 가능한 자격 증명 렌더러)는 HTML 템플릿이 최상위 브라우징 컨텍스트를 탐색하거나, 외부 콘텐츠에 접근하거나, 호스트 페이지에 접근하거나, 원격 콘텐츠를 로드하지 못하도록 반드시 방지해야 한다.
호스트 페이지를 사용하는 경우 다음 규칙이 적용된다:
frame-src 'none'이
반드시 포함되어야 한다.
이렇게 하면 iframe에서 src 대신 srcdoc을 사용하도록 강제되어,
브라우저가 HTML 템플릿을 로드하지 못하게 한다. 이에 따라
호스트 페이지 코드는 원격으로 참조된 템플릿
코드를 미리 로드하고, 템플릿을 래퍼 코드에 삽입하기 전에
응답을 관련 digestMultibase 값과 대조하여 확인해야 한다.
iframe에는 탐색 및 최상위 접근을 방지하기 위해
sandbox="allow-scripts"가 반드시 설정되어야 한다.
<html>
<head>
<meta http-equiv="content-security-policy" content="frame-src 'none'">
</head>
<body>
<iframe id="renderer" sandbox="allow-scripts allow-modals" srcdoc=""></iframe>
</body>
</html>
renderMethod의
template 속성이 참조하는 HTML 템플릿
코드는
검증 가능한
자격 증명을 렌더링하는 데 필요한 HTML, CSS 및 JavaScript를 포함하는
HTML 조각이어야 한다.
템플릿 코드에는 <html>,
<head> 또는
<body> 태그가 절대로 포함되어서는 안 된다.
이러한 태그는 래퍼
코드에서 제공되기 때문이다.
<div>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
console.log('템플릿 렌더링 스크립트 실행 중');
// 예제 렌더러로 자격 증명을 JSON으로 표시한다. 여기서는 무엇이든
// 대신 수행할 수 있으며, 표시할 HTML을 생성하기 위한 mustache/기타 스타일의
// 템플릿 처리도 포함된다
// FIXME: 데이터 블록/script 태그에 가장 적합한 이름/위치를 결정한다
const credential = JSON.parse(document.querySelector(
'head > script[name="credential"]').innerHTML);
document.querySelector('#credentialSubject-name').innerText =
credential.credentialSubject.name;
document.querySelector('#issuer-name').innerText =
credential.issuer.name;
// TBD: 렌더링이 완료되었음을 호스트에 알린다
window.renderMethodReady();
});
</script>
<style>
h1 {
color: blue;
}
</style>
<h1 id="credentialSubject-name"></h1>
<p>발급자: <span id="issuer-name"></span></p>
</div>
템플릿 HTML 조각은 부분적인 검증 가능한
자격 증명을 포함하는 데이터 블록을 제공하고,
탐색과 외부 콘텐츠 로드를 방지하기 위한 추가 CSP 정책을 적용하는 래퍼 코드로
반드시 감싸야 한다. 구체적으로 래퍼
코드는 템플릿
코드가 네트워크 요청을 수행하지 못하도록
default-src data: 'unsafe-inline'이라는 다음 CSP 제한을
반드시 추가해야 한다.
<html>
<head>
<meta http-equiv="content-security-policy" content="default-src data: 'unsafe-inline'">
<script name="credential" type="application/vc">${JSON.stringify(credential)}</script>
</head>
<body>${template}</body>
</html>
설정을 완료하려면 호스트 페이지는
검증 가능한
자격 증명과 템플릿 코드로 채워진
래퍼
코드를 iframe의 srcdoc
속성에 반드시 삽입해야 한다. 그러면 래퍼
코드와 템플릿 코드에 포함된 모든 JavaScript가
실행된다.
<html>
<head>
<meta http-equiv="content-security-policy" content="default-src 'none' data: 'unsafe-inline'">
<!-- 래퍼 코드에 삽입된 자격 증명 데이터 블록. -->
<script name="credential" type="application/vc">{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"type": [
"VerifiableCredential",
"NameCredential"
],
"issuer": {
"id": "did:example:1234",
"name": "발급자"
},
"credentialSubject": {
"name": "예제 이름"
}
}</script>
<!-- 자격 증명 데이터 블록 끝 -->
</head>
<body>
<!-- 래퍼 코드에 삽입된 템플릿 HTML. -->
<div>
<script>
console.log('템플릿 렌더링 스크립트 실행 중');
// 예제 렌더러로 자격 증명을 JSON으로 표시한다. 여기서는 무엇이든
// 대신 수행할 수 있으며, 표시할 HTML을 생성하기 위한 mustache/기타 스타일의
// 템플릿 처리도 포함된다
// FIXME: 데이터 블록/script 태그에 가장 적합한 이름/위치를 결정한다
const credential = JSON.parse(document.querySelector(
'head > script[name="credential"]').innerHTML);
document.querySelector('#credentialSubject-name').innerText =
credential.credentialSubject.name;
document.querySelector('#issuer-name').innerText =
credential.issuer.name;
// TBD: 렌더링이 완료되었음을 호스트에 알린다
window.renderMethodReady()
</script>
<style>
h1 {
color: blue;
}
</style>
<h1 id="credentialSubject-name"></h1>
<p>발급자: <span id="issuer-name"></span></p>
</div>
<!-- 템플릿 HTML 끝 -->
</body>
</html>
래퍼 코드에서 생성된 iframe은
렌더링이 완료되었거나 렌더링 중 오류가 발생했을 때 템플릿이
호스트 페이지에 알릴 수 있도록
통신 채널을 반드시 제공해야 한다. 이는
래퍼 코드에서 설정한
MessageChannel과 함께 postMessage API를 사용하여 구현할 수 있다.
아래에 표시된 JavaScript는 위의 호스트 페이지에
추가되어 MessageChannel을 설정하는 iframe의
onload 이벤트를 추가한다. 또한
호스트 페이지는
래퍼 코드에서 ready 메시지를 받으면
이행되고 error 메시지를 받으면 거부되는 Promise도 생성한다.
또한 래퍼 코드는 템플릿이
렌더링 완료를 호스트 페이지에 알리거나 오류 메시지를 다시
보내는 데 사용할 수 있는 window.renderMethodReady 메서드도 제공한다.
// 렌더링이 준비되면 이행되는 promise(실패하면 거부됨)
// 대신 디스플레이 또는 오류를 표시하는 데 사용할 수 있다
let resolveRender;
let rejectRender;
const readyPromise = new Promise((resolve, reject) => {
resolveRender = resolve;
rejectRender = reject;
});
// iframe의 템플릿 코드에서 사용할 통신 채널을 설정한다
renderer.onload = () => {
// MessageChannel을 생성하고 하나의 포트를 iframe으로 전송한다
const channel = new MessageChannel();
// iframe을 로드하는 동안 메시지가 손실되지 않도록 메시지 큐를 시작한다
channel.port1.start();
// `ready` 메시지를 처리한다
channel.port1.onmessage = function ready(event) {
if(event.data === 'ready') {
// 준비되었으므로 iframe을 표시한다
resolveRender();
} else {
rejectRender(new Error(event.data?.error?.message));
}
channel.port1.onmessage = undefined;
};
// "start" 메시지를 보내고, 반환 통신을 위해 `port2`를 iframe으로 보낸다
renderer.contentWindow.postMessage('start', '*', [channel.port2]);
};
// ready 또는 error에 대한 이벤트 응답을 설정한다
// NOTE: 이 섹션은 지갑/렌더러의 UX 요구사항에 따라 달라진다
readyPromise.then(() => {
console.log('렌더링 준비 완료');
const renderer = document.getElementById('renderer');
renderer.hidden = false;
}).catch(err => {
const errorMessage = document.getElementById('error-message');
errorMessage.style.display = 'block';
errorMessage.innerText = '렌더링 실패: ' + err.message;
console.error('렌더링 실패', err);
});
// 부모 창의 통신 포트로 이행될 promise를
// 추가한다
const portPromise = new Promise(resolve => {
window.addEventListener('message', function start(event) {
if(event.data === 'start' && event.ports?.[0]) {
window.removeEventListener('message', start);
resolve(event.ports[0]);
}
});
});
// 템플릿이 "준비됨"(또는 오류 발생)을 알릴 때 호출할 함수를 window에 연결하고
// 부모가 iframe을 표시할지 결정할 수 있도록 메시지를
// 부모에 보낸다
window.renderMethodReady = function(err) {
portPromise.then(port => port.postMessage(
!err ? 'ready' : {error: {message: err.message}}));
};
이 설정을 사용하면 템플릿 JavaScript는 window.renderMethodReady()를 호출하여
렌더링이 완료되었음을 호스트 페이지에 알리거나
window.renderMethodReady(new Error("error message"))를 호출하여 호스트 페이지에
오류를 알릴 수 있다.
렌더링 환경 기본 설정은 렌더링 메서드 내에 제공할 수 있다. 이 객체의 목적은 제공된 템플릿을 렌더링할 때 권장되는 용도, 표시 및 의도된 접근 모드를 제공하는 것이다. 구현은 이러한 기본 설정이 제공된 경우 이를 따르는 것이 권장된다.
| 속성 | 설명 |
|---|---|
| outputPreference | 제공된 템플릿에 대해 선호하는 렌더링 환경을 나타내는 선택 사항인 맵. |
outputPreference 객체에는 다음 속성 중 하나 이상을
포함할 수 있다:
| 속성 | 설명 |
|---|---|
| accessMode |
https://w3c.github.io/cg-reports/a11y-discov-vocab/CG-FINAL-vocabulary-20260128/#accessMode-vocabulary
에 정의된 auditory, tactile,
textual 또는 visual의 문자열
값 하나 이상으로 구성된 선택 사항인 목록.
|
| mediaType | 렌더링에 선호되는 IANA 미디어 유형에 나열된 유효한 미디어 유형을 나타내는 선택 사항인 문자열. 이 값은 렌더링 전에 추가 처리를 제안할 때 사용할 수 있다. 예로는 SVG 템플릿을 정적 이미지로 변환하거나 HTML 문서를 PDF로 변환하는 것이 있다. |
| style | 렌더링 환경에서 잠재적으로 사용할 스타일 속성을 정의하는 선택 사항인 맵. |
style 객체에는 다음 속성 중 하나 이상을 포함할 수 있다:
| 속성 | 설명 |
|---|---|
| width |
iframe에 설정할 CSS 호환 너비 기본 설정을 포함하는
선택 사항인 문자열.
|
| height |
iframe에 설정할 CSS 호환 높이 기본 설정을 포함하는
선택 사항인 문자열.
|
nfc 렌더링 제품군은 무선 NFC 연결을 통해
검증
가능한
자격 증명을 나타내는 바이너리 페이로드를 전송한다.
아래 예제에서는 완전히 내장된 NFC 페이로드를 렌더링 템플릿으로 사용하며, 이 템플릿은 자격 증명과 연결된 바코드 식별자만 공개한다.
{
...
"renderMethod": {
"type": "TemplateRenderMethod",
"renderSuite": "nfc",
"name": "탭하여 전송",
// NFC 페이로드가 내장되어 있다
"template": "data:application/octet-stream;base64,2QZkpQGDG...G8XJWnROcY4Biw",
// NFC를 통해 바코드만 전송된다
"renderProperty": ["/credentialSubject/barcode"]
}
...
}
다음 섹션에서는 렌더링 메서드에 대해 이 명세에서 사용하는 알고리즘을 설명한다.
card 템플릿을 처리할 때 다음 단계를 반드시
수행해야 한다:
/로 시작하는 경우(JSON 포인터임을 나타냄),
대상 문서로
검증 가능한
자격 증명을 사용하여 JSON 포인터 알고리즘 JavaScript 객체 표기법(JSON)
포인터에 따라 이를 평가합니다.
null을 반환하는 경우 동작은
구현에 따라 달라집니다. 구현은 빈 문자열을 사용할 수도 있고,
값을
null로 둘 수도 있으며, 오류를 알릴 수도 있습니다.
/로 시작하지 않는 경우 리터럴 문자열로 처리하고
변경하지 않은 채 그대로 둡니다.
여러 필드에 걸친 복합 데이터는 지원되지 않는다는 점에 유의한다. 템플릿의 각 필드는 자격 증명에서 하나의 값으로 확인되는 하나의 JSON 포인터를 참조한다.
다음 섹션에서는 html 렌더링 제품군이 HTML 템플릿을 안전하게 렌더링하는 데 사용하는
알고리즘을 설명한다. 보안 및 개인정보 보호 결과와 출력이 동일한 한
대체 알고리즘을 사용할 수 있다.
호스트 페이지는 HTML 템플릿을 호스팅하기 위한
iframe 요소를 반드시 생성해야 한다.
호스트 페이지는 탐색과 최상위 접근을 방지하기 위해
iframe의 sandbox 속성을
allow-scripts로 반드시 설정해야 한다.
vc를 렌더링할 검증 가능한
자격 증명이라고 하자.
vc에서 선택한 renderMethod 속성 중
renderMethod.type이 TemplateRenderMethod이고
renderMethod.renderSuite가 html인 것을
renderMethod라고 하자.
renderMethod.template이 문자열이면,
template을
renderMethod.template의 값이라고 하자.
renderMethod.template이 맵이면,
template을
renderMethod.template.id의 URL을 가져온 결과라고 하자.
호스트 페이지는 renderMethod.renderProperty가
존재하는 경우 여기에 지정된 속성만 포함하도록 검증 가능한
자격 증명 vc를 반드시 필터링해야 한다.
renderMethod.renderProperty가 존재하지 않으면 전체 검증 가능한
자격 증명을
사용한다.
이 필터링은 Data Integrity ECDSA Cryptosuites v1.0 명세 [VC-DI-ECDSA]의
섹션 3.4.13 selectJsonLd에 정의된
selectJsonLd 알고리즘을
renderMethod.renderProperty에 있는 JSON 포인터 [RFC6901] 값에 적용하여
반드시 수행해야 한다.
호스트 페이지는 필터링된 검증 가능한 자격 증명과 HTML 템플릿을 위에서 정의한 래퍼 코드 템플릿에 삽입하여 래퍼 코드를 반드시 생성해야 한다.
wrapperCode를 <head>에 <meta http-equiv="Content-Security-Policy"
content="default-src data: 'unsafe-inline'">가 있는 HTML 문서라고 하자.
datablock을 type이
application/vc인 HTML 데이터 블록이라고 하자.
datablock의 내용을 문자열화된 JSON 형식의 필터링된 검증 가능한
자격 증명으로
설정한다.
datablock을 wrapperCode의 <head>에 삽입한다.
template의 값을
wrapperCode의 <body>에 삽입한다.
호스트 페이지는 iframe의
srcdoc 속성을 결과 래퍼 코드로 반드시
설정해야 한다.
iframe의 srcdoc 속성을
wrapperCode의 문자열화된 HTML로 설정한다.
호스트 페이지는 위에서 설명한 대로 ready 및
error 메시지를 수신하기 위해 래퍼 코드와의 통신
채널을 반드시 설정해야 한다.
renderPromise를 다음과 같은 새 Promise라고 하자:
resolve 시 사용자에게 iframe을 표시하는 데 사용할 수 있다.
reject 시 사용자에게 오류 메시지를 표시한다.
iframe의 onload 이벤트에서:
channel을 새 MessageChannel이라고 하자.
wrapperCode를 통해 iframe에 삽입된
template의 코드에서 오는 ready
메시지를 수신하는 새 port1 리스너를
channel에 생성하고 시작한다.
port1 리스너에서 ready 메시지를 수신하면
renderPromise를 이행한다.
error 메시지를 수신하면 오류
메시지와 함께 renderPromise를 거부한다.
postMessage를 사용하여 channel의 port2를
iframe 콘텐츠 창으로 전송한다.
호스트 페이지는 렌더링이
완료되었는지 또는 렌더링 중 오류가 발생했는지를 판단하기 위해
renderPromise를 사용하는 것이 권장된다.
래퍼 코드는
MessageChannel을 통해 호스트 페이지로부터 통신을 수신하도록 반드시
설정하고, 템플릿 코드에서 사용할
window.renderMethodReady 메서드를 제공해야 한다.
이 섹션은 비규범적이다.
이 섹션에서는 렌더링 메서드의 게시, 검색 및 처리와 관련된 보안 및 개인정보 보호 고려사항을 다루는 이 명세의 위협 모델을 요약한다. 대응과 데이터 흐름 다이어그램을 포함한 전체 분석은 검증 가능한 자격 증명 렌더링 메서드 위협 모델에서 제공한다.
독자는 이 섹션을 읽기 전에 검증 가능한 자격 증명 데이터 모델 v2.1 명세의 위협 모델 섹션에서 제공하는 일반적인 위협 모델을 숙지할 것을 권장한다. 구현자는 해당 명세에서 제공하는 일반 분석을 이 명세에서 제공하는 각 구체적인 기능에 적용해야 한다.
html 렌더링 제품군은 템플릿에서 제공한 코드를 실행하고 신뢰할 수 없는 입력인
자격 증명 값을 소비하므로, 올바른 형식의 검증된 자격 증명 내부에 들어온 악성 콘텐츠가
렌더링 중 주변의
호스트 페이지에 접근하거나, 다른 곳으로 탐색하거나,
외부 위치에 접속하려고 시도할 수 있다.
html 렌더링 제품군은 선택한 렌더링 환경이 제공하는 격리에 의존하므로,
샌드박스를 벗어나거나, 정책을 우회하거나, 템플릿과 호스트 사이의 격리를
깨뜨릴 수 있게 하는 결함은 렌더링 메서드를 명세에 정확히 따라 사용하는 경우에도
렌더링 프로세스의 결함이 된다.
W3C는 포괄적인 위협 모델링 접근 방식으로 전환하고 있으며 새로운 명세에서 보안 고려사항 섹션을 폐기하는 과정에 있다. 보안 고려사항과 관련된 문서는 부록 A. 위협 모델을 참조한다.
W3C는 포괄적인 위협 모델링 접근 방식으로 전환하고 있으며 새로운 명세에서 개인정보 보호 고려사항 섹션을 폐기하는 과정에 있다. 개인정보 보호 고려사항과 관련된 문서는 부록 A. 위협 모델을 참조한다.
이 섹션은 비규범적이다.
검증 가능한 자격 증명을 발급자가 선호하는, 사람이 인지할 수 있는 형태로 표현하기 위해 기존의 여러 접근 방식과 기술이 검토되었다. 검증 가능한 자격 증명. 이 절에서는 그러한 대안과 이 명세에 설명된 렌더링 메서드 접근 방식이 선택된 이유를 요약한다.
어떤 메커니즘도 정의하지 않고 표현을 보유자 또는 검증자 소프트웨어에 맡기면 추가 데이터가 필요하지 않지만, 발급자가 의도한 표현을 전달할 방법이 없으므로 자격 증명이 일관되지 않게 렌더링되고 클레임이나 브랜딩이 잘못 표현될 수 있다. 이는 통제되지 않는 자격 증명 표현에 설명되어 있다. 다음과 같은 자격 증명 형식도 이러한 방식을 사용한다. ISO/IEC 18013-5 모바일 운전 면허증(mDL)과 JSON 웹 토큰 (RFC 7519)은 이러한 접근 방식을 취하여 자격 증명에 포함되는 클레임을 정의하지만 그 표현은 이를 사용하는 소프트웨어에 맡긴다. 현재는 중단된 Microsoft의 정보 카드 (CardSpace)는 이 방식의 제한적인 변형을 사용하여 발급자가 신원 선택기가 일관된 카드 외형으로 렌더링하는 카드 이름과 로고만 제공할 수 있도록 했다. 이 명세는 클라이언트 결정 렌더링을 금지하는 대신 발급자가 명시하는 대안을 추가한다.
레지스트리를 통해 자격 증명 유형별 표현을 표준화하면 잘 알려진 유형을 일관되게 렌더링할 수 있지만, 각 유형에 대한 사전 지식이 필요하고 사용자 정의 자격 증명으로 확장되지 않으며 발급자별 브랜딩을 표현할 수 없다. 다음과 같은 플랫폼 지갑이 Apple Wallet (PassKit), Google Wallet 및 Samsung Wallet은 이러한 접근 방식을 취하여 미리 정의된 고정된 패스 또는 객체 유형 집합을 플랫폼이 제어하는 고정 레이아웃으로 렌더링한다. 여기서 발급자는 필드 값과 자산을 채울 수 있지만 플랫폼 카탈로그 외부의 레이아웃이나 브랜딩은 표현할 수 없다. 이 명세에서 정의하는 렌더링 메서드 전략은 대신 자격 증명과 함께 전달되거나 자격 증명에서 참조되므로 익숙하지 않은 유형도 해당 발급자가 의도한 대로 렌더링할 수 있다.
이와 같은 중앙 집중식이고 통제되며 레지스트리 중심적인 해결책은 또한 그 밖에 다음 생태계의 일부로 명시된 분산형, 탈중앙화형 및 무허가형 패턴과도 상충한다. 탈중앙화 식별자(DID) 및 검증 가능한 자격 증명(VC).
완전히 렌더링된 PDF, 정적 SVG 또는 HTML 문서를 배포하는 방식은 자체 완결적이며 광범위하게 지원되지만, 이러한 스냅샷은 선택적 공개에 맞게 조정되지 않고 검증된 데이터로 다시 렌더링할 수 없으며 보호된 내용과 결합되어 있지 않다. 이 명세는 이러한 형식을 완성된 문서가 아니라 렌더링 시 클레임 값과 결합되는 템플릿으로 재사용한다.
이 명세는 새로운 무결성 메커니즘을 정의하는 대신 검증 가능한 자격 증명 데이터 무결성 1.0 및 digestMultibase 속성과 같은 기존 보호 메커니즘을 사용하여 참조된 템플릿을 자격 증명에 결합한다. 독자는 다음의 일반적인 보호 메커니즘에 관해 보호되지 않은 외부 리소스 변조 위협을 검증 가능한 자격 증명 위협 모델에서 읽어 볼 수 있다.
SD-JWT
VC는
고정된 스타일 지정 속성 집합을 지원하는 simple 메서드와
모든 코드 실행을 금지하고 SVG의 텍스트 자리표시자를 클레임 값으로 대체하는
svg_templates 메서드 중에서 선택하기 위한 rendering 속성을 정의한다.
이 그룹은 이 접근 방식을 검토한 결과 실제 사용 사례에는 지나치게
제한적이라는 결론을 내렸다. 자리표시자는 텍스트 노드에만 나타나고 어떤 코드도 실행할 수 없으므로
조건부 필드, 가변 길이
목록, 값 형식 지정 및 반응형 레이아웃과 같은 데이터 기반 표현 도구를 나타낼 수 없다. 이러한
기능은 의료, 소매 및
은행/금융과 같은 부문의 요구 사항이다. 반면 이 명세는 단일
자격 증명 직렬화에 종속되지 않으며, 코드가 없는 선언적 card 스위트,
제한된 "샌드박스화된" 환경에서 실행되는 데이터 기반 html 스위트 및 정적 nfc 스위트에 걸친
렌더링 스위트를 정의한다.
이 섹션은 비규범적입니다.
다음 JSON 스키마는 2.2.1.1 카드 객체에 정의된 카드 객체 규칙을 카드 템플릿에 적용되는 대로 구현합니다. 이 스키마는 비규범적입니다.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["name", "description", "fields"],
"properties": {
"name": {
"type": "string",
"description": "리터럴 문자열 또는 JSON 포인터로 된 표시 이름(예: \"/credentialSubject/degree/name\")"
},
"description": {
"type": "string",
"description": "리터럴 문자열 또는 JSON 포인터로 된 설명"
},
"icon": {
"type": "string",
"description": "리터럴 문자열 또는 JSON 포인터로 된 아이콘 URL 또는 data: URL"
},
"theme": {
"type": "object",
"properties": {
"primaryColor": {
"type": "string",
"description": "리터럴 문자열 또는 JSON 포인터로 된 기본 색상"
},
"accentColor": {
"type": "string",
"description": "리터럴 문자열 또는 JSON 포인터로 된 강조 색상"
}
},
"additionalProperties": false
},
"fields": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["label", "value"],
"properties": {
"label": {
"type": "string",
"description": "필드 레이블(리터럴 문자열이며 JSON 포인터는 허용되지 않음)"
},
"value": {
"type": "string",
"pattern": "^/",
"description": "JSON 포인터 문자열로 된 필드 값(\"/\"로 시작)"
},
"language": {
"type": "string",
"description": "필드의 선택적 BCP 47 언어 태그"
},
"direction": {
"type": "string",
"description": "필드의 선택적 텍스트 방향 태그"
}
},
"additionalProperties": false
}
},
"validFrom": {
"type": "string",
"description": "리터럴 ISO 8601 날짜 문자열 또는 JSON 포인터로 된 유효성 시작 날짜"
},
"validUntil": {
"type": "string",
"description": "리터럴 ISO 8601 날짜 문자열 또는 JSON 포인터로 된 유효성 종료 날짜"
}
},
"additionalProperties": false
}
Referenced in:
Referenced in: