패스키 로그인 구현하는 법 WebAuthn 2026 개발 가이드

profile_image
작성자 인증설계 연구가 배하준
댓글 0건 조회 3회

비밀번호를 없애면 로그인 화면은 단순해지지만 개발자의 고민까지 사라지는 것은 아닙니다. 패스키를 도입하려는 팀은 곧바로 “생체정보를 서버에 저장해야 하나요?”, “휴대폰을 잃어버리면 계정은 어떻게 복구하나요?” 같은 질문과 마주합니다.

크림코드는 인증 시스템을 설계해 온 웹 보안 엔지니어 배하준과 함께 2026년 기준 패스키와 WebAuthn의 구조, 구현 순서, 운영 체크포인트를 인터뷰 형식으로 짚었습니다. 기능 시연에 그치지 않고 실제 서비스에 적용할 때 필요한 서버 검증과 복구 정책까지 다룹니다.

Q1. 패스키는 비밀번호 로그인과 무엇이 다른가요?

비밀 문자열 대신 공개키 암호화를 사용합니다

질문: 패스키를 지문이나 얼굴로 로그인하는 기능이라고 이해해도 될까요?

배하준: 사용자 경험만 보면 비슷하지만 기술적으로는 정확하지 않습니다. 패스키는 특정 웹사이트와 사용자 계정에 연결된 공개키·개인키 쌍이며, 지문과 얼굴 인식은 기기 안의 개인키를 사용할 수 있도록 사용자를 확인하는 수단입니다. 생체정보가 웹사이트 서버로 전달되거나 서버 데이터베이스에 저장되는 구조가 아닙니다.

등록 과정에서는 인증기가 키 쌍을 만들고 서버는 공개키와 자격 증명 식별자를 보관합니다. 로그인할 때 서버가 일회성 challenge를 보내면 인증기가 개인키로 서명하고, 서버는 저장한 공개키로 서명을 검증합니다. 개인키 자체는 서버에 전송되지 않으므로 비밀번호처럼 탈취된 문자열을 다른 사이트에서 재사용하기 어렵습니다. 코딩의 기본 개념부터 확인하고 싶다면 네이버 지식백과의 코딩 용어 설명도 함께 참고할 수 있습니다.

  • 피싱 저항성: 자격 증명이 RP ID와 웹 출처에 묶여 있어 가짜 도메인에서 같은 서명을 얻기 어렵습니다.
  • 서버 유출 대응: 서버에 저장된 공개키만으로는 정상 로그인 서명을 만들 수 없습니다.
  • 사용 편의성: 복잡한 비밀번호를 기억하거나 문자 인증번호를 반복 입력할 필요가 줄어듭니다.
  • 기기 인증: 화면 잠금 PIN, 지문, 얼굴 인식 또는 하드웨어 보안 키로 개인키 사용을 승인합니다.
전문가 팁: “패스키는 생체정보를 서버에 저장하는 기술”이라고 안내하면 불필요한 거부감이 생깁니다. 서비스 화면에서는 “기기에 안전하게 보관된 로그인 키를 화면 잠금으로 확인한다”고 설명하는 편이 정확합니다.

Q2. 2026년 WebAuthn 구현은 어디서 시작해야 하나요?

등록과 인증을 각각 두 개의 서버 요청으로 나눕니다

질문: 프론트엔드에서 navigator.credentials만 호출하면 패스키 로그인이 완성되나요?

배하준: 아닙니다. 브라우저 API 호출은 인증기와 통신하는 한 부분일 뿐이며, 보안의 중심은 서버가 생성한 challenge와 서버 측 검증입니다. 패스키 등록은 ‘옵션 요청 → 자격 증명 생성 → 결과 검증 및 저장’ 순서로, 로그인은 ‘인증 옵션 요청 → 서명 생성 → assertion 검증’ 순서로 설계해야 합니다.

먼저 로그인된 사용자가 패스키 추가를 요청하면 서버가 예측하기 어려운 challenge, RP 정보, 사용자 식별자, 허용 알고리즘을 반환합니다. 프론트엔드는 이를 navigator.credentials.create()에 전달하고 결과를 서버로 보냅니다. 서버는 challenge, origin, RP ID, 플래그와 공개키 데이터를 확인한 뒤 credential ID, 공개키, 서명 카운터, 전송 방식 등 필요한 값을 저장합니다.

  1. HTTPS 환경과 실제 서비스 도메인을 확정합니다.
  2. 서버에서 충분한 무작위성을 가진 일회성 challenge를 만들고 짧은 만료 시간을 둡니다.
  3. 등록에는 create(), 로그인에는 get()을 사용합니다.
  4. 브라우저가 반환한 바이너리 값을 Base64URL 형식으로 안전하게 직렬화합니다.
  5. 서버 검증이 성공한 경우에만 challenge를 폐기하고 세션을 발급합니다.

