우선 라우터에서 로그인 안해도 볼 수 있는 페이지, 로그인 해야만 볼 수 있는 페이지로 중첩 라우팅을 구성한다.
<BrowserRouter>
<Provider store={store}>
<Routes>
<Route path="/" element={<NonAuthLayout />}>
<Route path="login" element={<LoginPage />} />
</Route>
<Route path="/" element={<AuthLayout />}>
<Route path="home" element={<Home />} />
<Route path="myPage" element={<MyPage />} />
<Route path="details/:id" element={<LetterDetailPage />} />
</Route>
</Routes>
</Provider>
</BrowserRouter>
+ Outlet 이해하기
부모 라우트 컴포넌트 안에 그 레이아웃 스타일을 상속할 자식 라우트 컴포넌트를 작성한다.
그런 다음 그 자식 라우트들을 렌더링할 곳에 Outlet으로 받으면 된다.
따라서 AuthLayout에서 Outlet으로 받으면 Home, MyPage, LetterDetailPage가 렌더링 되고
NonAuthLayout에서 Outlet으로 받으면 Loginpage가 렌더링 된다.
그런 다음 AuthLayout에서는 로그인 상태를 검사하여 만약 로그인상태가 아닐 경우 login페이지로 네비게이트하고 return으로 실행을 끝낸다.
로그인이 되지 않았을 때 페이지의 내용을 보여주지 않게 하기 위해(보안 이슈) isRendered 불린값을 이용하여 useEffect 실행이 완료된 후 컴포넌트들을 렌더링하도록 한다.
// AuthLayout - 로그인이 필요한 페이지
function AuthLayout() {
// 중략
useEffect(() => {
if (!accessToken) {
alert('잘못된 접근입니다.');
navigate('/login');
return;
}
//useEffect가 실행된 후 컴포넌트 렌더링(보안을 위해)
// 1. 브라우저 렌더링 -> useEffect 실행 -> isRendered = true -> 컴포넌트 렌더링됨
setIsRendered(true);
}, [accessToken, navigate]);
return (
<MainWrap>
<ResetStyles />
<LayoutWrap>
{isRendered && <NavHeader />}
<Header />
{isRendered && <Outlet />}
</LayoutWrap>
</MainWrap>
);
}
export default AuthLayout;
마찬가지로 NonAuthLayout에서는 로그인 상태일 경우 home으로 이동하도록 한다.
// NonAuthLayout - 로그인이 필요하지 않은 페이지
function NonAuthLayout() {
// 중략
useEffect(() => {
if (accessToken) {
navigate('/home');
}
setIsRendered(true);
}, [isRendered, navigate, accessToken]);
return (
<MainWrap>
<ResetStyles />
<LayoutWrap>
<Header />
{isRendered ? <Outlet /> : null}
</LayoutWrap>
</MainWrap>
);
}
export default NonAuthLayout;
두 레이아웃을 설정함으로써 로그인 상태에 따라 다른 레이아웃 스타일을 적용할 수 있다.
예를 들어 NonAuthLayout에서 Header를 지운다던지
'Today I Learned' 카테고리의 다른 글
개발자 도구로 디버깅하기 (0) | 2024.02.21 |
---|---|
파일 탐색기 버튼 input type='file' 커스텀하여 사용하기 (0) | 2024.02.21 |
2024.02.19 TIL (0) | 2024.02.19 |
2024.02.16 TIL (0) | 2024.02.16 |
2024.02.15 TIL (1) | 2024.02.16 |