JWT 토큰 안에는 무엇이 들어 있나
웹 서비스에 로그인하면 서버가 eyJhbGciOi...로 시작하는 긴 문자열을
돌려주는 경우가 많습니다. JWT(JSON Web Token)입니다. 겉보기엔 암호문 같지만,
사실 누구나 열어 볼 수 있는 투명한 봉투에 가깝습니다. 구조를 알면
«무엇을 믿어도 되고 무엇을 믿으면 안 되는지»가 분명해집니다.
점 두 개로 나뉜 세 부분
JWT는 헤더.페이로드.서명 — 점(.)으로 이은 세 덩어리입니다.
헤더와 페이로드는 JSON을 base64url로 인코딩한 것일 뿐 암호화가 아니라서,
토큰을 가진 사람이라면 누구든 내용을 읽을 수 있습니다.
- 헤더 — 서명에 쓴 알고리즘(
alg) 등 토큰 자체의 정보. - 페이로드 — 실제 내용. 사용자 식별자(
sub), 발급 시각(iat), 만료 시각(exp), 권한 범위(scope) 같은 «클레임»이 담깁니다. - 서명 — 앞 두 부분을 비밀키로 서명한 값. 여기가 JWT의 존재 이유입니다.
서명은 «숨기는» 게 아니라 «위조를 막는» 것
서명은 내용을 가리지 않습니다. 대신 내용이 한 글자라도 바뀌면 서명이 맞지 않게
됩니다. 서버는 자기만 아는 비밀키로 서명을 다시 계산해서, 토큰이 정말 자기가 발급한
그대로인지 확인합니다. 그래서 사용자가 페이로드의 "role": "user"를
"admin"으로 고쳐 봐야 서명 검증에서 걸립니다 — 비밀키 없이는
유효한 서명을 만들 수 없기 때문입니다.
거꾸로 말하면, 서명을 검증하지 않고 페이로드를 믿는 서버는 뚫린 것과 같습니다.
실제로 헤더의 alg 값을 none으로 바꾼 무서명 토큰을
받아 주던 라이브러리 구현이 과거에 여럿 발견되어, 지금은 «서버가 허용할 알고리즘을
목록으로 못박아라»가 표준 권고(RFC 8725)로 자리 잡았습니다.
개발할 때 지킬 것 세 가지
- 민감정보를 넣지 않는다 — 페이로드는 공개나 다름없습니다. 비밀번호·주민번호· 전화번호를 넣으면 토큰이 새는 순간 그대로 유출입니다. (내용까지 암호화하는 JWE라는 별도 규격이 있지만, 흔히 쓰는 JWT는 서명만 하는 JWS 방식입니다.)
- 만료를 짧게 잡는다 — JWT는 서버에 세션을 남기지 않는 방식이라, 한번 발급한
토큰을 서버가 도중에 무효화하기 어렵습니다.
exp를 짧게 두고 리프레시 토큰으로 갱신하는 구조가 일반적입니다. - 검증은 서버에서, 항상 — 클라이언트에서 디코딩해 보는 건 «읽기»일 뿐입니다. 신뢰 판단은 비밀키를 가진 서버의 서명 검증으로만 합니다.
직접 열어 보기
갖고 있는 토큰이 언제 만료되는지, 어떤 클레임이 들어 있는지는 JWT 디코더로 바로 확인할 수 있습니다. 디코딩은 브라우저 안에서만 이루어지고 토큰이 서버로 전송되지 않으며, 서명 검증은 하지 않으므로 진위 판단이 아니라 «내용 확인» 용도로만 쓰세요. 페이로드가 base64url이라는 게 어떤 의미인지는 Base64는 암호화가 아닙니다에서 이어집니다.
참고·출처
최종 검토: 2026-09-01