사용자 식별자와 RP ID를 신중하게 정합니다

WebAuthn의 사용자 ID에는 이메일 주소처럼 노출되거나 변경될 수 있는 값보다 내부의 불투명한 바이트 식별자를 사용하는 것이 좋습니다. RP ID는 일반적으로 서비스 도메인과 연결되며, 한번 잘못 정하면 서브도메인 구조를 바꿀 때 기존 패스키를 활용하지 못할 수 있습니다. 개발용 localhost와 운영 도메인의 자격 증명도 서로 별개라는 점을 기억해야 합니다.

2026년 7월 기준 WebAuthn Level 3는 구현 경험이 축적되는 단계이지만, 모든 최신 기능을 일괄 적용한다고 안정성이 자동으로 높아지지는 않습니다. 브라우저의 기능 지원 여부를 확인하고 기본 등록·인증 흐름부터 완성한 뒤 conditional mediation이나 Signal API 계열 기능을 점진적으로 추가하는 전략이 안전합니다.

Q3. 자동완성과 기존 비밀번호는 어떻게 함께 운영하나요?

패스키 우선 화면보다 자연스러운 선택권이 중요합니다

질문: 패스키를 출시하는 날 기존 비밀번호 로그인을 바로 제거해도 될까요?

배하준: 대다수 서비스에는 권하지 않습니다. 기존 회원이 모두 패스키를 등록한 것이 아니며 공용 PC, 오래된 브라우저, 회사 보안 정책처럼 사용자가 통제하기 어려운 환경도 존재합니다. 첫 단계에서는 비밀번호 로그인에 성공한 사용자에게 패스키 등록을 제안하고, 등록률과 성공률을 확인하면서 적용 범위를 넓혀야 합니다.

로그인 입력란에 autocomplete="username webauthn"을 지정하고 conditional mediation을 활용하면 사용자가 아이디 입력란을 선택했을 때 사용 가능한 패스키를 자동완성 후보로 제시할 수 있습니다. 별도의 커다란 ‘패스키 로그인’ 버튼만 두는 방식보다 기존 흐름에 자연스럽게 결합되며, 패스키 보유 여부를 기억하지 못하는 사용자도 덜 혼란스럽습니다.

운영 방식장점주의점
비밀번호와 패스키 병행도입 장벽이 낮고 기존 회원 대응이 쉽습니다.약한 비밀번호 복구 경로가 전체 보안을 낮출 수 있습니다.
패스키 우선 로그인로그인 속도와 피싱 저항성이 개선됩니다.사용할 수 없는 기기를 위한 대체 경로가 필요합니다.
패스키 전용 계정비밀번호 저장과 재설정 업무가 줄어듭니다.가입 단계부터 복구 수단과 추가 패스키 등록을 설계해야 합니다.

질문: 패스키를 한 개만 등록하게 하면 관리가 쉬워지지 않나요?

배하준: 관리 화면은 단순해지지만 계정 잠금 위험은 커집니다. 사용자가 휴대전화와 노트북에 각각 패스키를 만들거나, 동기화 패스키와 하드웨어 보안 키를 함께 등록할 수 있게 하세요. 각 항목에 ‘갤럭시에서 만든 패스키’, ‘업무용 보안 키’처럼 알아볼 수 있는 이름과 최근 사용 시각을 표시하면 삭제 실수도 줄어듭니다.

  • 등록 직후 실제 재인증 테스트를 한 번 진행합니다.
  • 비밀번호 로그인 성공 후 패스키 등록을 강요하지 않고 명확한 혜택을 설명합니다.
  • 사용자가 등록된 패스키의 이름, 생성일, 최근 사용일을 확인하고 삭제하게 합니다.
  • 계정에 패스키가 하나뿐이면 삭제 전에 대체 로그인 수단을 확인합니다.

Q4. 구현에서 가장 자주 발생하는 보안 실수는 무엇인가요?

클라이언트 성공 메시지를 인증 성공으로 믿으면 안 됩니다

질문: 브라우저가 자격 증명을 반환했다면 안전하게 인증된 것 아닌가요?

