“공개키, 어디에 뒀더라?”

JWT 서명 검증에 RSA 같은 공개키 방식을 쓸 때는 항상 같은 벽에 부딪힙니다. “공개키는 어떻게 배포하는 게 안전할까?”, “키를 교체하면 모든 서버 설정을 다시 해야 하나?”

이 고민을 해결하는 것이 **JWKS(JSON Web Key Set)**입니다. JWKS 생성 도구는 브라우저 안에서 RSA 키 페어를 생성해 JWKS 형식(공개키)과 PEM 형식(비밀키)을 그 자리에서 확인할 수 있게 해줍니다.

JWKS(JSON Web Key Set)란 무엇인가?

JWKS: 공개키의 “쇼케이스”

JWKS는 “JSON 형식으로 쓰인 키의 집합”입니다. 인증 서버(Auth0, Cognito 등)가 특정 URL—보통 /.well-known/jwks.json—에 이 JSON을 공개해 두면, 토큰을 검증해야 하는 API 서버가 그곳에서 가져옵니다.

JWKS가 편리한 이유

  1. 자동 로테이션 — 키를 교체해도 엔드포인트 뒤의 내용만 바꾸면 됩니다. API 서버는 URL을 조회하는 것만으로 최신 키를 얻습니다.
  2. 여러 키의 병행 관리 — “오래된” 키와 “새” 키가 공존할 수 있어 전환 기간이 매끄럽습니다.
  3. 세계 표준 — OAuth 2.0과 OIDC에서 널리 채택되어, 대부분의 라이브러리가 기본으로 지원합니다.

JWKS 내부: 각 필드의 의미

{
  "keys": [
    {
      "kty": "RSA",
      "n": "0vx7agoebGcQ...",
      "e": "AQAB",
      "kid": "f47ac10b-...",
      "use": "sig",
      "alg": "RS256",
      "key_ops": ["verify"]
    }
  ]
}
필드역할
kty키 종류(RSA 등)
n / eRSA 공개키 본체(모듈러스와 공개 지수)
kid키 식별자. JWT 헤더와 대조해 어느 키로 검증할지 선택하는, 키 로테이션의 핵심
use용도. 서명 검증용이면 sig(암호화용은 enc)
alg / key_ops알고리즘과 허용 연산을 선언. 검증 측의 오용 방지

keys는 배열이므로 로테이션 중에는 신구 키가 나란히 존재하며, JWT 헤더의 kid로 구분됩니다.

브라우저에서 키 페어 생성하기

JWKS 생성 도구jose 라이브러리와 Web Crypto API를 조합해 RSA 2048bit(RS256 서명용) 키 페어를 그 자리에서 생성합니다.

  • 공개키(JWKS 형식)/.well-known/jwks.json의 모의 데이터로 사용 가능
  • 비밀키(PEM 형식) — JWT 서명 생성에 사용 가능
  • kid를 지정하지 않으면 무작위 ID가 자동 발급됩니다

생성은 모두 브라우저 안에서 완결되므로 비밀키가 인터넷에 노출될 일이 없습니다. 로컬에서 자체 인증 서버(모의)를 구축하거나 JWT 검증 로직의 단위 테스트에 적합합니다.

JWT 서명 검증에서 JWKS가 쓰이는 흐름

  1. 인증 서버가 JWT를 발급한다
  2. JWT 헤더에는 서명에 사용한 키를 나타내는 kid가 들어간다
  3. API 서버는 JWKS 엔드포인트에서 공개키 목록을 가져온다
  4. kid가 일치하는 공개키를 선택한다
  5. 그 공개키로 JWT의 서명을 검증한다

이 구조 덕분에 API 서버는 비밀키를 가질 필요가 없습니다. 비밀키는 인증 서버 쪽에만 두고, 검증 측은 공개키만 사용하는—역할이 깔끔하게 분리됩니다. JWT의 페이로드 자체는 Base64URL로 인코딩되어 있을 뿐 암호화되어 있지 않다는 점은, JWT 디코드 도구로 실제 토큰을 확인해보면 쉽게 이해됩니다.

JWKS를 다룰 때 확인할 점

  • JWT 헤더의 kid와 JWKS 안의 kid가 일치하는가
  • alg가 예상한 서명 알고리즘인가
  • JWKS 취득 결과를 적절히 캐싱하고 있는가
  • 키 로테이션 시 신구 키를 일시적으로 나란히 두었는가
  • 폐기된 키를 언제 삭제할지 정했는가

특히 키 로테이션 중에는 새 키로 발급된 JWT와 기존 키로 발급된 JWT가 동시에 존재하는 기간이 있습니다. 그 기간에는 JWKS에 공개키 두 개를 모두 올려서 어느 쪽 JWT도 검증할 수 있는 상태로 두는 것이 일반적입니다.

자주 묻는 질문

JWKS에 비밀키를 넣어도 되나요?

안 됩니다. JWKS로 외부에 공개하는 것은 서명 검증용 공개키입니다. 비밀키는 JWT를 발급하는 쪽만 보유해야 하며, 브라우저나 API 이용자에게 노출되는 곳에 두면 안 됩니다.

kid는 필수인가요?

여러 키를 다루는 운영에서는 매우 중요합니다. JWT 헤더의 kid와 JWKS 안의 kid를 대조함으로써 검증 측이 어떤 공개키를 써야 할지 판단할 수 있습니다. 키 로테이션을 고려한다면 처음부터 kid를 붙여두는 것을 추천합니다.

로컬 개발용 JWKS는 어떻게 만들면 되나요?

JWKS 생성 도구로 테스트용 키 페어를 생성하고, 공개키 쪽을 JWKS로 사용하면 됩니다. 프로덕션 비밀키를 붙여넣거나 공유하지 말고, 개발용과 프로덕션용 키를 분리해 관리하세요.

생성한 키를 그대로 프로덕션에 써도 되나요?

권장하지 않습니다. 이 도구의 용도는 개발·테스트·학습입니다. 생성 자체는 브라우저 안에서 완결되어 키가 외부로 유출되지 않지만, 프로덕션 서명 키는 HSM이나 KMS 같은 관리된 환경에서 생성·보관해야 합니다.

정리

  • JWKS는 공개키를 JSON 형식으로 배포하는 구조. kid가 키 로테이션의 핵심
  • use/alg/key_ops는 오용 방지를 위한 선언
  • 검증 측은 비밀키를 가질 필요 없이, JWKS에서 가져온 공개키만으로 서명을 검증할 수 있다
  • 로테이션 중에는 신구 키가 JWKS 안에 함께 존재한다

OpenSSL 옵션을 매번 떠올릴 필요 없이, 바로 이 자리에서 필요한 키를 생성해보세요.