본문 바로가기
2026년 9월 10일18분 읽기

디지털 자격증명 API — Chrome 141·Safari 26에서 안정 지원 시작

YS
김영삼
조회 7
디지털 자격증명 API — Chrome 141·Safari 26에서 안정 지원 시작

디지털 자격증명 API(Digital Credentials API)가 2025년 9월 Chrome 141과 Safari 26에서 정식(stable) 지원에 들어갔다. 이제 웹페이지가 navigator.credentials.get()로 모바일 운전면허증 같은 신분증을 브라우저를 통해 안전하게 요청할 수 있다.

OS가 지갑 앱 선택을 중재하고, 응답은 암호화되어 브라우저는 내용을 못 본다. EU의 디지털 신원(EUDI) 아키텍처는 회원국 지갑에 이 API 지원을 조건부로 요구하기 시작했다. 패스키(WebAuthn)와 같은 뿌리(CTAP)를 쓰지만 목적이 다르다 — 하나는 ‘로그인’, 하나는 ‘신원 제시’다.

솔직히 처음 이 API 이름을 들었을 때 나는 또 하나의 실험적 플래그 기능이려니 했다. 웹에서 신분증을 다룬다는 발상 자체가 프라이버시 지뢰밭처럼 느껴졌으니까. 그런데 2025년 9월, 2주 간격으로 Safari 26(9월 15일)과 Chrome 141(9월 30일)이 나란히 정식 지원을 실으면서 얘기가 달라졌다. 실험이 아니라 두 개의 주요 렌더링 엔진에 ‘기본 탑재’된 표준이 된 것이다. 웹 개발자 입장에서 이건 그냥 넘길 뉴스가 아니다.

무슨 일이 정확히 일어났나

핵심만 말하면, 신분증을 웹에 제시하는 기능이 ‘실험(Origin Trial)’ 단계를 졸업해 안정 채널로 넘어왔다. Chrome은 141 버전에서 OpenID4VP와 ISO 18013-7 방식(mdoc online)을 모두 지원하고, 데스크톱에서는 QR + BLE로 휴대폰 지갑을 불러오는 크로스 디바이스 흐름까지 붙였다. Safari 26은 좀 더 보수적이어서 org-iso-mdoc 프로토콜만, 그것도 제시(presentation) 전용으로 지원한다. 발급(issuance)은 아직 브라우저 API로 못 한다.

타임라인을 압축하면 이렇게 된다. 실험이 1년 넘게 돌다가 올가을 한꺼번에 정식으로 풀렸다는 게 요점이다.

시점사건의미
2024-08Chrome 128 안드로이드 Origin Trial모바일에서 첫 실험 시작
2025-03Chrome 134 데스크톱 Origin Trial크로스 디바이스 흐름 실험
2025-09-15Safari 26 정식 지원org-iso-mdoc, 제시 전용
2025-09-30Chrome 141 정식 지원OpenID4VP + mdoc, 크로스 디바이스
2025-11TPAC에서 프로토콜 레지스트리 폐지허용 프로토콜을 명시적으로 고정
2026-02캘리포니아 DMV, DC API 지원 추가정부 기관 초기 도입 사례
2026-Q1Firefox 149 코드 반영(플래그)아직 기본 비활성, 입장은 유보적
참고 Edge는 크로미움 기반이라 141부터 Chrome과 같은 능력을 그대로 물려받는다. 즉 사실상 데스크톱 주요 브라우저 중에서는 파이어폭스만 아직 뒤에 서 있는 셈이다.

디지털 자격증명 API가 정확히 하는 일

한 문장으로: 웹사이트가 사용자의 디지털 지갑에게 ‘이 증명을 보여달라’고 요청하고, 지갑이 사용자 동의 하에 서명된 증명을 돌려주는 통로다. 여기서 지갑은 안드로이드/iOS에 깔린 신분증 앱(모바일 운전면허, EU 디지털 지갑 등)이고, 브라우저는 ‘중개인’ 역할만 한다. 중요한 건 브라우저가 그 응답을 못 읽는다는 점이다. 응답은 검증자(사이트)의 공개키로 암호화되어 브라우저에는 불투명(opaque)하게 지나간다.

기존에 이런 걸 하려면 각 지갑 벤더의 딥링크나 커스텀 스킴, 혹은 QR 코드를 손으로 붙여야 했다. 파편화가 심했다. DC API는 이 과정을 navigator.credentials.get()라는 표준 한 곳으로 모은 것이다. WebAuthn을 이미 써봤다면 인터페이스가 익숙할 것이다 — 실제로 같은 Credential Management API 위에 얹혀 있다.

