데이터베이스

RTR 방식과 Refresh Token을 Redis에 저장하는 이유

heyh0 2024. 10. 14. 22:34

Token과 RTR 방식

  • AccessToken: 사용자가 특정 서비스에 접근할 권한을 증명하는 문자열이다. 사용자의 인증 정보를 확인한 후 발급되며, 사용자가 서비스를 이용할 때마다 이 토큰을 사용해 자신의 인증 상태를 증명한다.
  • RefreshToken: AccessToken을 재발급받을 때 사용하는 토큰이다. AccessToken의 만료 시간을 길게 설정할 경우, 탈취 시 악의적인 공격에 악용될 위험이 있다. 따라서 AccessToken은 짧은 만료 시간을 가지도록 하고, 대신 상대적으로 긴 만료 시간을 가진 RefreshToken을 사용해 새로운 AccessToken을 발급받도록 한다. 이를 통해 사용자는 로그아웃하지 않고도 지속적으로 로그인 상태를 유지할 수 있다.

Refresh Token Rotation(RTR)은 Access Token이 만료될 때마다 Refresh Token도 함께 교체를 해주는 것이다. 쉽게 말하면 Refresh Token을 최대한 짧게 유지하고, 재사용 불가능하게 만들어 보안을 보장하는 방법이다.

 

RefreshToken을 왜 DB에 저장해서 사용할까?

JWT 토큰은 발급 후, HTTP로 상태를 서버가 관리하지 않는 Stateless한 방식으로 동작한다.

따라서 한 번 발급된 토큰의 상태를 서버가 추적할 수 없어 해당 요청이 실제 사용자의 것인지, 아니면 탈취된 토큰을 사용한 해커의 것인지 구별하기 어렵다.

 

이 때문에 AccessToken은 짧은 만료 시간을 설정한다.

탈취되더라도 금방 만료되기 때문에 오랜 시간 악용될 위험을 줄일 수 있다.

하지만 RefreshToken은 더 긴 만료 시간을 가지기 때문에, 만약 함께 탈취당하면 오랜 시간 동안 사용자의 권한을 악용할 수 있다.

이러한 위험을 방지하기 위해 RefreshToken을 DB에 저장해 관리한다.

 

RDB가 아닌 Redis?

Redis는 휘발성 메모리를 사용하기 때문에 장애가 발생하거나 전원이 끊어질 경우 데이터가 손실될 수 있다.

이런 점에서 RDB가 더 안정적이라고 생각할 수 있다.

 

하지만 Redis와 RDB는 각각의 특징이 존재한다. 

  • Redis: In-memory 캐시 서버로서 빠른 속도가 강점.
  • RDB: 영속적인 저장소로, 데이터의 안정성을 보장.

 

Redis를 선택한 이유

RefreshToken이 손실되더라도 모든 사용자가 로그아웃되고 재로그인만 하면 된다.

이는 큰 문제로 이어지지 않기 때문에, 속도가 중요한 경우 Redis를 선택하는 것이 나을 수 있다.

즉, Redis를 사용하면 더 나은 응답 속도로 사용자 경험을 개선할 수 있다.

 

따라서 상황과 비용을 고려해 적절한 기술과 방식을 선택하는 것이 중요하다.

개인적으로는 성능상의 이점을 중시해 Redis로 토큰을 관리하는 방식을 채택했다.

 

ETC.

Redis도 @Transactional로 트랜잭션 설정이 가능한가 ?

 

Redis는 RedisConfig에서 추가적인 설정을 통해 @Transactional을 사용하여 JPA와 하나의 트랜잭션으로 묶어 사용할 수 있다.

하지만 Redis는 JPA처럼 영속성 컨텍스트의 1차 캐시 기능을 지원하지 않기 때문에 일부 문제가 발생할 수 있다.

 

JPA는 DB에 flush되지 않은 데이터도 1차 캐시에 저장되기 때문에, 조회 시 먼저 캐시에서 데이터를 가져온다.

그러나 Redis에는 이러한 1차 캐시가 없기 때문에, DB에 커밋되기 전까지는 트랜잭션 내에서 발생한 변경 사항을 조회할 수 없다.

 

[PR] 카카오 소셜로그인 + JWT + Redis

https://github.com/pdohyung/doblog/pull/2

 

[Feature] 유저 카카오 로그인 기능 구현 by pdohyung · Pull Request #2 · pdohyung/doblog

💡 연관된 이슈 close #1 📝 작업 내용 카카오 로그인 API, 토큰 Reissue API 추가 사용자 인증 정보 추출 어노테이션 @Auth 추가 RefreshToken 추출 어노테이션 @RefreshToken 추가

github.com