배하준: 브라우저의 성공 응답은 인증기가 작업을 수행했다는 뜻이지, 해당 응답이 현재 서버 요청에 유효하다는 최종 판정은 아닙니다. 서버는 수신한 clientDataJSON에서 challenge와 origin을 비교하고, authenticatorData의 RP ID 해시와 사용자 확인 플래그를 검사해야 합니다. assertion의 서명도 계정에 저장된 공개키로 검증해야 합니다.

challenge를 세션이나 단기 저장소에 연결하지 않거나 여러 번 재사용할 수 있게 두는 실수가 특히 위험합니다. 로그인 옵션 발급 시점에 사용자 또는 인증 시도와 challenge를 묶고, 성공과 실패 여부에 관계없이 정책에 따라 만료 처리해야 합니다. 여러 서버 인스턴스를 운영한다면 특정 인스턴스의 메모리에만 저장하지 말고 공유 저장소 또는 안전하게 검증 가능한 상태값을 사용해야 합니다.

  • origin 검사: 프로토콜과 호스트를 포함해 서버가 허용한 정확한 출처인지 확인합니다.
  • RP ID 검사: authenticatorData의 RP ID 해시가 예상 값과 일치하는지 검증합니다.
  • challenge 검사: 서버가 발급한 값과 동일하고 아직 만료·소비되지 않았는지 확인합니다.
  • 서명 검사: credential ID에 연결된 공개키와 올바른 알고리즘으로 검증합니다.
  • 사용자 확인: 민감도에 따라 userVerification을 required로 설정하고 UV 플래그를 검사합니다.
  • 세션 보호: 인증 후에도 Secure, HttpOnly, SameSite 쿠키와 세션 회전 정책을 적용합니다.

라이브러리를 사용해도 검증 책임은 남습니다

검증 로직을 직접 암호 코드로 작성하기보다 검증된 서버용 WebAuthn 라이브러리를 사용하는 편이 현실적입니다. 다만 라이브러리가 기대하는 RP ID, origin, challenge, 사용자 확인 정책을 정확히 전달하지 않으면 안전한 기본값을 기대하기 어렵습니다. 업데이트 주기, 지원 알고리즘, 오류 처리 방식과 유지보수 상태를 확인하세요.

전문가 조언: 등록과 로그인 실패를 모두 “패스키 오류”로 합치지 마세요. 사용자 취소, 시간 초과, origin 불일치, challenge 만료, 알 수 없는 credential을 내부 오류 코드로 구분해야 보안 사고와 단순 UX 문제를 빠르게 가려낼 수 있습니다.

Q5. 기기 분실과 계정 복구는 어떻게 설계해야 하나요?

복구 경로가 가장 약한 인증 수단이 되지 않게 합니다

질문: 동기화 패스키를 사용하면 계정 복구 기능은 없어도 되나요?

배하준: 동기화는 기기 교체의 불편을 크게 줄이지만 모든 상황을 해결하지는 않습니다. 사용자가 생태계를 바꾸거나 동기화 계정에 접근하지 못할 수 있고, 회사 관리 기기에서는 동기화가 제한될 수도 있습니다. 따라서 서비스 위험도에 맞는 복구 절차와 여러 패스키 등록 기능을 함께 제공해야 합니다.

이메일 링크 하나만으로 패스키를 전부 제거하고 로그인하게 만들면 공격자는 패스키가 아니라 이메일 계정만 노리게 됩니다. 금융·관리자 서비스처럼 민감도가 높은 영역은 기존 로그인 기기의 승인, 복구 코드, 추가 신원 확인, 일정 시간 보류, 보안 알림을 조합하는 편이 좋습니다. 반대로 저위험 커뮤니티에 지나치게 복잡한 절차를 적용하면 사용자는 새 계정을 만들거나 서비스를 떠날 수 있으므로 위험 기반 설계가 필요합니다.

  1. 사용자에게 최소 두 개의 패스키 또는 독립적인 복구 수단 등록을 권장합니다.
  2. 복구 코드가 있다면 일회용으로 만들고 평문 저장을 피하며 재발급 시 기존 코드를 폐기합니다.
  3. 새 기기에서 복구한 직후에는 결제 정보 변경이나 모든 세션 종료 같은 고위험 작업을 잠시 제한합니다.
  4. 패스키 추가·삭제와 계정 복구가 발생하면 기존 채널로 즉시 알림을 보냅니다.
  5. 사용자가 알 수 없는 패스키를 발견하면 해당 키와 관련 세션을 손쉽게 해지하도록 지원합니다.