// 기능 지원 여부부터 확인 (DigitalCredential 인터페이스 존재로 판별)
if (typeof DigitalCredential === "undefined") {
  // 미지원 브라우저 — 기존 신원확인 방식으로 폴백
  return fallbackToLegacyVerification();
}

// 특정 프로토콜 지원 여부까지 확인하려면 (v5+ 브라우저)
if (DigitalCredential.userAgentAllowsProtocol?.("openid4vp-v1-signed")) {
  // openid4vp 서명 요청 사용 가능
}

코드로 보는 신원 제시 요청

실제 호출은 digital이라는 키 아래 requests 배열을 넘기는 형태다. 각 요청은 프로토콜 이름과 그 프로토콜에 맞는 data로 이뤄진다. 아래는 나이 인증(만 18세 이상만 선택적으로 공개)을 OpenID4VP로 요청하는 뼈대다. 실제 data 안의 쿼리는 프로토콜 스펙(DCQL 등)을 따라야 한다.

const controller = new AbortController();

try {
  const credential = await navigator.credentials.get({
    signal: controller.signal,
    mediation: "required",   // 반드시 사용자 상호작용을 거치도록 강제
    digital: {
      requests: [
        {
          protocol: "openid4vp-v1-signed",
          data: {
            // 서버가 만든 서명된 요청 객체(nonce, client_id, DCQL 쿼리 등)
            // 여기서는 “나이 18세 이상” 속성만 선택적 공개를 요구한다고 가정
            ...signedRequestFromServer,
          },
        },
      ],
    },
  });

  // credential.data 는 암호화된 응답 — 그대로 서버로 보내 검증
  await fetch("/verify", {
    method: "POST",
    body: JSON.stringify({ protocol: credential.protocol, data: credential.data }),
  });
} catch (err) {
  // 사용자가 취소하면 NotAllowedError
  if (err.name === "NotAllowedError") showUserCancelled();
  else showGenericError(err);
}
주의 검증(verify)은 반드시 서버에서 해야 한다. 클라이언트가 받은 credential.data는 검증자 키로 암호화된 서명 데이터이지, 브라우저가 신뢰할 판정 결과가 아니다. nonce 발급과 서명 검증을 프런트에서 흉내 내면 리플레이 공격에 그대로 뚫린다. 이건 문서에서 강조가 약한데, 실무에서 제일 먼저 틀리는 지점이다.

org-iso-mdoc vs OpenID4VP, 뭘 골라야 하나

지금 안정 채널에서 실질적으로 만나는 프로토콜은 둘이다. org-iso-mdoc는 ISO/IEC 18013-5/7 표준을 따르는 정부 신분증(모바일 운전면허, 국가 ID)용으로 좁고 엄격하게 정의돼 있고, openid4vp는 OpenID 재단 표준으로 포맷에 구애받지 않는(W3C VC, SD-JWT, mdoc 다 실림) 범용 교환 프로토콜이다. Safari를 반드시 지원해야 한다면 사실상 선택지는 mdoc뿐이라는 점이 현실적인 제약이다.

구분org-iso-mdocOpenID4VP
표준ISO/IEC 18013-5 / 18013-7OpenID Foundation
데이터 포맷CBOR 기반, 엄격히 고정포맷 무관(VC·SD-JWT·mdoc)
선택적 공개사전 정의 네임스페이스의 솔티드 해시DCQL / Presentation Exchange 쿼리
주 용도정부 ID(mDL, 국가신분증)범용 자격증명 교환
Chrome 141지원지원
Safari 26지원(유일)미지원

2025년 11월 TPAC에서 W3C FedID 워킹그룹은 열려 있던 프로토콜 레지스트리를 없애고, 허용 프로토콜을 명시적으로 고정하기로 했다. 2026년 1월 기준 제시용은 openid4vp-v1-unsigned/signed/multisignedorg-iso-mdoc, 발급용은 openid4vci-v1(Chrome 143 Origin Trial) 정도다. 목록에 없는 프로토콜은 브라우저가 거부한다. 개인적으로는 이 ‘화이트리스트 고정’ 결정이 초기 파편화를 막는 데는 낫다고 본다. 다만 새 프로토콜 실험은 그만큼 느려질 것이다.

패스키(WebAuthn)와는 뭐가 다른가

가장 많이 받는 질문이 이거다. 결론부터: 계층이 다르다. WebAuthn/패스키는 ‘이 계정이 당신 것인가’를 증명하는 인증(authentication)이고, DC API는 ‘당신이 누구이며 이런 속성을 가졌는가’를 제시(presentation)하는 것이다. 둘 다 CTAP 크로스 디바이스 흐름과 기기에 봉인된 키를 쓰지만, 답하는 질문이 다르다.

