안녕하세요, 흔한 감자입니다.
이번 블로깅에서는 React Router를 이용한 페이지 접근 권한하기 위한 PrivateRoute를 구현하였던 내용을 정리하려고 합니다.
위와 같은 문제를 해결하기 위해 해당 페이지 컴포넌트를 접근할때 비로그인 사용자에 대해서는 Login Page로 리다렉트시키는 PrivateRoute
컴포넌트를 구현하였습니다.
생각보다 코드는 매우 간단합니다
import React from 'react';
import { Navigate, Outlet, useLocation } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import isLoginSelector from '../recoil/seletors';
function PrivateRoute() {
// 로그인 여부 확인
const isLogin = useRecoilValue(isLoginSelector);
// 현재 URL 확인
const location = useLocation();
if (!isLogin) {
return <Navigate to="/login" state={{ from: location }} />; // from에 현재 URL을 저장하여 리다렉트에 사용
}
return <Outlet />; //로그인 상태라면 원래 컴포넌트로 렌더링
}
useLocation
를 통해 현제 URL을 받음export default createBrowserRouter([
{
element: <Root />,
children: [
{
// 권한 관리 Route로 감싸기
element: <PrivateRoute />,
children: [
{
path: '/mypage',
element: <MyPage />,
},
{
path: '/book-discussion/:postId/edit',
element: <DiscussionEditPage discussionType="book" />,
},
{
path: '/pro-con-discussion/:postId/edit',
element: <DiscussionEditPage discussionType="proCon" />,
},
{
path: '/posts/new',
children: [
{
path: 'pro-con-discussion',
element: <PostNewPage discussionType="proCon" />,
},
{
path: 'book-discussion',
element: <PostNewPage discussionType="book" />,
},
],
},
],
},
],
},
]);
const location = useLocation();
const fromUrl = location.state?.from;
const handleLogin = async (email: string, pas: string) => {
try {
const { jwt, userInfo } = await login(email, pas, setDisplayError);
setJwt(jwt);
setUserInfo(userInfo);
navigate(fromUrl || '/', { replace: true }); // fromUrl이 있는 경우 리다렉트
} catch (loginError) {
console.error(loginError);
setDisplayError('서버에서 문제가 발생하였습니다.');
}
};
구글링해보면 정말 다양한 방법으로 로그인 리다렉트하는 방법이 있다는 것을 깨달았습니다. 그 중에서 우리에 상황에 PrivateRouter가 가장 적합하고 구현 자체도 심플하도고 느껴져서 해당 방식을 채택하였습니다. 개인적으로 이 방식이 꽤나 마음에 들어 다음 프로젝트에도 똑같이 적용할거 같다는 생각이 들었습니다.