Axios interceptors 를 활용한 Refresh token 만료 시 처리 구현
이슈
JWT refresh token 만료 시 로그인 페이지로 이동하지 않는 현상
문제점
refresh 토큰이 만료된 경우를 구분이 어렵다
access 토큰은 만료되었으나 refresh 토큰은 만료되지 않은 경우에 첫 요청은 실패하지만
react-query에서 3번 더 요청을 하기 때문에 두 번째 요청을 보내기 전에 next auth에서 refresh 토큰을 발급받아서 두 번째 요청은 성공했다
해결
Axios interceptors를 이용하여 3번째 재시도까지 토큰이 만료되었다는 응답을 받으면 refresh 토큰이 만료된 것으로 간주하고 로그인 페이지로 이동
구현 코드
import http, { setToken } from 'lib/axios';
import { route } from 'constants/route';
import { useEffect, useRef } from 'react';
import { getAxiosError } from 'utils/http';
import { ERROR_CODE } from 'constants/error';
import { isAxiosError } from 'axios';
const SessionLoader = ({ children }: { children: React.ReactNode }) => {
// 각 요청에 대한 실패를 카운트하는 객체
const responseInvalidTokenCounterRef = useRef<{ [key: string]: number }>({});
useEffect(() => {
http.interceptors.response.use(
(response) => {
// 응답 성공 시 카운트 초기화
const requestUrl = response.config.url ?? 'common';
responseInvalidTokenCounterRef.current[requestUrl] = 0;
return response;
},
(error) => {
if (isAxiosError(error)) {
// 3번째 재시도까지 토큰이 유효하지 않을 때 로그인 페이지로 이동
const requestUrl = error.config?.url ?? 'common';
const errorData = getAxiosError(error);
if (errorData?.result.errorCode === ERROR_CODE.INVALID_TOKEN) {
responseInvalidTokenCounterRef.current[requestUrl] =
responseInvalidTokenCounterRef.current[requestUrl] ?? 0;
responseInvalidTokenCounterRef.current[requestUrl] += 1;
}
if (responseInvalidTokenCounterRef.current[requestUrl] > 2) {
window.location.href = route.login;
}
}
return Promise.reject(error);
},
);
}, []);
// 나머지 코드 생략...
return <>{children}</>;
};
export default SessionLoader;