⛵ 항해99/TIL · WIL ✏️
[TIL] 2023.11.13 - 트러블 슈팅(Token 재발급 후 페이지 이동 이슈)
hhhhy
2023. 11. 20. 15:10
트러블 슈팅(Token 재발급 후 페이지 이동 이슈)
① 문제
- axios interceptors를 사용해 axios가 서버로 HTTP 요청을 보내기 전, refresh Token으로 만료된 access Token을 재발급 받도로록 구현함.
- try catch문을 사용해 에러가 발생했을 때는 쿠키에 저장된 refresh Token과 로컬스토리지에 저장된 access Token을 모두 지우고 로그인 화면으로 이동하도록 useNavigate를 사용했는데, 페이지 이동이 되지 않는 이슈가 발생함.
② 시도
1) 토큰 재발급 코드 위치 변경 : axios interceptors → Layout
- axios interceptors는 useNavigate가 실행되지 않아 모든 페이지에 영향을 주는 Layout으로 옮겨서 Token 재발급 코드를 작성함
2) Layout 이동 후 : useNavigate는 동작하나, 토큰 재발급을 후 렌더링 이슈 발생
- 코드 위치를 바꾸고 나서 useNavigate는 잘 동작하지만, 각 페이지가 바로 렌더링되지 않고, 새로고침을 눌러야 렌더링이 되는 문제가 발생함.
③ 해결
- 리액트 훅(useNavigate, useEffect 등등)은 jsx파일이거나, 커스텀훅(use000.jsx) 파일에서만 쓸 수 있었음.
- interceptors는 js 파일이기때문에 useNavigate를 사용하는 대신에 window.location.href = "/login";로 수정해 문제를 해결함.
// accessToken 재발급
axiosInstance.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
// 액세스 토큰 만료됐을 때,
if (error.response.data.status === 500) {
const refreshToken = getCookie("refreshToken"); // 리프레시 토큰 가져오고,
localStorage.removeItem("accessToken"); // 엑세스 토큰은 지우기(axiosInstance 기본설정 때문에 post 보낼때 같이 보내지는데, 403 에러남!)
console.log("액세스 토큰 만료", error);
console.log("refreshToken 있니?", refreshToken);
// 1. 리프레시 토큰이 있으면,
if (refreshToken) {
try {
// 재발급 API로 리프레시 토큰 보내서
const response = await axiosInstance.post(
"/api/token/refreshAccessToken",
null, // 요청 body 보내지 않음
{
headers: {
Authorization_refresh: refreshToken,
},
}
);
console.log("리프레시 있을 때 response", response);
// 새로운 토큰(액세스/리프레시) 받고, 저장하기
const newAccessToken = response.data.accessToken;
const newRefreshToken = response.data.refreshToken;
localStorage.setItem("accessToken", newAccessToken);
setCookie("refreshToken", newRefreshToken, {
path: "/", // 모든 페이지에서 쿠키 접근 가능
secure: true, // https로 통신할때만 쿠키 저장됨
// httpOnly: true, // HttpOnly 속성을 적용(js 접근 불가) > 클라이언트에서 저장안됨
});
error.config.headers["Authorization"] = newAccessToken; // 업데이트된 액세스 토큰을 헤더에 설정하고 현재 요청을 다시 실행
return axiosInstance(error.config); // 현재 요청을 새로운 액세스 토큰을 가지고 재시도
// 2. 리프레시 토큰 에러면,
} catch (refreshError) {
console.log("리프레시 에러 refreshError", refreshError);
// 토큰(액세스/리프레시) 지우고, 재로그인 시키기
localStorage.removeItem("accessToken");
removeCookie("refreshToken");
window.location.href = "/login";
alert("재로그인이 필요합니다.");
}
} else {
// 토큰(액세스/리프레시) 지우고, 재로그인 시키기
localStorage.removeItem("accessToken");
removeCookie("refreshToken");
window.location.href = "/login";
alert("재로그인이 필요합니다.");
}
}
// 다른 오류의 경우, 오류를 다시 반환
return Promise.reject(error);
}
);