본문 바로가기

OAuth에서 JWT 토큰을 왜 쿠키와 Redis에 저장하나?

@silver-w2025. 12. 25. 19:54

MyAsset 프로젝트에 OAuth2를 통한 소셜로그인을 구현하던 중

Access Token과 Refresh Token에 대해 다른 구조를 가진 걸 발견했다.

  • Access Token → 쿠키
  • Refresh Token → 쿠키 + Redis

여기서 이런 의문이 생겼다.

“JWT는 stateless라면서 왜 굳이 Redis를 쓰는거지?”
“왜 Refresh Token만 Redis에 저장하는거지?"
"쿠키는 왜 쓰는거지?"

먼저 JWT가 무엇인지. 그리고 토큰의 역할과 특징을 정리하고,

그 다음 쿠키 redis을 이용하는 이유에 대해서 익혀보자.


1. OAuth 에서 JWT을 쓰는 이유

로그인 과정에서 서버의 목표는 항상 두 가지다.

  1. 보안
  2. 사용자 경험(UX)

이 둘은 본질적으로 충돌한다.
인증을 강하게 할수록 절차는 복잡해지고, UX는 나빠진다.

 

인증 정보를 강하게 보호할수록 절차는 복잡해지고, 사용자 경험은 나빠질 수 있다.

이 균형을 맞추기 위해 웹 환경에서는 JWT(JSON Web Token)가 널리 사용된다.

JWT를 사용하는 이유는 다음과 같다.

  • HTTP 환경에서 가볍게 전달할 수 있고
  • 서명 기반으로 무결성을 보장하며
  • 서버가 세션 상태를 유지하지 않아도 되는 확장성을 제공하기 때문이다.

이러한 특성 덕분에 JWT는 Authentication(인증)Authorization(인가) 에 특화된 토큰으로 활용된다.

 

§ JWT's benefits & Usage

더보기

- Benefits - 

 

(1) Compact : JWTs are small in size, which makes them a good choice to be passed in HTML and HTTP environments.

(2) Secure : JWTs can use a public/private key pair in the form of an X.509 certificate for signing. A JWT can also be symmetrically signed by a shared secret using the HMAC algorithm.

(3) Common : JSON parsers are supported by most programming languages.

 

- Usage - 

 (1) Authentication : When a user successfully logs in using their credentials, an ID token is returned.

 (2) Authorization : Once a user is successfully logged in, an application may request to access routes, services, or resources (for example, APIs) on behalf of that user. To do so, the application must pass an Access Token in every request, which may be in the form of a JWT.

JSON Web Tokens


2. Access Token

to allow an application to access an API after a user successfully authenticates and authorizes access.
  • 사용자가 인증을 성공적으로 완료한 이후 발급되는 토큰으로, 각 클라이언트 요청이 허가된 사용자 요청인지 판단하는 기준이 된다.
  • 즉, 서버 입장에서 Access Token은 "이 요청을 보낸 사용자가 누구인지"를 증명하는 인증 수단이다.

즉, Access Token은 로그인한 사용자의 신분증 역할을 한다.

  • 일반적으로 Access Token은 JWT(JSON Web Token) 형식으로 발급되며, 토큰 내부에는 사용자 식별자와 권한 정보 등이 Claims 형태로 포함된다.
  • 중요한 점은, Access Token이 탈취될 경우 공격자는 해당 토큰이 만료되기 전까지 정상 사용자로 위장할 수 있다는 것이다.

또한, JWT는 stateless 특성을 가진다.

  → 서버는 토큰을 저장하지 않고, 서명 + 만료 시간(exp) 만 검증한다.

