패스키(WebAuthn) 입문 — 비밀번호와 뭐가 다른지, 무엇을 설계해야 하는지

패스키WebAuthn보안인증Next.js

“패스키 달면 끝”이 아니라, 사용자가 잃어버리는 것(기기, 계정, 생체)과 서버가 믿는 것(공개키, challenge, origin)을 다시 정리해야 합니다. 이 글은 구현 라이브러리 나열 대신, 비밀번호와의 차이WebAuthn에 등장하는 역할만 짚고 넘어갈게요.

사용자가 체감하는 차이

비밀번호는 결국 기억하거나 메모한 공유 비밀이고, 유출·재사용·피싱에 노출됩니다. 패스키는 기기/OS가 보관하는 비대칭 키로, 서버에는 공개키만 남습니다. 도메인에 바인딩되기 때문에 피싱 사이트에서 같은 공격이 잘 먹지 않는다는 이야기가 자주 나오는 이유예요.

비밀번호 로그인과 패스키 로그인 비교

다만 복구 UX는 오히려 더 어려워질 수 있어요. “이메일 재설정” 한 방에 끝나던 흐름이, 패스키만으로 가면 다른 기기 등록, 백업 키, 인간 상담 같은 설계가 필요해질 수 있습니다.

WebAuthn에서 꼭 알아둘 세 이름

스펙을 읽을 때 등장하는 Relying Party(RP), 클라이언트(브라우저), Authenticator만 정리돼 있어도 문서가 반은 읽힙니다. RP는 당신의 백엔드와 도메인, 브라우저는 navigator.credentials 쪽 UI와 출처 전달, Authenticator는 플랫폼(TPM)이나 보안 키 쪽입니다.

WebAuthn 등장인물: RP, 브라우저, Authenticator

Next.js App Router를 쓴다면 보통 Route Handler에서 challenge를 세션에 싣고, 검증 후 세션 쿠키를 발급하는 패턴이 많습니다. 서명 검증·credentialId 매핑은 검증된 라이브러리를 쓰는 편이 안전하고, “직접 ASN.1 파싱”은 피하는 게 좋아요.

점진 도입을 추천하는 이유

이미 비밀번호+MFA를 쓰는 서비스라면, 비밀번호와 패스키를 병행한 뒤 로그인 화면에서 패스키를 조금씩 앞으로 당기는 방식이 운영 리스크가 적습니다. 팀에는 “패스키가 비밀번호를 대체할 수 있는지”보다 “어떤 사용자 세그먼트부터 시도할지”를 먼저 정하라고 말하고 싶어요.

정리

패스키는 인증 UX와 보안 아키텍처를 동시에 바꾸는 큰 결정입니다. 이 글은 그 결정을 할 때 필요한 개념 지도만 그렸고, 실제 도입 시에는 제품별 제약(브라우저, 기업 정책, 규제)을 릴리즈 노트 수준까지 따라가야 합니다. 이후에 실제 Route Handler 예제가 필요하면 그때 코드 편으로 이어 볼게요.

궁금한 점이 있으신가요?

협업·의뢰는 아래로, 가벼운 소통은 인스타그램 @bluefox._.hi도 환영이에요.