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 속성의 값은 소프트웨어가
검증
가능한
자격 증명을 시각적, 청각적 또는 촉각적 메커니즘을 사용하여 표현하는 데 사용할 수 있는
하나 이상의 렌더링 방법을 MUST 지정해야 합니다. 각
renderMethod 값은 예를 들어
SuiteRenderMethod와 같은 type을 MUST 지정해야 합니다.
각 렌더링 힌트의 정확한 내용은
renderSuite 속성에 지정된 렌더링 스위트에 따라 결정됩니다.
발급자가
검증 가능한
자격 증명에 대한
렌더링 지침을 지정하려는 경우,
아래에 설명된 데이터 모델을 사용하는 renderMethod 속성을 MAY 추가할 수 있습니다.
구체적인 렌더링 동작은 renderSuite 속성에 이름이 지정된
렌더링 스위트에 따라 결정됩니다.
각 렌더링 스위트는 아래 속성 중 어떤 것을 사용하는지 정의합니다. 각
렌더링 스위트 섹션을 참조하십시오.
| 속성 | 설명 | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| id | URL 표준을 따르며, 가져오면 렌더링 템플릿을 역참조하는 OPTIONAL 문자열입니다. | ||||||||
| type |
값이 SuiteRenderMethod이어야 하는 REQUIRED 문자열입니다.
|
||||||||
| renderSuite |
렌더링 스위트, 즉 구체적인 렌더링을 생성하는 데 사용되는
알고리즘 집합을 식별하는 REQUIRED 문자열입니다. 값은 일반
JSON 문자열이며 정확하고 대소문자를 구분하여 비교합니다. 이
명세에서는 static, summary 및
html 값을 정의합니다. 구현은
인식하거나 지원하지 않는 renderSuite 값을 가진
모든 renderMethod 항목을 MUST 무시해야 합니다.
|
||||||||
| name | 수행될 렌더링 유형에 대한 힌트를 제공하기 위해 표시할 수 있는 사람이 읽을 수 있는 OPTIONAL 문자열입니다. 이 속성은 개인이 여러 표시 모드 중에서 선택할 수 있도록 하는 그래픽 인터페이스에서 사용될 수 있습니다. | ||||||||
| description |
특정 렌더링이 유용할 수 있는 경우를 name보다
더 상세하게 설명하는 사람이 읽을 수 있는 OPTIONAL 문자열입니다.
|
||||||||
| renderProperty |
각각 JavaScript Object Notation (JSON)
포인터 구문을 준수하는 문자열 값의 OPTIONAL
목록으로, 이 특정 렌더링 방법을
사용할 때
검증 가능한
자격 증명의 어떤 속성이 노출되는지 지정합니다. renderProperty가 제공되지 않으면
렌더링 방법을 사용할 때 전체 검증 가능한
자격 증명이
공유되는 것으로 간주합니다.
|
||||||||
| template |
렌더링을 수행하는 데 사용할
템플릿을 제공하거나 참조하는 OPTIONAL URL 또는 맵입니다. 값이 URL인 경우,
템플릿 코드를 포함하는 data: URL [RFC2397]일 MAY 수 있습니다.
값이
맵인 경우 다음 규칙을 MUST 준수해야 합니다.
|
||||||||
| digestMultibase |
id가 지정된 경우 참조되는 렌더링 방법의
멀티베이스 인코딩된 Multihash인 OPTIONAL 값입니다. 멀티베이스 값은 u
(base64url-nopad)여야 하고 멀티해시
값은 256비트 출력의 SHA-2(0x12)여야 합니다.
|
렌더링 스위트 값이 어디에 등록되는지(이 명세의 레지스트리 섹션, VC Specs Directory 또는 둘 다), 그리고 확장 스위트 값이 일반 문자열인지 URL인지는 여전히 논의 중입니다.
summary 렌더링 스위트는 JSON 템플릿을 사용하여
검증
가능한
자격 증명을 표준화된 데이터 표시 형식으로 변환합니다. 이 형식을 사용하면
지갑이 주요 데이터를 강조하고 추가 필드를 구성할 수 있는 반응형 레이아웃으로
자격 증명을 표시할 수 있습니다. 이 방법을 구현하는 지갑은
표준화된 JSON 출력을 자체 UI 디자인으로 렌더링할 수 있으므로,
지갑이 특정 자격 증명 유형을 기본적으로 지원하지 않는 경우에도
자격 증명을 표시할 수 있습니다.
템플릿과 렌더링된 출력은 모두 아래에 제시된 단일 정의인 요약 객체를 공유하는 JSON 객체입니다. 템플릿의 문자열 값은 JavaScript Object Notation (JSON) 포인터에 명시된 JSON 포인터 문자열일 수 있으며, 검증 가능한 자격 증명의 값을 참조합니다. 템플릿을 처리할 때 JSON 포인터 문자열을 자격 증명 데이터에 대해 평가하고 해결된 값으로 대체합니다. 템플릿과 결과 출력 모두 요약 객체 정의를 MUST 준수해야 합니다. 여러 필드에 걸친 복합 데이터는 지원되지 않으며, 각 필드는 단일 JSON 포인터를 참조합니다.
summary 렌더링 스위트는 공통 렌더링 방법 속성을 다음과 같이 사용합니다.
| 속성 | 이 스위트에서의 사용 |
|---|---|
| template |
data: URL로 포함되거나
맵으로 참조되는 요약 템플릿을 제공합니다. 값은
2.2.1.2 요약 객체에 있는 요약 객체 정의를 준수하는
JSON 문서이거나 이를 역참조해야 합니다.
|
| renderProperty | 이 스위트에서는 사용하지 않습니다. 요약 템플릿의 JSON 포인터 문자열이 검증 가능한 자격 증명의 어떤 속성을 노출할지 결정합니다. |
| outputPreference |
제공할 MAY 수 있습니다. accessMode 및
style 기본 설정은
렌더링된 요약의 표시에 적용됩니다.
|
요약 객체는 아래에 정의된 멤버를 갖는 JSON 객체 [RFC8259]입니다.
동일한 정의가 템플릿과 렌더링된 출력에 적용됩니다. 템플릿에서
문자열로 정의된 멤버의 값은 대신
JavaScript Object Notation (JSON)
포인터에 명시된 것처럼 /로 시작하며
검증 가능한
자격 증명의 값을 참조하는 JSON 포인터 문자열일 MAY 수 있습니다.
다만 필드 객체의 label 및 value 멤버에 대해 명시된 예외가 있습니다.
렌더링된 출력에서는 모든 JSON 포인터가 해결된 값으로 대체됩니다.
namedescriptionicondata: URL
[RFC2397]을 포함하는
OPTIONAL 문자열입니다.
themeprimaryColoraccentColorfieldslabelvalue"/issuer").
languagedirectionvalidFromvalidUntil템플릿은 처리하기 전에 위의 요약 객체 정의에 대해 검증하는 것이 SHOULD 권장됩니다. 요약 템플릿을 위한 비규범적 JSON Schema는 C. 요약 템플릿 JSON Schema에 제공됩니다.
다음 예제는 JSON 포인터 문자열을 사용하는 유효한 요약 템플릿을 보여 줍니다.
{
"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"
}
다음 예제는 유효한 요약 출력을 보여 줍니다.
{
"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": "SuiteRenderMethod",
"renderSuite": "summary",
// JSON 템플릿이 VC에 포함되어 있습니다.
"template": "data:application/json;base64,eyJuYW1lIjogIi9jcmVkZW50aWFsU3ViamVjdC9kZWdyZWUvbmFtZSIsICJkZXNjcmlwdGlvbiI6ICJVbml2ZXJzaXR5IERlZ3JlZSBDcmVkZW50aWFsIiwgImZpZWxkcyI6IFt7ImxhYmVsIjogIkluc3RpdHV0aW9uIiwgInZhbHVlIjogIi9pc3N1ZXIifV19"
}
}
다음 예제는 웹의 JSON 템플릿에 연결하고
digestMultibase 속성을 사용하여 수정되지 않도록 보호합니다.
{
...
"renderMethod": {
"type": "SuiteRenderMethod",
"renderSuite": "summary",
"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": "SuiteRenderMethod",
"renderSuite": "summary",
"digestMultibase": "zQmG270iEu5h6JqWAPdhyxz2dRerWC85Wg6wFl9znFCwYxAp"
}
html 렌더링 스위트를 사용하면 템플릿 작성자가
검증
가능한
자격 증명을 렌더링하기 위한 HTML 템플릿을 제공할 수 있습니다. HTML은 원격으로 참조하거나
template 또는 template.id의 값으로 data: URL을 통해
참조할 수 있습니다(template의 값이 객체인 경우).
HTML 프래그먼트 내의 JavaScript는 HTML 데이터 블록
(즉, <script type="application/vc"></script>)을 통해 제공되는
필터링된 검증 가능한
자격 증명 데이터를 렌더링할 책임이 있으며,
이 데이터 블록은 HTML 템플릿과 함께 샌드박스된 iframe에서 호스팅됩니다.
{
"@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": "SuiteRenderMethod",
"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"
}
}
}
}
html 렌더링 스위트는 공통 렌더링 방법 속성을 다음과 같이 사용합니다.
| 속성 | 이 스위트에서의 사용 |
|---|---|
| template |
data: URL로 포함되거나
id가 프래그먼트를 역참조하는
맵으로 참조되는 HTML 프래그먼트를 제공합니다.
|
| renderProperty | 템플릿에 전달되는 검증 가능한 자격 증명 데이터를 제한하기 위해 제공할 MAY 수 있습니다. 존재하지 않으면 전체 검증 가능한 자격 증명이 제공됩니다. |
| outputPreference |
제공할 MAY 수 있습니다. style의 width
및 height 기본 설정은
템플릿을 호스팅하는 iframe에 적용됩니다.
|
구현은 필터링된 검증 가능한
자격 증명 데이터를 사용하여 JavaScript가 HTML 템플릿을
안전하게 렌더링할 수 있는 환경을 MUST 제공해야 합니다.
또한 호스트 페이지는
보호 릴레이를 사용하여 요청 클라이언트와 요청된 출처를 분리함으로써,
Oblivious HTTP [RFC9458] 또는 다른 수단을 사용하여
이루어진 모든 요청(예: template.id 역참조)의
개인정보를 보호하는 것이 SHOULD 권장됩니다.
다음 용어는 이 환경을 설명하는 데 사용됩니다.
환경은 최소한 추적 및 기타 개인정보 침해를 방지하기 위해 탐색, 외부 콘텐츠 로드 및 호스트 페이지 접근을 MUST 방지해야 합니다.
또한 환경은 템플릿 코드에
사용자 환경에서 사용할 수 있는 모든 국제화 및 접근성 설정을 MUST 노출해야 합니다.
이를 통해 템플릿은 개인이 사용자 에이전트 또는 운영 체제에 이미 표현한
언어, 텍스트 크기, 대비 및 모션 기본 설정을 따를 수 있습니다.
이러한 설정의 예로는 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 템플릿이 최상위 탐색 컨텍스트를 탐색하거나, 외부 콘텐츠에 접근하거나, 호스트 페이지에 접근하거나, 원격 콘텐츠를 로드하는 것을 MUST 방지해야 합니다.
호스트 페이지를 사용하는 경우 다음 규칙이 적용됩니다.
frame-src 'none'이 MUST 포함되어야 합니다.
이렇게 하면 iframe에 src 대신 srcdoc을 사용하도록 강제되어
브라우저가 HTML 템플릿을 로드하는 것을
방지합니다. 그 결과
호스트 페이지 코드는 원격으로 참조된 템플릿
코드를 미리 로드하고, 템플릿을 래퍼 코드에 삽입하기 전에
관련 digestMultibase 값과 응답을 확인해야 합니다.
iframe에
sandbox="allow-scripts"를 MUST 설정해야 합니다.
<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> 태그를 MUST NOT 포함해서는 안 됩니다.
이러한 태그는 래퍼
코드가 제공하기 때문입니다.
<div>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
console.log('running template render script');
// 예제 렌더러로 자격 증명을 JSON으로 표시합니다. 여기서는 무엇이든
// 대신 수행할 수 있으며, 표시할 HTML을 생성하기 위한 mustache/기타 스타일
// 템플릿 처리도 포함됩니다.
// FIXME: 데이터 블록/스크립트 태그에 가장 적합한 이름/위치를 결정합니다.
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 정책을 추가하는
래퍼 코드로 MUST 감싸야 합니다.
구체적으로 래퍼
코드는
템플릿
코드가 어떠한 네트워크 요청도 수행하지 못하도록
default-src data: 'unsafe-inline'이라는 다음 CSP 제한을 MUST
추가해야 합니다.
<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
속성에 MUST 삽입해야 하며, 그러면 래퍼
코드 및 템플릿 코드에 포함된 모든 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('running template render script');
// 예제 렌더러로 자격 증명을 JSON으로 표시합니다. 여기서는 무엇이든
// 대신 수행할 수 있으며, 표시할 HTML을 생성하기 위한 mustache/기타 스타일
// 템플릿 처리도 포함됩니다.
// FIXME: 데이터 블록/스크립트 태그에 가장 적합한 이름/위치를 결정합니다.
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은
렌더링이 완료되었을 때 또는 렌더링 중 오류가 발생했을 때
템플릿이 호스트 페이지에 알릴 수 있도록
통신 채널을 MUST 제공해야 합니다. 이는
래퍼 코드가 설정한 MessageChannel과
postMessage API를 사용하여 수행할 수 있습니다.
아래에 표시된 JavaScript는 위의 호스트 페이지에 추가되어
iframe에 MessageChannel을 설정하는
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]);
};
// 준비 또는 오류에 대한 이벤트 응답을 설정합니다.
// NOTE: 이 섹션은 지갑/렌더러의 UX 요구 사항에 고유합니다.
readyPromise.then(() => {
console.log('rendering ready');
const renderer = document.getElementById('renderer');
renderer.hidden = false;
}).catch(err => {
const errorMessage = document.getElementById('error-message');
errorMessage.style.display = 'block';
errorMessage.innerText = 'Rendering failed: ' + err.message;
console.error('rendering failed', 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에 함수를 연결합니다.
// "ready" 상태인지(또는 오류가 발생했는지)를 알리고 메시지를
// 상위 창으로 보내어 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"))를 호출하여 호스트 페이지에
오류를 알릴 수 있습니다.
렌더링 환경 기본 설정은 렌더링 방법 내에서 제공할 MAY 수 있습니다. 이 객체의 목적은 제공된 템플릿을 렌더링할 때 권장 사용 방식, 표시 및 의도된 접근 모드를 제공하는 것입니다. 구현은 제공된 경우 이러한 기본 설정을 따르는 것이 SHOULD 권장됩니다.
| 속성 | 설명 |
|---|---|
| outputPreference | 제공된 템플릿의 선호 렌더링 환경을 표현하는 OPTIONAL 맵입니다. |
outputPreference 객체는 다음 속성 중 하나 이상을
포함할 MAY 수 있습니다.
| 속성 | 설명 |
|---|---|
| accessMode |
다음에 정의된 auditory, tactile,
textual 또는 visual 값 중 하나 이상의
문자열로 이루어진
OPTIONAL 목록입니다.
https://w3c.github.io/cg-reports/a11y-discov-vocab/CG-FINAL-vocabulary-20260128/#accessMode-vocabulary
|
| mediaType | 렌더링에 선호되는 IANA 미디어 유형에 나열된 유효한 미디어 유형을 나타내는 OPTIONAL 문자열입니다. 이 값은 렌더링 전에 추가 처리를 제안할 때 사용할 MAY 수 있습니다. 예를 들어 SVG 템플릿을 정적 이미지로 변환하거나 HTML 문서를 PDF로 변환하는 경우가 있습니다. |
| style | 렌더링 환경에서 잠재적으로 사용할 스타일 속성을 정의하는 OPTIONAL 맵입니다. |
style 객체는 다음 속성 중 하나 이상을
포함할 MAY 수 있습니다.
| 속성 | 설명 |
|---|---|
| width |
iframe에 설정할 CSS 호환 너비 기본 설정을 포함하는
OPTIONAL 문자열입니다.
|
| height |
iframe에 설정할 CSS 호환 높이 기본 설정을 포함하는
OPTIONAL 문자열입니다.
|
static 렌더링 스위트는
검증
가능한
자격 증명을 다양한 정적 또는 사전 렌더링된 바이너리 형식으로 나타내는 바이너리 페이로드를 전달하는 데 사용되며,
여기에는 이미지, PDF 또는 내장된 NFC 페이로드 등이 포함됩니다.
아래 예제에서는 완전히 내장된 NFC 페이로드가 렌더링 템플릿으로 사용되며, 자격 증명과 관련된 바코드 식별자만 공개합니다.
{
...
"renderMethod": {
"type": "SuiteRenderMethod",
"renderSuite": "static",
"deliveryMode": "nfc",
"name": "탭하여 전송",
// NFC 페이로드가 내장됩니다
"template": "data:application/octet-stream;base64,2QZkpQGDG...G8XJWnROcY4Biw",
// 바코드만 NFC를 통해 전송됩니다
"renderProperty": ["/credentialSubject/barcode"]
}
...
}
static 렌더링 스위트는 공통 렌더링 메서드 속성을 다음과 같이 사용합니다:
| 속성 | 이 스위트에서의 사용 |
|---|---|
| template |
정적 바이너리 페이로드를 제공하며, 일반적으로 data: URL로 내장됩니다.
|
| deliveryMode |
렌더링된 템플릿에 의도된 전달 방법을 지정하며, 예를 들어
nfc
는 무선 NFC 채널을 통한 전송을 나타냅니다.
|
| renderProperty | 렌더링된 템플릿에 표현되는 검증 가능한 자격 증명 데이터를 제한하기 위해 제공될 수 있습니다. |
| outputPreference | 일반적으로 이 스위트에서는 사용되지 않습니다. |
다음 섹션에서는 이 명세에서 렌더링 방법에 사용하는 알고리즘을 설명합니다.
요약 템플릿을 처리할 때 다음 단계를 MUST 수행해야 합니다.
/로 시작하면(JSON 포인터임을 나타냄),
JSON Pointer 알고리즘 JavaScript Object Notation (JSON)
포인터를 사용하여
검증 가능한
자격 증명을 대상 문서로 평가합니다.
null을 반환하면 동작은
구현에 따라 다릅니다. 구현은 MAY 빈 문자열을 사용하거나,
값을
null로 그대로 두거나 오류를 알릴 수 있습니다.
/로 시작하지 않으면 리터럴 문자열로 취급하고
변경하지 않습니다.
여러 필드에 걸친 복합 데이터는 지원되지 않습니다. 템플릿의 각 필드는 자격 증명의 단일 값으로 확인되는 하나의 JSON 포인터를 참조합니다.
다음 섹션에서는 html 렌더링 스위트가 HTML 템플릿을 안전하게 렌더링하는 데 사용하는 알고리즘을
설명합니다. 보안 및 개인정보 보호 결과와 출력이 동일하다면 대체 알고리즘을 MAY 사용할 수
있습니다.
호스트 페이지는 HTML 템플릿을 호스팅하기 위한
iframe 요소를 MUST 생성해야 합니다.
호스트 페이지는
iframe의 sandbox 속성을
탐색 및 최상위 접근을 방지하도록 allow-scripts로 MUST 설정해야 합니다.
vc를 렌더링할 검증 가능한
자격 증명이라고 합니다.
renderMethod를 vc에서 선택된 renderMethod 속성이라고 하며,
여기서
renderMethod.type은 SuiteRenderMethod이고
renderMethod.renderSuite는 html입니다.
renderMethod.template이 문자열이면, template을
renderMethod.template의
값이라고 합니다.
renderMethod.template이 맵이면, template을
renderMethod.template.id의 URL을
가져온 결과라고 합니다.
호스트 페이지는 검증 가능한
자격 증명 vc를 renderMethod.renderProperty이 존재하는 경우
여기에 지정된 속성만 포함하도록 MUST 필터링해야 합니다.
renderMethod.renderProperty이 존재하지 않으면 전체 검증 가능한
자격 증명이
사용됩니다.
이 필터링은
Data Integrity ECDSA Cryptosuites v1.0 명세 [VC-DI-ECDSA]의
섹션 3.4.13 selectJsonLd에 정의된
selectJsonLd 알고리즘을
renderMethod.renderProperty에 존재하는 JSON Pointer [RFC6901] 값에 적용하여
MUST 수행해야 합니다.
호스트 페이지는 필터링된 래퍼 코드를 검증 가능한 자격 증명과 HTML 템플릿을 래퍼 코드 템플릿에 포함하여 위에서 정의된 대로 MUST 생성해야 합니다.
wrapperCode를 <head>에 <meta http-equiv="Content-Security-Policy"
content="default-src data: 'unsafe-inline'">가 있는 HTML Document라고 합니다.
datablock을 type이
application/vc인 HTML Data Block이라고 합니다.
datablock의 내용을 필터링된 검증 가능한
자격 증명의
문자열화된 JSON 형식으로 설정합니다.
datablock을 wrapperCode의 <head>에 삽입합니다.
template의 값을 wrapperCode의 <body>에
삽입합니다.
호스트 페이지는
iframe의 srcdoc 속성을
결과 래퍼 코드로 MUST 설정해야 합니다.
iframe의 srcdoc 속성을 wrapperCode의 문자열화된 HTML로
설정합니다.
호스트 페이지는 통신
채널을 래퍼 코드와 MUST 설정하여
위에서 설명한 대로 ready 및 error 메시지를 수신해야 합니다.
renderPromise를 다음과 같은 새 Promise라고 합니다.
resolve되면 사용자에게 iframe을 표시하는 데 사용할 수 있습니다.
reject되면 사용자에게 오류 메시지를 표시합니다.
iframe의 onload 이벤트에서:
channel을 새 MessageChannel이라고 합니다.
channel에 새 port1 리스너를 생성하고 시작하여
현재 iframe에 삽입된 template의 코드에서 오는 ready
메시지를
wrapperCode를 통해 수신합니다.
port1 리스너에서 ready 메시지를 수신하면
renderPromise를 resolve합니다.
error 메시지를 수신하면 renderPromise를 오류
메시지와 함께 reject합니다.
postMessage를 사용하여 channel의 port2를
iframe 콘텐츠 창으로 전송합니다.
호스트 페이지는
렌더링이 완료되었는지 또는 렌더링 중 오류가 발생했는지 판단하기 위해
renderPromise를 SHOULD 사용해야 합니다.
래퍼 코드는 호스트 페이지에서
MessageChannel을 통해 통신을 수신하도록 MUST 설정하고
템플릿 코드가 사용할 수 있도록 window.renderMethodReady
메서드를 제공해야 합니다.
이 섹션은 비규범적입니다.
이 섹션에서는 이 명세의 위협 모델을 요약하며, 렌더링 방법의 게시, 검색 및 처리와 관련된 보안 및 개인정보 보호 고려 사항을 다룹니다. 대응 및 데이터 흐름 다이어그램을 포함한 전체 분석은 검증 가능한 자격 증명 렌더링 방법 위협 모델에 제공됩니다.
독자는 이 섹션을 읽기 전에 검증 가능한 자격 증명 데이터 모델 v2.1 명세의 위협 모델 섹션에 제공된 일반 위협 모델을 숙지할 것을 권장합니다. 구현자는 해당 명세에서 제공하는 일반 분석을 이 명세에서 제공하는 각 특정 기능에 적용해야 합니다.
html 렌더링 스위트는 템플릿이 제공하는 코드를 실행하고 신뢰할 수 없는 입력인 자격 증명
값을 사용하므로, 올바른 형식이며 검증된 자격 증명 내부에 포함된 악의적인 콘텐츠가 렌더링 중
주변의
호스트 페이지에 접근하거나, 다른 곳으로 탐색하거나, 외부 위치에 접속하려고
시도할 수 있습니다.
html 렌더링 스위트는 선택한 렌더링 환경이 제공하는 격리에 의존하므로,
샌드박스를 탈출하거나, 정책을 우회하거나, 템플릿과 호스트 간의 격리를 깨뜨릴 수 있게 하는 결함은
렌더링 방법이 명시된 대로 정확하게 사용되는 경우에도 렌더링 프로세스의 결함이
됩니다.
W3C는 전체적인 위협 모델링 접근 방식으로 전환하고 있으며 새로운 명세에서 보안 고려 사항 섹션을 폐지하는 과정에 있습니다. 보안 고려 사항과 관련된 문서는 부록 A. 위협 모델을 참조하십시오.
W3C는 전체적인 위협 모델링 접근 방식으로 전환하고 있으며 새로운 명세에서 개인정보 보호 고려 사항 섹션을 폐지하는 과정에 있습니다. 개인정보 보호 고려 사항과 관련된 문서는 부록 A. 위협 모델을 참조하십시오.
이 섹션은 비규범적입니다.
검증 가능한 자격 증명을 발급자가 선호하는 사람이 인식할 수 있는 방식으로 표시하기 위해 여러 기존 접근 방식과 기술이 고려되었습니다. 이 섹션에서는 이러한 대안과 이 명세에 설명된 렌더링 방법 접근 방식이 선택된 이유를 요약합니다.
메커니즘을 정의하지 않고 표시를 보유자 또는 검증자 소프트웨어에 맡기면 추가 데이터가 필요하지 않지만, 발급자가 의도한 표시 방식을 전달할 방법이 없으므로 자격 증명이 일관되지 않게 렌더링되고 클레임이나 브랜딩이 잘못 표현될 수 있습니다. 이는 제어되지 않는 자격 증명 제시에서 설명합니다. 다음과 같은 자격 증명 형식, ISO/IEC 18013-5 모바일 운전 면허증(mDL) 및 JSON Web Tokens (RFC 7519)은 이러한 접근 방식을 취하며, 자격 증명이 포함하는 클레임을 정의하지만 그 표시는 이를 소비하는 소프트웨어에 맡깁니다. 현재는 중단된 Microsoft의 Information Card (CardSpace)는 이 접근 방식의 제한된 변형을 사용하여, 발급자가 신원 선택기가 균일한 카드 외형으로 렌더링할 카드 이름과 로고만 제공할 수 있도록 했습니다. 이 명세는 클라이언트 결정 렌더링을 금지하는 대신 발급자가 명시하는 대안을 추가합니다.
레지스트리를 통해 자격 증명 유형별 표시 방식을 표준화하면 잘 알려진 유형에 대해 일관된 렌더링을 제공하지만 각 유형에 대한 사전 지식이 필요하고, 사용자 지정 자격 증명으로 확장하기 어려우며, 발급자별 브랜딩을 표현할 수 없습니다. 다음과 같은 플랫폼 지갑, Apple Wallet (PassKit), Google Wallet 및 Samsung Wallet은 이러한 접근 방식을 취하여 미리 정의된 고정된 패스 또는 객체 유형 집합을 플랫폼이 제어하는 고정 레이아웃으로 렌더링하며, 여기서 발급자는 필드 값과 자산을 채울 수 있지만 플랫폼 카탈로그 밖의 레이아웃이나 브랜딩을 표현할 수 없습니다. 이 명세에서 정의하는 렌더링 방법 전략은 대신 자격 증명과 함께 전달되거나 자격 증명에서 참조되므로, 익숙하지 않은 유형이라도 해당 발급자가 의도한 대로 렌더링할 수 있습니다.
이러한 중앙 집중식이고 통제되며 레지스트리에 초점을 맞춘 해결책은 또한 분산 식별자(DID) 및 검증 가능한 자격 증명(VC) 생태계의 일부로 명시된 분산형, 탈중앙화형 및 무허가 패턴과도 상충합니다.
완전히 렌더링된 PDF, 정적 SVG 또는 HTML 문서를 배포하는 방식은 자체 완결적이며 널리 지원되지만, 이러한 스냅샷은 선택적 공개에 적응하지 못하고, 검증된 데이터에서 다시 렌더링할 수 없으며, 보호된 내용과 결합되지 않습니다. 이 명세는 이러한 형식을 완성된 문서로 사용하는 대신 렌더링 시 클레임 값과 결합되는 템플릿으로 재사용합니다.
새로운 무결성 메커니즘을 정의하는 대신, 이 명세는 검증 가능한 자격 증명 데이터 무결성 1.0과 같은 기존 보호 메커니즘 및 참조된 템플릿을 자격 증명에 결합하기 위한 digestMultibase 속성에 의존합니다. 독자는 보호되지 않은 외부 리소스 변조 위협에 대한 검증 가능한 자격 증명 위협 모델의 설명을 읽어 이러한 일반적인 보호 메커니즘에 대해 알아볼 수 있습니다.
SD-JWT
VC는
고정된 스타일링 속성 집합을 지원하는 simple 메서드와
코드 실행을 금지하고 텍스트 자리 표시자에 클레임 값을 대입하는 svg_templates 메서드 중에서 선택하기 위한
rendering 속성을 정의합니다. 이 그룹은 이 접근 방식을 검토한 결과 실제
사용 사례에는 지나치게 제한적이라고 판단했습니다. 자리 표시자는 텍스트 노드에만 나타나며 코드를 실행할 수 없기 때문에,
조건부 필드, 가변 길이
목록, 값 서식 지정, 반응형 레이아웃과 같은 데이터 기반 프레젠테이션 도구를 표현할 수 없습니다. 이러한
기능은 의료, 소매 및
은행/금융과 같은 분야의 요구 사항입니다. 이와 대조적으로, 이 명세는 단일
자격 증명 직렬화에 종속되지 않으며, 대신
코드 없는 선언적 summary 스위트, 제한된 "샌드박스" 환경에서 실행되는 데이터 기반 html 스위트 또는
static 스위트에 걸친 렌더링 스위트를 정의합니다.
이 섹션은 비규범적입니다.
다음 JSON 스키마는 요약 템플릿에 적용되는 2.2.1.2 요약 객체에 정의된 요약 객체 규칙을 구현합니다. 이 스키마는 비규범적 입니다.
{
"$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: