로그인 시 로그인 유효성을 access token 하나당 30분으로 뒀는데,
기능 페이지에서 30분 이상 있을 시 토큰이 유효하지 않게 되어서 에러가 발생할 수 있다.
// index.js 중 일부
<BrowserRouter>
<AuthProvider>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/login" element={<PublicRoute><LoginPage /></PublicRoute>}/>
<Route path="/register" element={<PublicRoute><RegisterPage /></PublicRoute>} />
<Route path="/profile" element={<ProtectedRoute><ProfilePage /></ProtectedRoute>} />
<Route path="/mypage" element={<ProtectedRoute><CalendarPage /></ProtectedRoute>} />
<Route path="/file-upload" element={<ProtectedRoute><FileUploaderPage /></ProtectedRoute>} />
<Route path="/result" element={<ResultPage />} />
<Route path="/magazine" element={<MagazinePage/>} />
<Route path="/survey" element={<ProtectedRoute><SurveyPage/></ProtectedRoute>}/>
<Route path="/product" element={<HaircareProductPage/>}/>
<Route path="/about" element={<AboutPage></AboutPage>}/>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</AuthProvider>
</BrowserRouter>
이를 해결하기 위해 JWT 인증 방식을 추가해 쿠키를 사용하고,
ProtectedRoute로 감싼 페이지, 로그인 후에 접근할 수 있는 페이지들이 랜더링 되면
자동으로 access token과 refresh token이 갱신되게 기능을 추가했다.
import React, { useContext, useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import { AuthContext } from 'components/Functions/AuthContext';
import axios from 'axios';
import Cookies from 'js-cookie';
const ProtectedRoute = ({ children }) => {
const { isLoggedIn } = useContext(AuthContext);
// ProtectedRoute로 감싸진 페이지 접속시 sessionStorage와 cookie 에 있는 access , refresh token 을 갱신
useEffect(() => {
const refreshTokens = async () => {
const refreshToken = Cookies.get('refresh-token');
const accessToken = Cookies.get('access-token')
let headers = {
Authorization: `Bearer ${accessToken}`,
};
if (refreshToken) {
try {
const response = await axios.post(
`백엔드 주소`,
null,
{
headers: headers,
}
);
const { accessToken, refreshToken: newRefreshToken } = response.data;
Cookies.set('refresh-token', newRefreshToken, { path: '/' });
Cookies.set('access-token', accessToken, { path: '/' });
sessionStorage.setItem('accessToken', accessToken);
sessionStorage.setItem('refreshToken', newRefreshToken);
} catch (error) {
console.error('Token reissue failed:', error);
}
}
};
if (isLoggedIn) {
refreshTokens();
const intervalId = setInterval(refreshTokens, 60*60*25); // 25분 간격으로 토큰 갱신
return () => clearInterval(intervalId); // 컴포넌트 언마운트 시 인터벌 정리
}
}, [isLoggedIn]);
if (!isLoggedIn) {
return <Navigate to="/login" />;
}
return children;
};
export default ProtectedRoute;
ProtectedRoute로 감싼 페이지에 들어가면 access token과 refresh token을 받아와서 쿠키 값을 갱신하고, 25분 간격으로 access token과 refresh token을 갱신해준다.
const refreshToken = Cookies.get('refresh-token');
const accessToken = Cookies.get('access-token')
let headers = {
Authorization: `Bearer ${accessToken}`,
};
if (refreshToken) {
try {
const response = await axios.post(
`백엔드 주소`,
null,
{
headers: headers,
}
);
어려웠던 부분은 바로 이 부분이였다. 쿠키를 post 할 시에 header를 지정해줘야 하는데
자꾸 500 에러가 나서 꽤나 시간이 많이 들었다.
위와 같은 형식으로 헤더를 지정해서 같이 post 해주니 결과가 잘 출력 되었다.
axios로 쿠키를 post 할 시에 헤더구조를 저런식으로 설정해줘야 한다는 것을 잊지말자