JS/React

React - 로그인 여부에 따른 Router 관리(Guard)

shin96bc 2024. 3. 9. 18:14

프로세스

Routes를 하나만 두고 private Routes에만 Guard를 감싸고 Guard에서 로그인 여부를 체크해서 로그인 상태가 아닌 경우에 로그인 페이지로 redirect 하는 방법입니다.

 

권한별로 가드를 만드는 방법입니다.

 

권한이 3가지인 경우에는 권한마다 가드를 만들어서 해당 페이지를 감싸주면 됩니다.

  • 권한이 없으면 redirect 시킵니다.

만약 권한이 많고 복잡해서 1, 2, 3, 4중에 1,2만 해당 페이지에 접근하게 만들고 싶다면 권한 1, 2를 체크하는 가드를 하나 더 만들면 됩니다.

 

코드 작성법

폴더 구조

 

/guard

  • LoginGuard.js
import { useNavigate } from "react-router-dom";
import { useSelector } from "react-redux";
import { useEffect } from "react";

const LoginGuard = (props) => {
  const {children} = props;

  const navigate = useNavigate();

  const {isValidToken} = useSelector((state) => state.loginData);

  useEffect(() => {
		// 토큰이 유효하지 않을 때 redirect
    if (!isValidToken) {
      navigate('/login', {replace: true});
    }
  }, [isValidToken]);

  return (
    <>
      {children}
    </>
  );
};

export default LoginGuard;

 

/routes

  • CommonRoutes.js
import DashBoard from "../pages/DashBoard";
import CommonLayout from "../layout/CommonLayout";
import Login from "../pages/Login";
import LoginGuard from "../guard/LoginGuard";

const CommonRoutes = {
  path: '/',
  element: <CommonLayout />,
  children: [
    {
      path: '',
      element: (
				// private 페이지만 가드로 감싼다
        <LoginGuard>
          <DashBoard />
        </LoginGuard>
      )
    },
    {
      path: 'login',
      element: <Login />
    }
  ]
}

export default CommonRoutes;

 

  • index.js
import {useRoutes} from "react-router-dom";
import CommonRoutes from "./CommonRoutes";

const Routes = () => {

  return useRoutes([
    CommonRoutes
  ])
};

export default Routes;

 

App.js

import Routes from "./routes";

function App() {
  return (
    <>
      <Routes />
    </>
  );
}

export default App;

 

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import store from "./store";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <BrowserRouter>
      <App/>
    </BrowserRouter>
  </Provider>
);

reportWebVitals();

 

장단점

  • 장점
    • Routes를 layout별로 나눠서 관리할 수 있다.
    • 페이지별로 한눈에 확인하기가 쉽다. (페이지를 기준으로 확인할 때 좋다.)
    • 숨기고 싶은 페이지가 여러 Routes에 존재하더라도 숨기고 싶은 페이지에만 가드를 감싸주면 된다.
      • layout이 페이지 마다 다른 경우
    • 페이지 권한에 대한 수정사항이 생긴 경우 가드만 바꿔주면 된다.
  • 단점
    • 홈 url(“/”)을 하나밖에 사용할 수 없다.
    • 권한을 삭제하는 경우가 생기면 가드들을 하나하나 찾아서 지워줘야 한다.
    • 권한이 복잡할 때 가드의 개수가 많아질 수 있다.
      • 권한 마다 가드가 필요하다.
      • 예시) 권한 1, 2만 보이는 페이지가 있으면 권한 1, 2를 체크하는 가드 필요
    • 같은 router상에 존재하기 때문에 강제로 url을 입력해서 접근하면 redirect 되기 전까지 private 페이지가 잠깐 보여질 수 있다.
      • 거의 체감이 되지 않을 정도이긴 하나, 인터넷이 느릴 때 발생할 수 있다.
      • 권한이 체크될 때 까지 렌더링 자체를 막는 방법을 사용해서 해결은 가능하다.