WebAuthn / 패스키Digital Credentials API
목적로그인·계정 인증신원·속성 제시
답하는 질문“이 계정 주인이 맞나?”“나이/이름/면허가 이건가?”
호출navigator.credentials.get({publicKey})navigator.credentials.get({digital})
발급 주체사이트가 등록 시 키 생성정부·기관이 지갑에 발급
선택적 공개해당 없음핵심 기능(속성 하나만 공개)

실무에서는 둘을 섞어 쓰게 될 가능성이 높다. 패스키로 계정에 로그인시키고, 고위험 절차(예: 대여·계좌개설·연령 확인)에서만 DC API로 신분증을 한 번 더 요구하는 식이다. 같은 navigator.credentials.get() 지붕 아래 있으니 코드 모양이 비슷해서, 오히려 둘을 헷갈려 엉뚱한 옵션 키를 넣는 실수를 조심해야 한다.

EU 디지털 신원(EUDI)이 이걸 조건부로 요구한다

이 API가 단순한 브라우저 실험이 아니라 ‘정책’과 엮인다는 신호가 EUDI다. EU 디지털 신원 지갑의 아키텍처 참조 프레임워크(ARF) Topic F는 모든 회원국 지갑에 DC API 지원을 조건부로 요구한다. 조건은 두 가지 — 스펙이 W3C 권고(Recommendation) 지위에 도달할 것, 그리고 기능·브라우저/OS 중립성·프라이버시·DoS 방어에 대한 기대치를 충족할 것이다.

즉 ‘지금 당장 무조건 써라’가 아니라 ‘표준이 익으면 표준 통로로 붙어라’에 가깝다. 유럽 지갑 컨소시엄은 이미 DC API 테스트 케이스를 적합성(conformance) 프로그램에 넣었고, 미국에서는 캘리포니아 DMV의 OpenCred 플랫폼이 v10.0.0에서 DC API 지원을 추가하며 초기 정부 도입 사례가 됐다. 유럽만의 얘기가 아니라는 뜻이다.

참고 한국 개발자 관점에서 당장 실무에 들어오는 건 아니다. 다만 글로벌 서비스에서 EU 사용자의 연령·신원 확인을 다룬다면, 향후 커스텀 연동 대신 이 표준 통로로 수렴할 공산이 크다. 미리 아키텍처에서 ‘검증은 서버, 요청은 표준 API’ 형태로 여지를 남겨두는 정도가 현실적이다.

웹 개발자가 지금 챙길 것 — 프라이버시와 UX

이 API의 설계 철학은 ‘최소 공개’다. 나이 확인 하나 때문에 주소·생년월일·면허번호까지 통째로 넘길 이유가 없다. 선택적 공개(selective disclosure)로 필요한 속성 하나만 요구하는 게 정석이고, 요청 UI 문구도 그에 맞춰야 사용자가 동의를 눌러준다. 개인적으로는 ‘왜 이 정보가 필요한지’를 요청 직전에 한 줄로 설명하는 화면을 붙이는 게 전환율에 크게 작용한다고 본다.

UX에서 놓치기 쉬운 함정 몇 가지. 첫째, mediation: "required"가 사실상 강제라 사용자 제스처 없이는 호출이 막힌다 — 페이지 로드 직후 자동 호출은 실패한다. 둘째, 사용자가 취소하면 NotAllowedError가 나는데 이걸 ‘에러’로 처리해 붉은 토스트를 띄우면 안 된다. 취소는 정상 흐름이다. 셋째, 데스크톱에서는 휴대폰 지갑을 QR로 부르는 크로스 디바이스라 시간이 걸린다. 로딩·대기 상태를 반드시 설계해야 한다.

주의 아직 남은 보안 이슈가 있다. 지갑 선택 바인딩 결함(malicious wallet이 OpenID4VCI 사전인가 코드를 가로챌 수 있는 문제)이 보고돼, 정부 발급 도입을 막고 있다. 그래서 발급(issuance)은 여전히 실험 단계(Chrome 143 Origin Trial)이고, 지금 안정적으로 쓸 수 있는 건 제시(presentation)까지라고 보는 게 안전하다.

“안정”이라도 아직 조심할 것들

정식 지원이라고 해서 다 익은 건 아니다. 냉정하게 한계를 정리하면 이렇다. 스펙 자체는 아직 W3C 권고까지 1~2년 남았다는 평가가 많고, 프라이버시에 대한 규범적(normative) 요구사항이 스펙에 아직 부족하다. Mozilla는 데이터 공유 남용, 신분증 없는 사용자의 배제, 선택적 공개의 비연결성(unlinkability) 미비를 이유로 여전히 유보적이다 — 그래서 Firefox 149도 플래그 뒤에 숨겨져 있다.

