[React+Typescript] Private Router(react-router-dom v6)

anonymous-planet·2022년 4월 30일
11

React+Typescript

목록 보기
1/6

내게 Private Router가 필요했던 이유

  • 반드시 인증(로그인)을 해야만 접근 가능한 페이지(마이 페이지 등)
  • 반드시 인증(로그인)을 하지 않아야만 접근 가능한 페이지(로그인, 회원가입 페이지 등)

위와 같이 페이지의 구분이 생겨 인증(로그인) 여부에 대해 체크를 해주는 부분을 Private Router에서 해주었다.

Private Router의 역할

EX1)
로그인한 사용자가 URL을 통해 로그인 페이지로 진입했을 경우 접근을 못하도록 막아 주어야 한다

EX2)
로그인하지 않은 사용자가 회원만 접근 가능한 마이페이지에 URL을 통해 진입했을 경우 접근을 못하도록 막아 주어야 한다

간단한 예제

PrivateRouter.tsx

import { ReactElement } from 'react';
import { Navigate, Outlet } from 'react-router-dom';


interface PrivateRouteProps {
  children ?: ReactElement; // Router.tsx에서 PrivateRoute가 감싸고 있는 Componet Element
  authentication : boolean; // true :인증을 반드시 해야하만 접속가능, false : 인증을 반디스 안해야만 접속 가능
}


export default function PrivateRoute({authentication}:PrivateRouteProps):React.ReactElement|null {

  /**
   * 로그인 했는지 여부
   * 로그인 했을 경우 : true 라는 텍스트 반환
   * 로그인 안했을 경우 : null or false(로그아웃 버튼 눌렀을경우 false로 설정) 반환
   */
  const isAuthenticated = sessionStorage.getItem("isAuthenticated");

  if(authentication) {
    // 인증이 반드시 필요한 페이지
  
    // 인증을 안했을 경우 로그인 페이지로, 했을 경우 해당 페이지로
    return (isAuthenticated === null || isAuthenticated === 'false') ? <Navigate to="/login"/> : <Outlet/>;

  } else {
    // 인증이 반드시 필요 없는 페이지

    // 인증을 안햇을 경우 해당 페이지로 인증을 한 상태일 경우 main페이지로
    return (isAuthenticated === null || isAuthenticated === 'false') ? <Outlet/> : <Navigate to='/'/>;  
  }
}

Router.tsx

import {BrowserRouter, Routes, Route} from 'react-router-dom';
import LoginPage from '../pages/LoginPage';
import MainPage from '../pages/MainPage';
import MyPage from '../pages/MyPage';
import PrivateRoute from './PrivateRoute';


export default function Router() {

  return (
    <BrowserRouter>
      <Routes>

        {/* 인증 여부 상관 없이 접속 가능한 페이지 정의 */}
        <Route index element={<MainPage/>}/>

        {/* 인증을 반드시 하지 않아야만 접속 가능한 페이지 정의 */}
        <Route element={<PrivateRoute authentication={false}/>}>
          <Route path="/login" element={<LoginPage/>} />
        </Route>

        {/* 인증을 반드시 해야지만 접속 가능한 페이지 정의 */}
        <Route element={<PrivateRoute authentication={true}/>}>
          <Route path="/mypage" element={<MyPage/>} />
        </Route>
      </Routes>
    </BrowserRouter>
  )
}

App.tsx

import Router from './routes';

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

export default App;

MainPage.tsx

import { useState } from 'react';
import { useNavigate } from 'react-router';

export default function MainPage() {
  // const isAuthenticated = sessionStorage.getItem('isAuthenticated');
  const [isAuthenticated, setIsAuthenticated] = useState<string|null>(sessionStorage.getItem('isAuthenticated'));
  const navigate = useNavigate();

  return (
    <>
      <h1>Main Page</h1>
      <div>로그인 여부 상관없이 누구나 접속 가능!</div>
      {
        isAuthenticated === null || isAuthenticated === 'false' ? <button onClick={()=>{
          navigate("/login");
        }}>로그인</button>: <div><button onClick={()=>{
          setIsAuthenticated("false");
          sessionStorage.setItem('isAuthenticated', "false");
        }}>로그아웃</button><button onClick={() => {navigate("/mypage")}}>myPage로 이동</button></div>
      }
    </>
  );
}

LoginPage.tsx

import { useNavigate } from 'react-router';

export default function LoginPage() {
  const navigate = useNavigate();
  return (
    <>
      <h1>Login Page</h1>
      <div>로그인 하지 않아야만 접속 가능</div>
      <button onClick={() => {
        sessionStorage.setItem('isAuthenticated', 'true');
        // 메인으로 이동
        navigate("/")
      }}>로그인 하기</button>
    </>
  )
}

MyPage.tsx

export default function MyPage() {

  return(
    <>
      <h1>My Page</h1>
      <div>로그인해야만 접속 가능</div>
    </>
  )
}

github : https://github.com/anonymous-planets/anonymous-planet-react

profile
취미로 Front-End를 즐기는 Back-End개발자 입니다.

4개의 댓글

comment-user-thumbnail
2022년 10월 11일

해당 내용 찾고있었는데 친절한 게시글 감사합니다‼️

1개의 답글
comment-user-thumbnail
2023년 5월 29일

딱 찾던 내용인데 덕분에 배워갑니다 ㅎㅎ 감사합니다!!

1개의 답글