ToolPal
화면에 보안 잠금 아이콘이 표시된 디지털 보안 개념

온라인 JWT 인코더: 라이브러리 없이 브라우저에서 토큰 만들기

📷 Pixabay / Pexels

온라인 JWT 인코더: 라이브러리 없이 브라우저에서 토큰 만들기

테스트, 디버깅, 인증 모킹을 위해 브라우저에서 바로 JWT를 서명하고 생성하는 방법 — 실제 시크릿을 남의 서버에 붙여넣지 않고도.

D작성: Daniel Park2026년 4월 25일7분 소요

개발자라면 누구나 JWT를 처음 접하는 순간이 있습니다. 인증을 구현해야 할 때, 누군가가 JWT를 써보라고 권유하죠. RFC를 읽고, base64로 디코딩된 페이로드를 보면서 "어, 그냥 JSON이네"라고 생각합니다. 그리고 서명 부분이 대체 뭘 하는 건지, 왜 필요한지 이해하는 데 한 시간쯤 쓰게 됩니다.

혼란스러운 건 당연합니다. JWT는 구조는 단순한데 보안 함의는 은근히 복잡합니다. 이 글은 실용적인 부분에 집중합니다. 테스트와 디버깅에 JWT를 직접 만들고 활용하는 방법, 그리고 ToolBox Hubs의 JWT 인코더로 라이브러리 설치나 서버 없이 그걸 해내는 방법을요.

JWT가 실제로 뭔가

JSON Web Token은 점(.)으로 구분된 세 개의 base64url 인코딩 문자열입니다. 헤더.페이로드.서명 구조입니다.

헤더는 토큰 유형과 서명 알고리즘을 식별합니다.

{
  "alg": "HS256",
  "typ": "JWT"
}

페이로드는 클레임을 담습니다. 본질적으로 정보를 담은 키-값 쌍들입니다.

{
  "sub": "user_12345",
  "email": "alice@example.com",
  "role": "admin",
  "iat": 1714000000,
  "exp": 1714086400
}

서명은 인코딩된 헤더와 페이로드를 시크릿 키로 해싱한 암호학적 해시값입니다. 토큰이 변조되지 않았음을 증명합니다. 페이로드에서 문자 하나라도 바꾸면 서명이 맞지 않게 됩니다.

많은 사람이 헷갈리는 부분이 있습니다. 페이로드는 암호화된 게 아닙니다. base64url로 인코딩된 것뿐이라 토큰을 가진 사람이라면 누구나 즉시 디코딩해서 읽을 수 있습니다. 서명은 변조되지 않았음을 증명하지만, 내용을 숨기지는 않습니다. 이게 JWT에 뭘 담을지 결정할 때 핵심적인 고려사항입니다.

실제로 쓰는 클레임들

JWT 스펙에는 라이브러리가 자동으로 검증하는 방법을 아는 "등록된 클레임"이 있습니다.

sub (subject) — 토큰의 주체. 보통 사용자 ID나 계정 식별자입니다. 안정적이고 고유해야 합니다. 흔한 실수: 이메일 주소를 여기 넣는 것. 이메일은 바뀝니다. 불투명한 ID는 바뀌지 않습니다.

iat (issued at) — 토큰이 발급된 시각의 유닉스 타임스탬프입니다. 디버깅에 유용하고, 일부 검증 로직은 이 값을 확인해 미래에서 온 것처럼 보이는 토큰을 거부합니다(클락 스큐 공격 방지).

exp (expiration) — 이 시각 이후에는 토큰을 거부해야 하는 유닉스 타임스탬프입니다. 중요합니다. exp가 없는 JWT는 영원히 유효합니다. 토큰이 유출되면 서명 키를 교체하기 전까지는 방법이 없는데, 그러면 기존 토큰이 모두 무효화되어 전체 로그아웃이 됩니다. 단기 세션은 15-60분, 리프레시 토큰은 몇 시간에서 며칠이 일반적입니다. 항상 설정하세요.

