React 프로젝트를 진행하면서 React-Router-Dom을 사용하게 되었는데, 기존에 사용했던 <BrowserRouter> 대신 <createBrowserRouter> 를 사용해 보기로 결정했다. 기존 <BrowserRouter> 에서는 사용자 인증 여부를 useState에 담아 일부분만 보여주는 식으로 페이지를 렌더링 했었는데 <createBrowserRouter> 사용자 인증 여부에 따라 보여줄 페이지를 결정하는 방법에 알아보면서 글을 남겨두면 좋을 것 같다는 생각이 들어 글을 쓰게 되었다.
BrowserRouter 사용자 인증 여부에 따른 페이지 렌더링
function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false)
return (
<div className="App">
<Router isAuthenticated={isAuthenticated} />
</div>
);
}
export default App;
const Router = ({ isAuthenticated }) => {
return (
<Routes>
{ isAuthenticated ? (
<>
<Route path="/" element={ <HomePage /> }/>
<Route path="/about" element={ <AboutPage /> }/>
<Route path="/admin" element={ <AdminPage /> }/>
</>
) : (
<Route path="/login" element={ <LoginPage /> }/>
)}
</Routes>
)
}
export default Router
사용자 인증 여부를 Props로 받아 유무에 따라 사용자 인증이 있다면, 루트, 어바웃, 어드민 페이지를 보여주고 사용자 인증이 없다면 로그인 페이지만 볼 수 있는 이러한 방식으로 사용자 인증 유무에 따른 페이지 렌더링을 했다.
createBrowserRouter 사용자 인증 여부에 따른 페이지 렌더링
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
기존 BrowserRouter 에서는 최상단을 감싸고 시작했지만, createBrowserRouter 에서는 RouterProvider 에 router 를 제공해 페이지를 렌더링 한다. 그래서 보통은 App 컴포넌트가 레이아웃의 역할을 한다. 따로 레이아웃 컴포넌트를 만들어도 상관없다.
function App() {
return (
<div className="App">
<Header />
<main>
<Outlet />
</main>
<Footer />
</div>
);
}
export default App;
const router = createBrowserRouter([
{
path: '/',
element: <App />,
errorElement: <ErrorPage />,
children: [
{ path: '/', element: <HomePage /> },
{ path: '/about', element: <AboutPage /> },
{ path: '/admin', element: <AdminPage /> },
{ path: 'login', element: <LoginPage />}
]
}
])
export default router
이러한 방식으로 작성하는데 사용자 유무를 Props 로 받아서 사용자 인증 여부를 파악했던 BrowserRouter 와 다르게 createBrowserRouter 는 Route 들 즉 children 페이지를 보여주기 전에 검사하는 과정을 거칠 수 있다. 사용자 인증유무를 검사하는 AuthenticatedRoute 를 만들고 사용자 인증 여부에 따라 페이지를 렌더링 할 수 있다.
- AuthenticateRoute 만들기
import { Navigate, Outlet } from "react-router-dom";
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { app } from '../firebaseApp';
import { useState, useEffect } from "react";
const AuthenticatedRoute = () => {
const auth = getAuth(app);
const [isAuthenticated, setAuthenticated] = useState(null); // 초기 상태를 null로 설정하여 로딩 상태 표시
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setAuthenticated(!!user); // 사용자가 있으면 true, 없으면 false로 설정
});
return () => unsubscribe(); // 컴포넌트 언마운트 시 구독 해제
}, [auth]);
if (isAuthenticated === null) {
return <div className="loader">Loading...</div>; // 인증 상태 확인 중 로딩 표시
}
return (
isAuthenticated ? <Outlet /> : <Navigate to='/login' replace />
);
}
export default AuthenticatedRoute;
나는 Firebase를 사용했기 때문에 onAuthStateChanged를 통해 사용자 인증 여부를 관찰하고, 사용자 인증이 되었다면 Outlet을 통해 AuthenticatedRoute의 children에 접근이 가능하고 사용자 인증이 되지 않았다면, Navigate를 통해 로그인 페이지로 리다이렉션되게 했다.
- router 수정하기
const router = createBrowserRouter([
{
path: '/',
element: <App />,
errorElement: <ErrorPage />,
children: [
{ path: '/', element: <HomePage /> },
{
path: '',
element: <AuthenticatedRoute />,
children: [
{ path: '/about', element: <AboutPage /> },
{ path: '/admin', element: <AdminPage /> },
]
},
{ path: '/login', element: <LoginPage />}
]
}
])
export default router
위와 같은 방식으로 수정하면 어바웃 페이지와, 어드민 페이지를 사용자 인증이 있을 때만 접근 할 수 있다. 이 내용과 관련된 블로그 글을 잘 작성해놓은 글을 추가로 첨부한다.
'Rroblem Solving' 카테고리의 다른 글
CRA(--template typescript)에서 alias 별칭 안되는 문제 eject 해보기 (0) | 2024.07.03 |
---|---|
audio 태그 자동 재생 해결 방안 및 크로스 브라우징 (0) | 2024.06.25 |
FIreStore에서 "\n" 개행 처리하는 방법 (0) | 2024.06.02 |
Objects are not valid as a React child~ 에러와 Typescript (0) | 2024.04.07 |
댓글