당근플래너 서비스에 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만 헤더에 담아서 보낸다.
문제는 여기서 발생했다.
결국 토큰 재발급 요청시 Access Token도 함께 헤더에 담아 오기로 했다.
Access Token에 담겨 있는 유저의 email을 가지고 레디스에서 Refresh Token을 조회하고, Refresh Token 검증이 끝나면 유저에게 토큰을 재발급해준다.
이렇게 문제가 해결!!!
된 줄 알았으나, 재발급 요청에서 계속 에러가 발생했다.
Access Token에서 유저정보를 추출하기 위해 토큰을 분해하는 과정👇 에서 ExpiredJwtException 에러가 발생하는 것이었다.
생각해보니 토큰이 만료되었고, 만료된 토큰에서 유저정보를 추출하려 하니 에러가 발생하는 건 당연한 것이었다.
하지만 재발급 요청 시에는 만료된 토큰에서 유저정보를 추출해야 하는 상황이므로 무언가 처리를 해줘야 했다.
ExpiredJwtException예외 클래스를 들어가 보니👇 다음과 같이 예외 객체에 토큰의 Claims가 속성으로 있는 것을 확인할 수 있었다.
여기서 힌트를 얻어 아래와 같이 try-catch문으로 토큰만료예외를 잡아서 예외 객체의 Claims를 추출해 반환하도록 했다.
이렇게 처리를 해주면 만료된 토큰에서도 유저의 email을 추출할 수 있었고, 성공적으로 유저에게 토큰을 재발급할 수 있었다.
자바공부를 할 때 예외처리에 대한 부분을 공부하긴 했지만 실제로 예외 객체에 어떤 속성이 있는지 알지 못했었다.
그래서 처음에 토큰 만료 예외처리가 된다는 사실을 발견했을 때 어떻게 해결해야할 지 몰라 당황한 게 사실이었다.
하지만 구글링과 질문과 고민을 통해 예외 객체를 이용하면 된다는 것을 알았고, 성공적으로 Redis로 저장소를 이전할 수 있어서 뿌듯했다.
모를 땐 자바 클래스들을 다 들어가봐야한다....그 곳에 꽤 답이 있나니..🥳