Skip to content

JWT & AccessToken / RefreshToken

🔑 JWT 한 줄 정리

JWT는 사용자가 누구인지(sub), 어떤 권한(role)을 가졌는지 담고,
서명(signature)으로 위조 여부를 검증할 수 있는 Stateless 인증 토큰이다.

🧩 Reference

  • JWT(Json Web Token) = 인증/인가 정보를 담은 서명 가능한 토큰
  • JWT 구조: Header.Payload.Signature (base64url 인코딩)
  • AccessToken = 짧게 유지되는 인증 토큰 (Authorization 헤더로 전송)
  • RefreshToken = 새로운 AccessToken 발급용 장기 토큰 (httpOnly 쿠키로 전송)
  • 서버는 토큰의 서명과 만료 시간, 발급자 등을 검증해서
    별도의 세션 저장소 없이도 사용자 신원을 확인할 수 있음 → Stateless 인증

🧩 Point

  • AccessToken은 짧게 만료되어야 탈취 피해가 최소화된다.
  • RefreshToken은 js 접근이 불가능한 httpOnly + Secure 쿠키로 보호해야 한다.
  • 401 Unauthorized는 현재 인증 정보(AccessToken 등)에 문제가 있다는 신호다.
    많은 서비스에서 AccessToken 만료 상황을 401로 내려주고,
    이때 RefreshToken으로 재발급을 시도하도록 설계한다.
  • 자동 로그인은 RefreshToken이 쿠키로 자동 전송되기 때문에 가능한 구조이다.
  • JWT는 payload가 클수록 네트워크 비용 증가 → 필요한 최소 정보만 넣어야 한다.
  • HTTPS 없으면 Authorization 헤더의 JWT나 쿠키에 담긴 RefreshToken이 그대로 노출될 수 있으므로 필수다.

JWT를 이해하기 전에 중요한 사실

JWT는 독립적으로 동작하는 기술이 아니라,
HTTP + HTTPS + Cookie + Authorization Header 위에서 돌아가는 인증 프로토콜이다.

즉 인증을 구현할 때,

  • 토큰 → HTTP Authorization 헤더로 보내고
  • RefreshToken → httpOnly 쿠키로 자동 전송되고
  • 토큰 만료 → HTTP 401 응답으로 감지되고
  • 자동 재발급 → Axios interceptor로 구현되는 것

→ 이 모든 과정이 HTTP 규약 위에서 이루어진다.
(그래서 HTTP/HTTPS, 쿠키 동작을 먼저 이해하면 JWT를 훨씬 쉽게 이해할 수 있다.)

🧩 Axios를 사용하지 않으면 어떻게 될까?

본문에서 설명하는 흐름은 Axios 기준이지만, JWT 인증 자체는 Axios 의존적인 기술이 아니라 HTTP 규약 위에서 동작하는 인증 방식이다. 현재 진행 중인 프로젝트가 Axios를 사용하고 있어 이를 기준으로 적었다!

  • AccessToken → Authorization 헤더로 보내고
  • RefreshToken → httpOnly 쿠키로 자동 전송되고
  • AccessToken 만료 → 서버가 401을 내려주고
  • RefreshToken 재발급 → fetch로도 가능

따라서 JWT 인증은 Axios 기능이 아니라 HTTP 규약 위에서 동작하는 인증 방식이다. Axios를 쓰지 않는다면, interceptor 부분만 직접 함수로 감싸서 구현하면 동일하게 동작한다!


JWT란?

JWT(Json Web Token)는 인증을 위해 사용되는 서명된 토큰 포맷이다.
토큰 내부에 유저 ID, 권한, 만료 시간 등 중요한 정보가 포함되며, 토큰이 변조되지 않았는지만 서버가 검증하면 요청을 신뢰할 수 있다.

JWT 구조는 header.payload.signature 형태의 세 부분으로 나누어진다:

plaintext
Header.Payload.Signature
부분설명
Header토큰 형식, 서명 알고리즘 정보
Payload실제 데이터
sub: subject (사용자 고유 ID)
role: 권한 정보
iat: 발급 시간 (Issued At)
exp: 만료 시간 (Expiration)
Signature비밀키로 서명된 값 → 위조 방지

서버는 Signature를 검증해 이 토큰이 우리 서버에서 발급된 토큰인지?, Payload가 유효한지?를 판단할 수 있다. 그래서 세션 저장소 없이도 인증이 가능하다. (stateless)

왜 JWT는 Stateless인가?

세션 인증과 다르게 JWT 인증에서는:

  • 서버가 사용자 상태를 메모리에 저장하지 않음
  • DB에 세션 레코드도 없음
  • 오직 토큰의 서명(signature)만 검증하면 사용자를 식별할 수 있음

즉, 서버는 “유저 정보를 들고 있지 않아도” 요청을 처리할 수 있다. → 확장성에 특히 유리하다.


AccessToken & RefreshToken

JWT 인증에서는 보통 두 종류의 토큰이 함께 사용된다.

