PrivateRoute 구현하기 (페이지 접근 권한 관리)

흔한 감자·2023년 6월 2일
0

회고

목록 보기
6/7

안녕하세요, 흔한 감자입니다.
이번 블로깅에서는 React Router를 이용한 페이지 접근 권한하기 위한 PrivateRoute를 구현하였던 내용을 정리하려고 합니다.

기존 URL 직접 접근 문제

이슈 사항

  • 현재 로그인 권한이 필요한 페이지들에 대해선 헤더의 Navigate에서만 권한을 관리하고 있어, URL로 직접 입력시 모두 접근이 되는 이슈가 발생

토론하기 헤더로 접근시

토론하기 URL로 접근시 (접근됨)

해결 방안

위와 같은 문제를 해결하기 위해 해당 페이지 컴포넌트를 접근할때 비로그인 사용자에 대해서는 Login Page로 리다렉트시키는 PrivateRoute 컴포넌트를 구현하였습니다.
생각보다 코드는 매우 간단합니다

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 />; //로그인 상태라면 원래 컴포넌트로 렌더링
}
  • 로그인 상태는 Recoil을 통해 관리되고 있어, 이를 통해 로그인 여부를 판단
  • 현재 위치를 useLocation를 통해 현제 URL을 받음
  • 비로그인 유저에 대해 Navigate 컴포넌트를 통해 리다이렉트
  • 로그인 완료 후 최초 권한이 필요했던 원래 페이지로 리다이렉트 하기 위해 from을 통해 전달해줍니다

createBrowserRouter 로그인 권한 필요 컴포넌트 감싸기

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" />,
              },
            ],
          },
        ],
      },
    ],
  },
]);

로그인 완료시 원래 URL로 리다렉트 시키기

  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 확인하기

마무리

구글링해보면 정말 다양한 방법으로 로그인 리다렉트하는 방법이 있다는 것을 깨달았습니다. 그 중에서 우리에 상황에 PrivateRouter가 가장 적합하고 구현 자체도 심플하도고 느껴져서 해당 방식을 채택하였습니다. 개인적으로 이 방식이 꽤나 마음에 들어 다음 프로젝트에도 똑같이 적용할거 같다는 생각이 들었습니다.

profile
프론트엔드 개발자

0개의 댓글