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시간 후 자동 만료, 갱신권은 한 번 쓰면 새 걸로 교체."
관련¶
- SHA-256 token storage — refresh 를 DB 에 안전하게 저장하는 방법
- Refresh Token Rotation — refresh 탈취 위험 최소화
- JWT stateless vs Refresh stateful — 두 토큰의 본질적 차이