웹사이트를 작성하다 보면 '로그인 한' 혹은 '관리자만' 혹은 그 외의 제한적으로 접근 가능한 페이지를 구현할 필요가 생깁니다.
여러 시행착오를 겪으며 제가 현재 사용중인 방법을 소개하고자 합니다.
// RestrictRoute.tsx
import React, { FC } from "react";
interface Props {
path: string | string[];
component: FC;
fallback: FC;
exact?: boolean;
isAllow: (user: User) => boolean;
}
export const RestrictRoute = ({
component: Component,
fallback: Fallback,
isAllow
}: Props) => {
const user = useUser();
return isAllow(user) ? <Component /> : <Fallback />;
};
RestrictRoute
컴포넌트는 해당 페이지에 접근하면 인증 여부에 따라 컴포넌트이며, 기본 4개의 Props와 1개의 추가적인 Props를 받습니다.
path
는 경로를 의미하며 React Router 기반으로 사용하던 경로를 그대로 사용할 수 있습니다.
component
는 인증 성공시의 컴포넌트입니다.
fallback
은 인증 실패시의 컴포넌트입니다.
exact
는 정확히 일치하는 경로일 때에만 컴포넌트를 렌더링 할지 결정합니다.
isAllow
함수는 인증 여부를 판정하는 역할을 합니다.
useUser는 예시일 뿐이니, User 뿐만 아니라 더 많은 데이터를 가진 무엇인가를 isAllow 함수의 파라미터로 전달해도 괜찮습니다.
이 컴포넌트에는 path와 exact를 사용하는 부분이 없는데, 이 부분은 잠시 후 소개하겠습니다.
// App.tsx
import React from "react";
import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import { RestrictRoute } from "./RestrictRoute";
const GoToMainPage = () => <Redirect to="/" />;
const App = () => (
<BrowserRouter>
<Switch>
<Route path="/" component={MainPage} />
<RestrictRoute
path="/sign-in"
component={SignInPage}
fallback={GoToMainPage}
exact
isAllow={user => user.isSignedIn}
/>
<RestrictRoute
path="/sign-up"
component={SignUpPage}
fallback={GoToMainPage}
exact
isAllow={user => user.isSignedIn}
/>
{/* ... */}
{/* ... */}
{/* ... */}
<Redirect to="/" />
</Switch>
</BrowserRouter>
);
실제 사용은 위처럼 할 수 있습니다.
이미 로그인을 한 유저가 로그인(/sign-in
) 페이지 혹은 회원가입(/sign-up
) 페이지에 접근할 필요는 없을테니, 로그인 여부를 확인한 후 로그인을 이미 했다면 메인(/
) 페이지로 이동시킵니다.
React Router
의 Switch
컴포넌트는 바로 하위 컴포넌트를 순회하면서 path
와 exact
조건을 만족하면 전달 받은 component를 바로 렌더링 합니다.
이것을 이용하기 위해 RestrictRoute
컴포넌트는 path
와 exact
를 받는 것입니다.
// App.tsx
import React from "react";
import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import { RestrictRoute } from "./RestrictRoute";
const GoToMainPage = () => {
alert("관리자만 접근 가능한 페이지입니다.");
return <Redirect to="/" />;
};
const App = () => (
<BrowserRouter>
<Switch>
{/* ... */}
{/* ... */}
{/* ... */}
<RestrictRoute
path="/admin"
fallback={GoToMainPage}
component={AdminPage}
isAllow={user => user.isAdmin}
/>
{/* ... */}
{/* ... */}
{/* ... */}
</Switch>
</BrowserRouter>
);
관리자만 접속 가능한 페이지인 경우도 간단하게 구현할 수 있습니다.
관리자가 아니면 alert(Toast 등도 가능!)로 관리자만 접근 가능한 페이지라고 알릴 수도 있습니다.
interface 선언을 제외하면 몇 라인 되지 않는 이 간단한 컴포넌트는 다양한 요구사항을 만족시킬 수 있습니다.
응용하기에 따라 더 많은 유연성을 확보할 수 있기도 합니다.
이 아이디어가 여러분을 도울 수 있기를 바랍니다.
Nice info. Thanks for sharing.
https://www.visualpath.in/ReactJs-Training-in-Hyderabad.html
좋아요 감사합니다!