codingstairs
노트에듀라이프연락
⌕검색⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

연락하기

로그인 없이도 보낼 수 있어요. 답변이 필요하면 이메일을 함께 적어 주세요.

  • 익명 폼으로 의견 남기기 →
  • ✉ warragon112@gmail.com
  • 카카오톡 오픈채팅 ↗

© 2026 codingstairs

  • 노트
  • 에듀
  • 검색
  • 라이프
  • 연락
  • 약관
  • RSS
  • GitHub
노트›security

JWT 와 토큰 회전

2026-04-28 게시· 2026-05-18 갱신·0회 조회

JWT 와 토큰 회전

JWT 는 가벼운 클레임 전달 수단이지만, 그 자체로 인증 시스템의 모든 답을 주지는 않습니다. 짧은 액세스 토큰 · 긴 리프레시 토큰 패턴 · 무효화 전략 · 알고리즘 선택 · 잘 알려진 함정 (alg:none) 을 정리합니다.

1. JWT 에 대한 이야기

JWT (JSON Web Token, RFC 7519, 2015) 는 세 부분:

header . payload . signature
  • header — 알고리즘 · 토큰 타입 ({"alg":"HS256","typ":"JWT"}).
  • payload — 클레임 (sub · exp · iat · iss · aud · 사용자 정의).
  • signature — 헤더 + 페이로드를 서명. HMAC 또는 비대칭 서명.

각 부분은 base64url 인코딩, 서명은 base64url 디코딩된 값이 아닌 인코딩된 문자열을 입력으로 합니다.

표준 클레임:

클레임 의미
iss 발급자
sub 주체 (사용자 ID)
aud 수신자
exp 만료 시각 (Unix epoch)
nbf not-before
iat 발급 시각
jti 토큰 고유 ID

2. 알고리즘

알고리즘 종류 메모
HS256 / HS384 / HS512 HMAC + SHA-2 대칭 키. 발급자 · 검증자가 같은 비밀 공유.
RS256 / RS384 / RS512 RSA + SHA-2 비대칭. 비공개 키로 서명, 공개 키로 검증. 길이 권장 2048+.
ES256 / ES384 / ES512 ECDSA 비대칭. 작은 서명 크기. 곡선마다 매개변수가 다름.
EdDSA (Ed25519) Edwards 곡선 서명 빠르고 결정적. RFC 8037.

선택 기준:

  • 서비스 내부 한 곳에서 발급 · 검증 — HS256 으로 충분한 자리가 많음.
  • 다른 서비스가 검증해야 함 (분산) — 비대칭 (RSA · EC · Ed25519). 검증자에게 공개 키만 배포.
  • OIDC IdP 통합 — 보통 RS256 또는 ES256 가 표준.

3. Access · Refresh 분리

JWT 만으로 세션 관리를 다루면 두 요구가 충돌:

  • 장기 세션 — 사용자가 매번 로그인하지 않아도 되는 자리.
  • 짧은 만료 — 토큰 탈취 시 영향 범위 최소화.

해법으로 access · refresh 토큰 분리:

  • Access Token — 짧은 TTL (5~15 분). 자원 호출에 동반. 만료 후 폐기.
  • Refresh Token — 긴 TTL (7~30 일). access 만료 시 새 access 발급용. 보관 위치 (httpOnly 쿠키 · 안전한 저장소) 가 중요.

4. Refresh Token Rotation

리프레시 토큰을 한 번 쓰면 새 리프레시 토큰을 받고 옛 것은 무효화. 탈취된 토큰이 한 번 쓰이는 순간 옛 사용자의 다음 회전이 실패하면서 사고를 감지할 수 있음.

서버는 refresh 토큰의 jti 와 사용자 ID 를 Redis 또는 DB 에 기록:

on refresh:
  if redis.get("rt:" + jti) != "valid":
    revoke all sessions for user
    return 401
  redis.del("rt:" + jti)
  new_rt = issue_new()
  redis.set("rt:" + new_rt.jti, "valid", ttl=30d)
  return new_access, new_rt

옛 jti 를 다시 보면 "재사용 감지" 로 간주해 그 사용자의 모든 세션을 끊습니다.

5. 무효화 전략

JWT 의 무상태성은 강점이지만 무효화가 어려운 자리.

Block-list (Deny-list) — 무효화된 토큰의 jti 를 짧은 TTL 로 Redis 에 기록. 검증 단계에서 block-list 확인. 액세스 토큰의 TTL 만큼만 보관.

key = "bl:jwt:" + jti
ttl = exp - now + clock_skew

장점 — 단순. 한계 — 호출마다 외부 조회.

Allow-list — 발급된 모든 토큰을 추적하고 매 호출 시 확인. 강한 통제, 그러나 무상태 JWT 의 의미가 약해짐. 사실상 세션 토큰에 가까워짐.