패스키 삭제는 서버와 인증기 양쪽에서 상태가 어긋날 수 있다는 점도 운영팀이 알아야 합니다. 서버에서 credential을 삭제해도 사용자 기기의 패스키 목록에는 항목이 남을 수 있으며, 반대로 기기에서만 지우면 서버에는 사용할 수 없는 공개키가 유지됩니다. 로그인 실패 시 알 수 없는 credential을 브라우저에 알리는 기능과, 인증 후 서버가 인정하는 credential 목록을 동기화하는 기능은 지원 범위를 확인해 점진적으로 적용하세요.

AI 코딩 도구로 인증 기능의 초안을 빠르게 만들 수는 있지만 생성된 코드가 challenge 검증과 복구 정책까지 보장하지는 않습니다. 대화형 개발 흐름을 익히고 싶다면 혼자 공부하는 바이브 코딩 with 클로드 코드 같은 관련 서적을 참고하되, 인증 코드는 반드시 공식 사양과 라이브러리 문서에 맞춰 사람이 검토해야 합니다.

Q6. 배포 전에 어떤 항목을 반드시 테스트해야 하나요?

성공 경로보다 실패와 전환 상황을 먼저 확인합니다

질문: 개발자 노트북에서 등록과 로그인이 성공했다면 출시해도 될까요?

배하준: 패스키는 운영체제, 브라우저, 인증기와 서버가 함께 움직이는 기능이라 한 환경의 성공만으로 충분하지 않습니다. Android, iOS, macOS, Windows의 주요 브라우저를 조합하고 QR 코드 기반 교차 기기 인증, 플랫폼 인증기, 외장 보안 키를 실제로 시험해야 합니다. 지원하지 않는 환경에서는 비어 있는 화면 대신 이해하기 쉬운 대체 로그인 경로를 제공해야 합니다.

관측 지표도 등록 버튼 클릭 수만으로는 부족합니다. 옵션 발급, 브라우저 API 호출, 사용자 승인, 서버 검증, 세션 발급을 단계별 이벤트로 나눠 어느 구간에서 이탈하는지 확인하세요. 단, credential ID나 clientDataJSON 같은 인증 데이터를 분석 도구에 그대로 보내서는 안 됩니다. 오류 유형과 환경 정보도 필요한 수준으로 최소화하고 보존 기간을 정해야 합니다.

  • 새 계정과 기존 계정에서 패스키 등록이 각각 정상 작동하는지 확인합니다.
  • 사용자 취소, 화면 잠금 실패, 시간 초과가 친절한 메시지로 처리되는지 점검합니다.
  • 만료되거나 재사용된 challenge가 서버에서 거부되는지 공격 테스트를 진행합니다.
  • 잘못된 origin과 RP ID, 변조된 서명, 등록되지 않은 credential이 차단되는지 확인합니다.
  • 여러 계정과 여러 패스키를 보유한 사용자가 올바른 계정을 선택할 수 있는지 살펴봅니다.
  • 기기 분실, 패스키 삭제, 이메일 변경, 복구 완료 후 세션 정책을 검증합니다.
  • 지원하지 않는 브라우저와 자바스크립트 오류 상황에서도 비밀번호 또는 고객지원 경로가 보이는지 확인합니다.

출시 후에는 전환율과 보안 지표를 함께 봅니다

좋은 패스키 도입은 등록 수가 많은 프로젝트가 아니라 실제 로그인 성공률이 높고 계정 잠금과 복구 문의가 줄어드는 프로젝트입니다. 패스키 제안 노출 대비 등록 완료율, 패스키 선택 대비 서버 인증 성공률, 평균 로그인 시간, 복구 시작률, 복구 완료율을 함께 비교하세요.

처음에는 일부 내부 사용자와 선택형 베타 그룹에 적용하고 오류 분포를 확인한 뒤 점진적으로 확대하는 방식이 적합합니다. 여러분의 서비스에서 가장 민감한 계정은 누구이며, 그 사용자가 휴대전화를 잃어버렸을 때 어떤 절차를 거치게 될까요? 이 질문에 개발팀·보안팀·고객지원팀이 같은 답을 할 수 있다면 패스키 구현은 코드 작성을 넘어 운영 가능한 인증 시스템에 가까워진 것입니다.

패스키 로그인 구현하는 법 WebAuthn 2026 개발 가이드

댓글목록

등록된 댓글이 없습니다.