Refresh Token 저장소를 Redis로 변경하며 만난 문제

JeongO·2023년 2월 26일
0

당근플래너

목록 보기
2/2

당근플래너 서비스에 Redis를 도입한 과정을 간단히 글로 작성했었다.
( 도입기 👉 https://danggeunplanner.tistory.com/entry/BE-%EB%8B%B9%EA%B7%BC%ED%94%8C%EB%9E%98%EB%84%88%EC%97%90-%EB%A0%88%EB%94%94%EC%8A%A4-%EB%BF%8C%EB%A6%AC%EA%B8%B0%EB%8F%84%EC%9E%85%EA%B8%B0)



사실 처음에는 Refresh Token기능 로직이 다 작성되어 있으니 저장소만 옮기면 된다!고 간단하게 생각했었다.
하지만 머지 않아 그렇지 않다는 것을 알게 되었다.

Redis를 처음 접해본 나에게는, 그리고 당시 구현되어있던 우리의 로직에서는 뿅!하고 순식간에 옮겨지는 것은 아니었다.


🔴 문제 상황

기존 Refresh Token은 단순히 DB의 회원 테이블에 Refresh Token컬럼을 추가하여 저장해 두었었다.
하지만 Redis에서는 데이터의 저장 형태가 key-value 형식이었기 때문에 Refresh Token값과 짝을 이루는 key값이 있어야 했다.
회원의 데이터중 유니크한 값이 email을 key에 넣기로 했는데 문제는 레디스에서 Refresh Token을 조회할 때 email값을 인자로 받아올 수가 없다는 점이었다.

레디스에서 Refresh Token을 조회하는 경우는 Access Token이 만료된 후, 토큰 재발급 요청을 보낼 때인데 이때 클라이언트는 Refresh Token만 헤더에 담아서 보낸다.

문제는 여기서 발생했다.

  • Refresh Token의 목적성을 고려해, 불필요하게 유저의 정보를 토큰에 담지 않는다.
  • 토큰 재발급 요청시에는 Refresh Token만 헤더에 담아 온다.
  • 재발급 요청이 들어왔을 때 레디스에서 Refresh Token을 조회하려면 유저의 email 정보가 필요하다.(근데 없다..)

🟡 첫 번째 해결

결국 토큰 재발급 요청시 Access Token도 함께 헤더에 담아 오기로 했다.
Access Token에 담겨 있는 유저의 email을 가지고 레디스에서 Refresh Token을 조회하고, Refresh Token 검증이 끝나면 유저에게 토큰을 재발급해준다.

이렇게 문제가 해결!!!
된 줄 알았으나, 재발급 요청에서 계속 에러가 발생했다.
Access Token에서 유저정보를 추출하기 위해 토큰을 분해하는 과정👇 에서 ExpiredJwtException 에러가 발생하는 것이었다.


🟢 최종 해결

생각해보니 토큰이 만료되었고, 만료된 토큰에서 유저정보를 추출하려 하니 에러가 발생하는 건 당연한 것이었다.
하지만 재발급 요청 시에는 만료된 토큰에서 유저정보를 추출해야 하는 상황이므로 무언가 처리를 해줘야 했다.

ExpiredJwtException예외 클래스를 들어가 보니👇 다음과 같이 예외 객체에 토큰의 Claims가 속성으로 있는 것을 확인할 수 있었다.

여기서 힌트를 얻어 아래와 같이 try-catch문으로 토큰만료예외를 잡아서 예외 객체의 Claims를 추출해 반환하도록 했다.

이렇게 처리를 해주면 만료된 토큰에서도 유저의 email을 추출할 수 있었고, 성공적으로 유저에게 토큰을 재발급할 수 있었다.






자바공부를 할 때 예외처리에 대한 부분을 공부하긴 했지만 실제로 예외 객체에 어떤 속성이 있는지 알지 못했었다.
그래서 처음에 토큰 만료 예외처리가 된다는 사실을 발견했을 때 어떻게 해결해야할 지 몰라 당황한 게 사실이었다.

하지만 구글링과 질문과 고민을 통해 예외 객체를 이용하면 된다는 것을 알았고, 성공적으로 Redis로 저장소를 이전할 수 있어서 뿌듯했다.

모를 땐 자바 클래스들을 다 들어가봐야한다....그 곳에 꽤 답이 있나니..🥳

profile
IT'S YOUR VICTORY

0개의 댓글

관련 채용 정보