Short TTL + Refresh Rotation — 가장 흔한 절충. 액세스 토큰 자체에는 무효화 메커니즘 없이 짧은 TTL 로 위험 창 축소, 리프레시는 회전 · 재사용 감지로.

Clock skew — exp 검증 시 서버 · 발급자의 시계 차이 흡수. 보통 30~60 초 마진. 너무 크면 만료 후 사용 가능 창이 길어짐.

6. alg:none 과 BCP

JWT 명세는 alg:none 을 정의하지만, 이 값은 검증 우회의 출발점 (JWT none-알고리즘 취약점, 2015 년 보고). 라이브러리가 기본적으로 alg:none 을 거부해야 한다는 권고가 있고, RFC 8725 (JSON Web Token Best Current Practices, 2020) 에 정리.

핵심 권고:

  • alg 화이트리스트 명시 (['HS256','RS256']) — 라이브러리가 토큰의 헤더에서 알고리즘을 그대로 받지 않게.
  • 키 혼동 공격 차단 — HS256 검증 함수에 RS256 공개 키를 전달하는 사고 방지.
  • kid 검증 — 키 ID 를 그대로 파일 경로로 쓰지 말 것.
  • 인증 · 암호화의 분리 (JWS · JWE).

7. 토큰 저장 위치

  • httpOnly Secure 쿠키 — XSS 에서 보호. CSRF 대비 필요 (SameSite + 토큰).
  • JS 접근 가능 저장소 (localStorage) — XSS 발생 시 토큰 노출. 권장도가 낮음.
  • 메모리 (앱 인스턴스 전역 변수) — 새 탭 · 새로고침에 사라짐.

웹은 httpOnly 쿠키 + SameSite=Lax 또는 Strict + 짧은 access TTL 이 자주.

8. 키 관리

  • 키 회전 (rotation) 일정 — JWKS endpoint 의 다중 키.
  • 발급 시 kid 헤더에 키 식별자.
  • 검증 시 JWKS 캐시 · 만료 처리.

비대칭 키의 비공개 키는 시크릿 매니저 (KMS · Vault · 1Password) 로.

9. 클레임 설계

최소 정보만 — 이메일 · 민감 정보를 페이로드에 넣지 않음 (JWT 는 서명만, 암호화 안 됨).

권한 스냅샷 — 토큰에 권한을 넣으면 사용자 권한 변경이 즉시 반영 안 됨. 짧은 TTL 로 보완 또는 권한 체크를 매번 DB 에서.

10. 자주 걸리는 자리

암호화 안 된 사실 — JWT 는 서명만. 페이로드는 누구나 디코딩해 봄. 민감 정보는 JWE 또는 서버 세션.

alg 헤더 신뢰 — 토큰이 자기 알고리즘을 선언하게 두면 공격 표면. 화이트리스트 강제.

HS256 비밀의 약함 — 짧은 비밀은 무차별 공격에 약함. 32 바이트 이상의 무작위 값.

exp 검증 누락 — 라이브러리 기본을 신뢰하지 말고 단위 테스트.

리프레시의 단일 사용 미보장 — 회전 패턴의 의미가 사라짐. 사용 시 즉시 무효화.

로그아웃의 의미 — access TTL 동안은 토큰이 살아 있음. UX 와 안전 사이의 결정.

다중 디바이스 무효화 — 한 디바이스의 비밀번호 변경이 다른 디바이스의 세션을 끊을지 정책 결정.

하고픈 말

JWT 는 무상태 인증의 가벼운 답이지만, 무효화 · 리프레시 · 키 회전이라는 셋의 운영 부담이 따라옵니다. 짧은 access TTL + Refresh Token Rotation + alg 화이트리스트 셋이 함께 있을 때 운영 안전성이 크게 좋아집니다. 민감 정보는 페이로드가 아니라 서버 세션으로.

Next

  • oauth-state-pkce
  • rate-limit-redis

RFC 7519 JWT · RFC 8725 JWT BCP · RFC 7515 JWS · RFC 7516 JWE · OWASP JWT Cheat Sheet · Auth0 Refresh Token Rotation · JWT.io · RFC 9700 OAuth 2.0 BCP 을 참고합니다.

security 카테고리의 다른 글

카테고리 전체 보기 →
  • 공개 라우트 화이트리스트 — 신규 도메인 도입 시 같이 갱신
  • 익명 폼 — 최소한의 안전망
  • 보안 헤더와 CORS
  • 비밀번호 해싱 — bcrypt · scrypt · Argon2
  • 입력 검증 — 경계에서 다듬는다
  • 레이트 리밋 — 알고리즘과 구현