iss (issuer) — 토큰을 발급한 주체를 식별하는 문자열입니다. 멀티 서비스 환경에서 올바른 소스의 토큰을 검증하는지 확인하는 데 유용합니다.

aud (audience) — 토큰의 대상. 서비스 A를 위해 발급된 토큰이 서비스 B에 사용되는 걸 막습니다.

커스텀 클레임은 자유롭게 추가해도 됩니다. role, plan, org_id 같은 것들을 요청마다 DB를 조회하지 않기 위해 토큰에 넣는 건 흔한 패턴입니다. 다만 기억하세요. 누구나 읽을 수 있습니다.

온라인 JWT 인코더를 실제로 쓰는 경우

솔직히 말하면: 프로덕션에는 아닙니다. 프로덕션에서는 인증 서버가 서명을 처리하고, 시크릿은 서버 환경을 절대 벗어나지 않습니다.

온라인 인코더가 진짜 유용한 상황들:

인증 서버 없이 미들웨어 테스트. JWT를 검증하는 백엔드 엔드포인트를 만들고 있는데, Postman이나 curl에 붙여넣을 유효한 토큰이 필요합니다. 온라인 인코더로 몇 초 만에 해결됩니다.

로컬 개발에서 인증 모킹. 프론트엔드가 인증이 필요한 API에 붙어야 하는데 로컬에 인증 서비스가 아직 없을 때. 테스트 시크릿으로 토큰 하나 생성해서 개발 환경에 박아두면 됩니다. 배포할 코드가 아닙니다. 로컬 개발을 막히지 않게 하는 겁니다.

토큰 검증 실패 디버깅. 서버가 토큰을 거부하는데 이유를 모를 때. exp가 이미 지났나? iss가 틀렸나? 페이로드가 잘못됐나? 인코더로 정상 토큰을 만들어 비교하고, JWT 디코더로 문제 토큰을 분해해 보면 됩니다.

JWT 동작 이해. 라이브러리가 JWT로 뭘 하는지 이해하는 가장 좋은 방법은 직접 만들어 보는 겁니다. 만료를 바꿔보고, 알고리즘을 변경하고, 뭐가 깨지는지 보세요. 코드 없이 바로 실험할 수 있습니다.

HS256 서명 동작 원리 (수식 없이)

HS256은 HMAC-SHA256의 줄임말입니다. HMAC은 해시 함수(여기선 SHA-256)와 시크릿 키를 함께 사용해 메시지 인증 코드를 생성하는 구조입니다.

평범한 말로: 인코딩된 헤더에 점을 붙이고 인코딩된 페이로드를 붙입니다. 그 문자열과 시크릿 키를 HMAC-SHA256 함수에 넣으면 고정 길이의 해시가 나옵니다. 그걸 base64url로 인코딩해서 토큰의 세 번째 부분으로 붙입니다.

왜 이게 작동하나요? HMAC은 시크릿 키 없이는 주어진 메시지에 대한 유효한 해시를 만들 수 없도록 설계되었습니다. 누군가 페이로드를 수정하면, 서명을 맞게 재계산할 수 없습니다. 시크릿이 없으니까요. 서버가 JWT를 검증할 때는 수신한 헤더와 페이로드로 같은 HMAC-SHA256 계산을 다시 실행하고, 결과를 토큰의 서명과 비교해서 수락 또는 거부합니다.

ToolBox Hubs 인코더는 브라우저 내장 Web Crypto API로 이 계산을 합니다. TLS에 사용되는 것과 같은 암호학적 기본 요소입니다. 직접 구현한 JavaScript나 출처 불명의 서드파티 라이브러리를 쓰는 게 아닙니다.

HS256의 한계