`서버는 이미 발급된 Access Token을 개별적으로 무효화할 수 없다.

따라서,

  • 토큰이 탈취되면
  • 만료 전까지는 서버가 강제로 무효화할 수 없다

이러한 이유로 Access Token의 유효 시간(expiration time)은 짧게 설정하는 것이 일반적이며, 보통 5~15분 수준으로 운영된다.

a user needs a new access token when gaining access to a resource for the first time, or after the previous access token granted to them expires.

 

새로운 Access Token이 필요한 경우는 두가지인데 

  • 처음으로 특정 리소스에 접근할 때
  • 기존의 Access Token이 만료되었을 때

근데 여기에서 문제가 되는게 두번째 상황인데, Access Token이 만료되었을 때 사용자는 다시 로그인을 해야한다.

→ 즉 보안은 좋아지지만, UX는 악화된다.

그러므로 Access Token 단독으로 사용하진 않으며 3.Refresh Token과 병행해서 사용하게 된다.

 

  JSON Web Token - Access Tokens Overview


3. Refresh Token

to issue a new access token or ID token without having to re-authenticate the user.
  • Access Token을 다시 발급받기 위한 토큰이며 '새 신분증'을 발급하기 위한 준비물이다.
  • Refresh Token을 이용하면, Access Token이 만료되더라도 사용자가 다시 로그인할 필요 없이 Refresh Token을 통해 새로운 Access Token을 발급받아 서비스를 끊김 없이 이용할 수 있다.
  • 이 덕분에 Access Token의 유효 시간을 짧게 가져가면서도, 보안과 사용자 경험(UX)을 동시에 만족시킬 수 있다.
Refresh Tokens must be stored securely by an application since they allow a user to remain authenticated essentially forever.

 

하지만 Refresh Token도 문제가 있다. 

 

Refresh Token은 사용자가 사실상 장기간(또는 무기한)에 가깝게 인증 상태를 유지할 수 있도록 해주는 자격 증명이다. 

Refresh Token이 탈취될 경우, 공격자가 사용자의 추가적인 로그인 없이도 새로운 Access Token을 계속 발급받을 수 있다, 그만큼 보안적으로 매우 민감하며, 애플리케이션은 Refresh Token을 반드시 안전하게 저장하고 관리해야 한다.

 

JSON WEB TOKEN - Refresh Token

 

※ Access Token과 Refresh Token 핵심 차이 

구분 Access Token Refresh Token
목적 API 접근 Access Token 재발급
사용 빈도 매우 잦음 드묾
유효 기간 짧음
탈취 시 피해 제한적 매우 큼

5. 왜 Refresh Token만 따로 서버 저장소에 저장할까? (stateless의 한계)

JWT는 서버가 토큰을 기억하지 않아도 검증할 수 있도록 하기 위해 stateless 구조로 설계되었다.

서버는 매 요청마다 토큰의 서명과 만료 시간만 확인하며, 토큰 자체를 저장하거나 추적하지 않는다.

이러한 설계로 인해 JWT에는 명확한 한계가 존재한다.

  • 토큰이 만료되기 전까지는 서버가 이를 강제로 무효화할 수 없고
  • 사용자 로그아웃이나 권한 변경과 같은 상태 변화를 즉시 반영할 수 없다

이 특성은 Access TokenRefresh Token에 서로 다르게 작용한다.

Access Token은

  • 요청마다 사용되고
  • 수명이 짧으며
  • 빈번한 조회가 발생하기 때문에

stateless 구조를 유지하는 것이 오히려 장점이 된다.

 

반면 Refresh Token은 다음과 같은 특성을 가진다.

  • 오직 Access Token을 발급할 수 있는 권한
  • 장기간 세션을 유지할 수 있는 자격 증명
  • 탈취될 경우 피해 범위가 매우 큼

이러한 이유로 Refresh Token을 stateless하게 운용하는 것은 보안적으로 적절하지 않다.

Refresh Token은 반드시 서버가 직접 상태로 관리해야 하는 대상이다.

 

즉, JWT의 stateless 특성은 Access Token에는 장점이지만, Refresh Token에는 치명적인 한계가 된다.

그래서 Refresh Token은 서버가 Redis와 같은 저장소를 사용해 직접 관리한다.


6. Redis를 사용하는 이유?

Redis는 이와 같은 요구사항을 만족시키는 세션 상태 저장소로서 자주 사용된다.

  1. In-Memory 기반
    → 빠른 조회 성능으로 재발급 요청에 즉시 대응 가능
  2. TTL(Time To Live) 지원
    → Refresh Token 만료 시간을 자동으로 관리
  3. 삭제를 통한 즉시 무효화
    → 로그아웃, 탈취 감지 시 강제 무효화 가능 (stateless 한계 극복)
  4. 세션 일관성 유지
    → 다중 서버 환경에서도 동일한 인증 상태 공유로 확장성 확보

 

RefrshToken은 왜 Redis를 사용해 관리할까?

 → 해당 포스팅에서 Redis말고 일반적 DBMS로도 충분한 상황 + 탈취 플로우에 대해서도 잘 설명이 되어있음


7. 왜 Access Token은 쿠키에 저장할까?

JWT는 인증을 담당하고, 쿠키는 브라우저가 해당 인증 정보를 매 요청마다 자동으로 전달하기 위한 수단이다.

A cookie is a small piece of data a server sends to a user's web browser. 
The browser may store cookies, create new cookies, modify existing ones, and send them back to the same server with later requests.
Cookies enable web applications to store limited amounts of data and remember state information; by default the HTTP protocol is stateless
.
※ 여기서 HTTP stateful은 JWT의 stateless와 무관하다 
JWT stateless
 : 서버가 토큰을 저장하지 않는다 검증만 한다 (서명 + exp) → 즉 서버 관점
Cookie stateful
 : 브라우저가 이전 값을 자동 전송 요청 간 연결을 만들어줌 → 즉 클라이언트 관점
- jwt의 stateless의 한계는 Redis에서 상태 관리함으로서 해결하는 것

 

쿠키는 브라우저에서 매 클라이언트 요청 시, 사용자가 요청하지 않아도 HTTP Header에 Request를 넣어서 자동으로 서버에 전송한다.


즉, 쿠키를 사용하면 쿠키 덕분에 Access Token을 매번 자동으로 보내니 개발자 입장에서 요청마다 Authorization 헤더를 직접 관리할 필요가 없어진다.


8. 동작 흐름

로그인

  1. Access Token 발급
  2. Refresh Token 발급
  3. Refresh Token을 Redis에 저장
  4. Access Token / Refresh Token을 쿠키에 저장

Access Token 만료

  1. 클라이언트가 Refresh Token으로 재발급 요청
  2. 서버가 Redis 조회
  3. 저장된 값과 요청 토큰 비교
  4. 일치 → Access Token 재발급
    불일치 → 탈취 또는 로그아웃 처리

로그아웃

  1. Redis에서 Refresh Token 삭제
  2. 쿠키 삭제
  3. 이후 재발급 불가

9. 전체 구조 요약

이 구조는 JWT의 장점(stateless)과 전통 세션의 장점(통제)을 절충한 결과다.

Access Token은 짧게 쓰는 신분증,
Refresh Token은 재발급 받을 권한,
Redis는 서버가 인정한 권한 목록,
쿠키는 브라우저가 이를 자동으로 전달하는 수단이다.

 

'JAVA > SPRING' 카테고리의 다른 글

[JPA] @Temporal 명시하지 않아도 되는 이유  (0) 2026.02.02
[JPA]개인 정리 -  (0) 2026.01.19
@MapsId : Derived Identifier  (1) 2025.12.22
record class(JAVA)와 data class(Kotlin) 비교  (0) 2025.12.19
Null 안정성 확보 방법  (0) 2025.12.19
silver-w
@silver-w :: silver-w 님의 블로그

silver-w 님의 블로그 입니다.

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차