DevTool Hub
Guide

만료 시간이 이상할 때: seconds vs milliseconds 버그

JWT exp, 캐시 TTL, 예약 실행에서 초와 밀리초를 혼동해 만료 시간이 틀어지는 문제를 정리합니다.

작성자: DevTool Hub게시일: 2026-03-19업데이트: 2026-03-19읽는 시간: 약 3

목차

만료 시간이 이상할 때: seconds vs milliseconds 버그

토큰이 발급 직후 만료되거나, 캐시가 너무 오래 살아 있거나, 예약 실행 시간이 엉뚱하게 잡히는 문제는 생각보다 자주 발생합니다. 이때 가장 먼저 의심해야 할 것은 초(seconds)와 밀리초(milliseconds) 혼동입니다. 숫자 자체는 비슷해 보여도 결과 시간은 완전히 달라집니다.

1) 왜 이렇게 자주 틀리나

자바스크립트의 Date.now()는 밀리초를 반환합니다. 반면 JWT의 exp, 많은 Unix timestamp 예제, 여러 백엔드 라이브러리는 초 단위를 자주 사용합니다. 이 차이를 모르면 한 시스템의 값을 다른 시스템에 그대로 넘기는 순간 버그가 시작됩니다.

2) 대표적인 증상

  • 로그인 직후 토큰이 만료됨
  • 만료까지 하루 남았다고 생각했는데 이미 지난 상태
  • 캐시 TTL이 몇 초가 아니라 몇 밀리초로 적용됨
  • 예약 작업이 수십 년 뒤나 과거 시점으로 계산됨

이 증상은 인증, 스케줄, 세션 관리 모두에서 나타날 수 있습니다.

3) JWT에서 특히 많은 이유

JWT의 exp, iat, nbf는 보통 초 단위 epoch 값입니다. 그런데 프런트엔드 코드에서 이를 Date.now()와 직접 비교하면 밀리초와 초를 그대로 비교하게 됩니다. 그 결과 아직 유효한 토큰을 만료로 판단하거나, 반대로 만료된 토큰을 살아 있다고 볼 수 있습니다.

4) 빠른 판별 방법

대략 10자리면 초, 13자리면 밀리초일 가능성이 큽니다. 물론 예외는 있지만, 현장에서 가장 빠른 1차 판별법은 자릿수입니다. 값이 이상하게 먼 미래나 먼 과거로 보이면 거의 항상 단위 문제를 먼저 보면 됩니다.

5) 실무 예시

예를 들어 exp=1710000000인데 코드가 다음처럼 되어 있으면 문제가 납니다.

if (Date.now() > exp) {
  // 만료 처리
}

Date.now()는 밀리초, exp는 초이므로 비교 기준이 다릅니다. 이 경우 Date.now() / 1000으로 맞추거나, 반대로 exp * 1000으로 맞춰야 합니다.

6) 로그와 UI도 분리해서 봐야 한다

내부 저장은 UTC epoch인데, 화면에는 로컬 시간으로 보이는 경우도 많습니다. 여기에 초/밀리초 혼동까지 겹치면 사용자는 “시간대 문제인가?”라고 오해하기 쉽습니다. 실제로는 단위 문제와 시간대 문제가 동시에 섞여 있을 수 있으므로 따로 분리해서 봐야 합니다.

7) 예방 방법

  • API 스펙에 단위를 명시
  • 변수명에 Ms, Seconds 같은 접미어 사용
  • 테스트 데이터에 초/밀리초 케이스 모두 포함
  • 비교 전 단위를 통일

이 네 가지만 해도 대부분의 만료 버그를 예방할 수 있습니다.

8) 캐시와 예약 작업에서도 같은 문제가 난다

이 문제는 JWT에서만 생기지 않습니다. 예를 들어 캐시 TTL을 초 단위로 기대하는 라이브러리에 밀리초 값을 넣으면 캐시가 지나치게 오래 유지될 수 있습니다. 반대로 예약 작업 시각을 밀리초로 넣어야 하는 API에 초 값을 주면 이미 지난 시간으로 처리되거나 엉뚱한 시각으로 예약될 수 있습니다. 즉 인증 버그처럼 보여도 실제로는 시스템 전반의 시간 단위 문제일 수 있습니다.

9) 디버깅 습관

문제가 난 값을 그냥 숫자로 보지 말고 실제 시각으로 변환해서 비교하는 습관이 중요합니다. “이 숫자가 가리키는 시점이 언제인가”를 먼저 확인하면 초/밀리초 혼동은 바로 드러납니다. 서버 로그, 브라우저 콘솔, JWT payload를 각각 같은 기준으로 맞춰 보면 원인을 훨씬 빨리 좁힐 수 있습니다.

10) 체크리스트

  • 현재 값이 초인지 밀리초인지 문서와 자릿수로 확인했는가
  • 비교하는 두 값의 단위를 맞췄는가
  • JWT exp와 Date.now()를 직접 비교하고 있지 않은가
  • UI 시간대 문제와 단위 문제를 분리해서 확인했는가

11) 관련 도구

Unix Timestamp Converter로 실제 시각을 바로 확인할 수 있고, JWT의 exp 값은 JWT Decoder와 같이 보면 더 빠르게 점검할 수 있습니다. 만료 문제는 복잡해 보여도 대부분 단위 확인부터 시작하는 것이 맞습니다.

Author

운영 및 검수 정보

이 문서는 DevTool Hub에서 작성하고 유지 보수합니다. 실무에서 자주 발생하는 문제를 기준으로 정리하며, 잘못된 설명이나 오래된 내용은 검토 후 수정합니다.

운영 정책은 Editorial Policy에서 확인할 수 있고, 수정 제보는 Contact로 받을 수 있습니다.

관련 도구

다음 읽을 글

Feedback
내용 개선이나 오류 제보는 Contact로 알려주세요.