HS256은 대칭 키를 사용합니다. 토큰을 서명하는 시크릿과 검증하는 시크릿이 동일합니다. 즉, 토큰을 검증할 수 있는 쪽은 토큰을 만들 수도 있습니다. 한 서버가 토큰을 발급하고 다른 서버가 검증하는 시스템에서는 두 서버 모두 시크릿을 알아야 합니다. 서비스 간 시크릿 공유는 조율과 보안 표면 문제입니다.

RS256(과 ES256)은 비대칭 키를 씁니다. 비공개키는 토큰에 서명합니다. 인증 서버만 갖고 있으면 되고 절대 외부로 나가지 않습니다. 공개키는 토큰을 검증합니다. 자유롭게 배포할 수 있고, JWKS 엔드포인트에 공개하면 검증이 필요한 어떤 서비스든 로드할 수 있습니다.

여러 서비스가 관여하는 아키텍처라면 대개 RS256이 더 나은 선택입니다. HS256은 설정이 단순하고, 모든 검증자를 직접 통제하는 소규모 시스템이나 단일 백엔드 서비스에는 충분합니다.

보안 관련 핵심 사항

JWT에 민감한 데이터를 넣지 마세요. 비밀번호 해시, 신용카드 번호, 불필요한 개인정보는 절대 안 됩니다. 페이로드는 토큰을 가진 누구에게나 보입니다. 클라이언트, 인증 헤더를 캡처하는 로그 시스템, 중간의 프록시와 CDN 모두 포함해서요. JWT 페이로드는 URL 쿼리 스트링처럼 취급하세요. 누구나 볼 수 있다고 가정하세요.

온라인 도구에는 테스트 시크릿만. 도구가 정말 클라이언트 사이드이고 데이터를 어디에도 보내지 않더라도, 프로덕션 시크릿을 브라우저 UI에 입력하는 습관은 나쁩니다. 테스트용 시크릿을 만드세요. test-secret-do-not-use-in-production 같은 걸 쓰면 됩니다. 실제 시크릿은 비밀번호처럼 취급하세요. 그것이 사는 서버를 절대 벗어나지 않아야 합니다.

만료는 항상 설정하세요. exp 없는 JWT는 영원한 자격증명입니다. 유출되면 서명 키를 교체하기 전까지 방법이 없습니다.

알고리즘 혼동 공격은 실제 존재합니다. 일부 JWT 라이브러리에는 alg 헤더를 none으로 바꾸면 서명 없는 토큰을 수락하는 취약점이 있었습니다. 서버가 기대하는 알고리즘을 항상 검증하고, 그 외의 것은 거부하세요. 토큰의 alg 헤더를 그대로 신뢰하지 마세요.

ToolBox Hubs vs. jwt.io

jwt.io는 표준적인 JWT 도구고 대부분의 개발자가 알고 있습니다. 좋은 도구입니다. 그래도 ToolBox Hubs를 선호할 이유가 두 가지 있습니다.

첫째, ToolBox Hubs는 명시적으로 프라이버시 우선, 클라이언트 사이드 전용입니다. jwt.io는 입력한 시크릿이 로깅될 수 있는지에 대한 우려를 받아온 적이 있습니다. jwt.io가 악의적이라는 게 아닙니다. 도구의 프라이버시 모델이 명확하지 않을 때 위험 계산이 달라진다는 겁니다. 저희 도구는 브라우저에서만 처리합니다.

둘째, 관련 도구들이 연결되어 있습니다. JWT를 인코딩한 뒤 바로 JWT 디코더로 이동해 검사하거나, 페이로드의 값을 해싱해야 할 때 해시 생성기로, JWT 페이로드에 평문으로 담으면 안 되는 내용을 암호화할 때 텍스트 암호화/복호화로 이동할 수 있습니다.

다만 솔직히 말하면, jwt.io는 저희에게 없는 기능들이 있습니다. 라이브러리 선택, 키 쌍 생성과 함께하는 RS256 지원 등이요. 필요에 맞는 도구를 쓰세요.