실무 체크리스트로 요약하면: (1) 지금은 제시만, 발급은 기대하지 말 것. (2) Safari를 지원하려면 org-iso-mdoc 경로를 반드시 확보할 것. (3) 항상 기능 탐지 후 폴백을 둘 것 — 파이어폭스·구형 브라우저·지갑 미설치 사용자가 상당수다. (4) 검증은 서버, 프라이버시 문구는 요청 직전. 이 네 개만 지켜도 초기 도입에서 크게 데일 일은 없다.

현실에서 어떤 서비스가 먼저 쓸까

이 표준이 가장 먼저 실익을 보는 곳은 ‘법적으로 신원·연령 확인이 강제되는 서비스’다. 지금은 이런 곳들이 대부분 신분증 사진을 업로드받아 OCR로 읽거나, 외부 신원확인 벤더에 붙여 처리한다. 사진 업로드 방식은 위조에 취약하고, 무엇보다 필요 없는 정보(주소·주민번호 전체)까지 사업자가 떠안게 돼 유출 시 책임이 커진다. DC API의 선택적 공개는 이 부담을 구조적으로 줄여준다 — ‘18세 이상 참/거짓’만 받으면 애초에 저장할 민감정보가 없다.

구체적으로 이런 흐름들이 우선 후보다. 공통점은 “한 속성만 확인하면 되는데 지금은 과하게 받고 있다”는 것이다.

  • 연령 제한 콘텐츠·주류/전자담배 커머스 — 생년월일 대신 “성인 여부”만 요구.
  • 렌터카·모빌리티 — 모바일 운전면허(mDL)로 유효 면허 보유를 즉시 검증.
  • 금융 온보딩(KYC) — 정부 발급 신분증 제시로 대면 확인 절차 단축.
  • 공공 서비스 로그인 — 국가 디지털 지갑으로 신원 연계(EU 중심).

반대로 지금 서둘러 붙일 필요가 없는 곳도 분명하다. 단순 회원가입, 이메일 인증으로 충분한 서비스, 혹은 사용자 대다수가 아직 디지털 신분증을 발급받지 않은 지역이라면 폴백만 요란해지고 실익이 없다. 나라면 ‘신분증이 있어야만 진행되는 고위험 단계’가 명확히 있는 서비스부터 파일럿으로 붙여보고, 발급 보급률을 보며 확대하는 순서를 택하겠다.

자주 묻는 질문

디지털 자격증명 API는 지금 프로덕션에 써도 되나요?

제시(presentation) 용도라면 Chrome 141+와 Safari 26+에서 안정 채널로 쓸 수 있습니다. 다만 반드시 기능 탐지 후 폴백을 두고, 발급(issuance)은 아직 실험 단계라 의존하지 마세요. 서버 측 검증이 전제입니다.

WebAuthn/패스키를 쓰고 있으면 이걸로 대체하나요?

아니요, 대체가 아니라 보완입니다. 패스키는 로그인 인증, DC API는 신원·속성 제시로 목적이 다릅니다. 로그인은 패스키로, 고위험 단계의 연령·신원 확인은 DC API로 나눠 쓰는 조합이 자연스럽습니다.

org-iso-mdoc와 OpenID4VP 중 뭘 지원해야 하나요?

Safari까지 지원하려면 org-iso-mdoc은 사실상 필수입니다. Safari 26은 이 프로토콜만 지원하기 때문입니다. 범용성과 포맷 유연성이 필요하면 Chrome/Edge에서 OpenID4VP를 추가로 받는 이중 지원이 안전합니다.

브라우저가 사용자의 신분증 내용을 볼 수 있나요?

아니요. 응답은 검증자(사이트)의 키로 암호화되어 브라우저에는 불투명하게 전달됩니다. 브라우저는 지갑 선택을 중재할 뿐 내용을 읽지 못하며, 실제 검증은 사이트 서버에서 이뤄집니다.

EU EUDI 지갑이 이 API를 반드시 요구하나요?

조건부입니다. ARF Topic F는 스펙이 W3C 권고에 도달하고 프라이버시·중립성 등 기준을 충족하는 것을 전제로 지원을 요구합니다. 지금 당장의 의무는 아니지만, 향후 표준 통로로 수렴할 방향입니다.

사용자가 지갑이 없거나 취소하면 어떻게 처리하나요?

취소 시 NotAllowedError가 발생하는데 이는 정상 흐름이므로 에러가 아닌 “다른 방법으로 진행” UX로 처리하세요. 지갑 미설치·미지원 브라우저를 위해 기존 신원확인(문서 업로드 등)으로의 폴백 경로를 항상 마련해야 합니다.

출처 Corbado, “Digital Credentials API”(corbado.com/blog/digital-credentials-api), W3C Digital Credentials 스펙, Chrome 141 / WebKit(Safari 26) 릴리스 노트. 버전·날짜는 2026년 초 기준.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록