First Read

가장 많이 틀리는 건 숫자가 아니라 해석 순서

exp

이 시각 이후에는 토큰을 거부해야 한다는 뜻입니다. 문제는 서버 시간, 프록시 시간, 사용자의 로컬 시간이 모두 다를 수 있다는 점입니다.

nbf

이 시각 이전에는 토큰을 아직 쓰면 안 된다는 의미입니다. 발급 직후 호출에서 바로 실패하는 상황은 이 값과 clock skew를 먼저 의심해야 합니다.

iat

언제 발급되었는지를 뜻하지만, 검증에 직접 쓰이지 않는 경우도 많습니다. 다만 디버깅할 때는 세 클레임을 같이 봐야 흐름이 맞습니다.

Common Failures

실제 장애에서 자주 보이는 패턴

초와 밀리초를 섞어 읽음

JWT는 보통 Unix 초 단위를 쓰는데, 프런트엔드 코드나 로그 뷰어가 밀리초로 착각하면 시간이 완전히 다르게 보입니다.

검증보다 디코딩만 함

내용을 읽을 수 있다고 해서 유효한 토큰은 아닙니다. 외부 issuer 환경이라면 JWKS 기반 서명 검증이 별도로 필요합니다.

환경 시간 차이를 무시함

애플리케이션 서버와 인증 서버의 시간이 몇 초만 달라도 경계 구간에서 실패가 반복될 수 있습니다. 운영 문서에 허용 clock skew 기준을 적어두는 편이 좋습니다.

Workflow

이 사이트에서 바로 같이 볼 페이지

  1. JWT 디코더에서 헤더와 페이로드를 먼저 확인합니다.
  2. 타임스탬프 변환기exp, nbf, iat를 사람이 읽는 시각으로 다시 봅니다.
  3. 응답 전체 흐름을 재현해야 하면 API 요청 테스트를 같이 열어 요청과 응답을 함께 봅니다.

Examples

실제 입력과 결과

만료 판정에 쓰이는 클레임

입력

{
  "sub": "user-123",
  "iat": 1767225600,
  "nbf": 1767225600,
  "exp": 1767229200
}

결과

iat 발급 시각  2026-01-01 00:00:00 UTC
nbf 유효 시작  2026-01-01 00:00:00 UTC
exp 만료      2026-01-01 01:00:00 UTC
유효 기간 1시간

세 값 모두 초 단위 epoch입니다. 밀리초를 넣으면 수만 년 후로 해석되어 만료 검사가 무력화됩니다.

nbf가 미래인 토큰

입력

현재 1767225600 · nbf 1767229200

결과

아직 사용할 수 없음 (1시간 뒤부터 유효)

Troubleshooting

자주 만나는 오류

유효한 토큰인데 만료로 거부될 때

서버 시계가 어긋난 경우가 가장 흔합니다. 발급 서버가 조금 빠르면 받는 쪽 기준으로 nbf가 아직 미래입니다. 대부분의 라이브러리가 clock skew 허용값(보통 30~60초)을 제공하니 그것을 먼저 확인하세요.

exp를 밀리초로 넣었을 때

JWT 표준(RFC 7519)의 시간 클레임은 초 단위입니다. Date.now()를 그대로 넣으면 1000배가 되어 사실상 만료되지 않는 토큰이 발급됩니다. 보안 사고로 이어지는 실수라 발급 코드를 먼저 확인하세요.

디코딩됐다고 검증된 것은 아닙니다

JWT의 헤더와 페이로드는 Base64URL 인코딩일 뿐 암호화가 아닙니다. 누구나 읽을 수 있고 내용을 바꿔 다시 인코딩할 수도 있습니다. 서명 검증을 통과해야 신뢰할 수 있으며, 페이로드에 비밀 값을 담아서는 안 됩니다.