로컬 개발에서의 실용적인 워크플로

실제 개발 중에 JWT 인코더를 쓰는 방식입니다.

  1. 토큰에 필요한 클레임을 결정합니다. 보통 sub, exp, 그리고 미들웨어가 확인하는 앱 특화 클레임(예: role, org_id)입니다.

  2. 디버깅 세션 중에 만료되지 않을 만큼 충분히 먼 exp를 설정합니다. 현재 유닉스 타임스탬프에 86400(24시간)을 더하면 됩니다. 계산이 귀찮으면 타임스탬프 변환기를 씁니다.

  3. 기억하기 쉬운 테스트 시크릿을 입력합니다. dev-secret-not-real 같이 명백히 가짜인 걸로요.

  4. 토큰을 생성하고 Postman, curl 등 API 클라이언트에 붙여넣습니다.

  5. 검증에 문제가 생기면 토큰을 JWT 디코더에 붙여 페이로드가 맞는지 확인하고, 서버의 기대 시크릿과 알고리즘이 생성 시 사용한 것과 일치하는지 확인합니다.

이 루프가 JWT 관련 디버깅 혼란의 90%를 해결합니다. 나머지 10%는 보통 클락 스큐(exp 계산이 틀림)나 알고리즘 불일치(HS256으로 생성했는데 서버가 RS256을 기대함)입니다.

이 도구가 못 하는 것들

솔직하게 한계를 말씀드립니다.

RS256, ES256 미지원. 비대칭 키 서명은 지원하지 않습니다. 브라우저 UI에서 비공개 키를 처리하면 복잡성이 크게 늘어납니다. RS256 테스트에는 로컬에서 jsonwebtoken npm 패키지나 python-jose 라이브러리가 더 적합합니다.

토큰 폐기 없음. JWT는 설계상 상태가 없습니다. 발급되면 만료될 때까지 유효합니다. 특정 토큰을 만료 전에 무효화해야 한다면, 서버에 토큰 차단 목록이 필요합니다. 인코더가 해줄 수 있는 게 아닙니다.

JWKS 생성 없음. RS256 기반 시스템에는 JWKS 엔드포인트도 필요한데, 이 도구의 범위를 벗어납니다.

범위 안에 있는 것들 — HS256 서명 토큰 생성, JWT 구조 이해, 로컬 개발에서 인증 모킹 — 에서는 JWT 인코더가 군더더기 없이 제 역할을 합니다.

시작하기

JWT 인코더를 열고, {"sub": "test-user", "role": "admin"} 같은 간단한 페이로드를 입력하고, 테스트 시크릿을 넣고, 생성을 누르세요. 출력을 보세요. 그 다음 JWT 디코더에 붙여넣고 분해되는 걸 보세요.

한 번 해보면 JWT 구조가 더 이상 추상적이지 않게 됩니다. 세 부분이 뭔지, base64url로 인코딩된 JSON이 어떻게 생겼는지, 서명이 단순히 해시값이라는 걸 알게 됩니다. 라이브러리 연동, 알고리즘 선택, 클레임 검증은 모두 그 위에 쌓이는 것들입니다.

함께 열어두면 좋은 관련 도구들: 토큰 검사에 JWT 디코더, HMAC이 뭘 만들어내는지 이해하려면 해시 생성기, base64 인코딩된 평문으로는 부족한 경우에 텍스트 암호화/복호화.

자주 묻는 질문

D

작성자

Daniel Park

서울에서 활동하는 시니어 프런트엔드 엔지니어. 국내 SaaS 회사들에서 7년간 웹 애플리케이션을 개발하며 개발자 도구, 웹 성능 최적화, 프라이버시 중심 설계에 집중해 왔습니다. JavaScript 생태계 오픈소스 기여자이자 ToolPal 창립자입니다.

더 알아보기

이 글 공유하기

XLinkedIn

관련 글