콘텐츠로 이동

JWT vs Refresh Token — 왜 토큰을 두 개로 쪼갰나

한 줄 요약: 토큰 수명은 보안과 UX 가 정반대 방향으로 끌어당기는 trade-off. 한 토큰으로는 양쪽을 다 잡을 수 없어서, 자주 쓰이는 짧은 토큰 (access) + 거의 안 쓰이는 긴 토큰 (refresh) 두 개로 쪼갠다.

문제 — 한 토큰의 어정쩡한 절충

토큰 수명을 정할 때 보안과 UX 가 정반대 방향으로 끌어당긴다:

토큰 수명 보안 UX
15분 좋음 (탈취돼도 15분만 위험) 나쁨 (자주 재로그인)
24h ← 흔한 어정쩡한 절충 나쁨 (탈취 시 24h 무방비) 그저 그럼 (하루마다 재로그인)
7일 매우 나쁨 (일주일 무방비) 좋음

어느 수명을 잡아도 한 측면은 희생. 어정쩡한 24h 는 양쪽 다 어정쩡함.

해법 — 토큰을 두 개로 쪼개기

로그인 시:
  Access Token  (1시간, 매 요청에 첨부)
  Refresh Token (2주, access 갱신 전용 — 거의 안 쓰임)

[1시간 후 access 만료]
  클라이언트가 자동으로 refresh 호출 → 새 access 받음
  → 사용자는 갱신 사실도 모르고 2주간 로그인 유지

[2주 후 refresh 만료]
  → 그 때만 재로그인

양쪽이 동시에 잡히는 이유

측면 어떻게 잡혔나
보안 Access 가 1시간 — 탈취돼도 최대 1시간만 위험. 1시간 후 자동 무효
UX Refresh 가 2주 — 사용자는 백그라운드 자동 갱신만 일어남, 재로그인 부담 X

핵심 원리: 자주 쓰이는 건 짧게, 거의 안 쓰이는 건 길게.

Access 는 모든 API 요청에 첨부되어 노출 위험이 크니까 수명 짧음, Refresh 는 1시간에 한 번만 호출되어 노출 면이 작으니까 길게.

FAQ

Q: 그냥 access 를 1시간으로 짧게 하면 안 되나? → 그러면 매시간 사용자가 재로그인 해야 함 (UX 폭망). Refresh 가 "1시간마다 자동 재로그인" 의 자동화 도구.

Q: 그냥 토큰 한 개를 2주로 길게 하면 안 되나? → 그러면 토큰 한 번 탈취 시 2주 동안 무방비. Access 를 따로 두는 게 "토큰을 자주 갈아치우는" 보안 효과.

Q: 둘 다 훔치면? → Access 는 1시간 후 만료. Refresh 는 Rotation 으로 한 번만 유효. 동시 탈취해도 노출 창 최소화.

발표 시 한 줄 비유

"24시간짜리 출입증 한 장 대신, 1시간짜리 출입증 + 2주짜리 갱신권 두 장. 출입증을 훔쳐도 1시간 후 자동 만료, 갱신권은 한 번 쓰면 새 걸로 교체."

관련