JWT는 유효기간이 있는 토큰이기 때문에 다음 문제가 생긴다:

  • AccessToken을 길게 하면 → 탈취 위험 증가
  • AccessToken을 짧게 하면 → 사용자가 자주 로그아웃됨

그래서 나온 구조가 AccessToken (짧게) + RefreshToken (길게)이다.
두 개가 합쳐져서 보안 + 유저 경험 둘 다 잡는 구조가 된다.

종류저장 위치만료역할
AccessToken메모리/Zustand/localStorage15분~1시간요청 인증
RefreshTokenhttpOnly 쿠키(브라우저 자동 관리)2주~1달AccessToken 재발급

AccessToken (AT)

역할

  • 사용자가 누구인지 인증하는 정보
  • 요청을 보낼 때 Authorization 헤더에 담아 전달

특징

  • 만료 시간이 매우 짧다 (5분 ~ 30분)
  • 탈취되면 곧 만료되므로 피해가 제한적
  • 프론트에서는 보안상 메모리(Zustand 등)에 두는 것을 우선으로 하고,
    필요에 따라 LocalStorage에 저장하는 방식도 사용된다. (XSS 취약성 고려 필요)

요청 예시

http
Authorization: Bearer <access_token>

RefreshToken (RT)

역할

  • AccessToken이 만료되었을 때 새 토큰을 발급받기 위한 장기 토큰

특징

  • 수명이 김 (7일 ~)
  • 탈취되면 계정이 위협받음 → 가장 민감한 토큰
  • JS 접근이 불가한 httpOnly + Secure 쿠키로 저장
  • 브라우저가 자동으로 전송

서버가 RefreshToken을 쿠키로 주는 예시

http
Set-Cookie: refresh_token=abc123; HttpOnly; Secure; SameSite=Strict; Path=/auth

프론트에서는 RT를 읽을 수 없다

js
console.log(document.cookie); // refresh_token 보이지 않음

→ 이 특성이 XSS 공격으로부터 토큰을 보호한다.


RefreshToken이 쿠키여야 하는 이유

RefreshToken은 클라이언트의 신원(Identity)을 증명하는 데이터이기 때문에 프론트가 직접 저장하거나 관리하면 안 된다. 브라우저가 자동으로 관리하는 httpOnly 쿠키여야 한다.

1. RefreshToken은 서버가 신원을 판단하는 인증 채널이어야 한다.

  • 서버가 RT를 통해 “이 재발급 요청이 진짜 우리 사용자가 보낸 요청인지” 판단한다.

쿠키는 서버가 Set-Cookie로 내려주면 브라우저가 자동 저장 + 자동 전송해주므로 프론트 코드 개입 없이 안정적인 인증 채널을 유지할 수 있다.

2. RefreshToken은 JS에서 읽히면 안 된다.

RT를 localStorage 같은 곳에 저장하면 악성 스크립트가 삽입되는 순간 바로 털린다. httpOnly 쿠키는 JS로 접근할 수 없기 때문에 XSS 공격으로부터 RefreshToken을 보호하는 유일한 방법이다.

3. RT는 재발급 용도라 노출되면 세션이 영구 탈취된다.

  • AccessToken은 짧아서 피해가 제한적이다.
  • RefreshToken은 길어서 털리면 치명적이므로 무조건 보호해야 한다.

그래서 RT는 실무에서 보통
httpOnly + Secure + SameSite=strict(or lax) 조합의 쿠키로 저장한다.
SameSite 설정은 CSRF 공격을 얼마나 허용/차단할지 정책에 따라 조정한다.


JWT의 장점과 단점

장점

  • 확장성 뛰어남 (서버가 상태를 들고 있지 않아도 됨)
  • 서버가 여러 대여도 문제 없음 (Load Balancing 완벽)
  • bearer token 표준 방식
  • 로그인 상태 유지가 간단

단점

  • 토큰 크기가 큼 → Network 비용 증가
  • 토큰 탈취되면 만료되기 전까지 무조건 유효
  • 토큰 강제 무효화(revoke)가 어려움 → 블랙리스트 DB 필요
  • 쿠키 4KB 제한으로 payload를 많이 넣을 수 없음

정리

💡

  • JWT 인증은 HTTP/HTTPS + Authorization 헤더 + Cookie 위에서 동작한다.
  • AccessToken은 요청 인증용이며, 보안을 위해 짧게 유지해야 한다.
  • RefreshToken은 재발급용이며, httpOnly 쿠키로 반드시 보호해야 한다.
  • AccessToken이 만료되면 서버는 401 Unauthorized를 내려 신호를 보낸다.
  • 이 신호를 받아 RefreshToken으로 재발급 → 요청 재시도 흐름이 시작된다.
  • Axios를 사용할 경우, interceptor가 이 재발급 과정을 자동화하는 도구가 된다.
  • 핵심은 Axios가 아니라 “HTTP 응답(401) → 토큰 재발급 → 요청 재시도”라는 흐름 자체!