일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Node
- NVM
- JavaScript
- Client-Side Navigation
- JS
- CPU와 GPU의 차이점
- 광고지구
- 회고록
- git
- Passed by Value
- next/link
- input error
- CloudFront 무효화
- 유령 의존성
- 식별자란
- react portal
- Mac OS NVM
- Redux
- toast err
- 알고리즘
- 원티드프리온보딩
- 원티드인턴십
- Til
- react
- 원티트 프리온보딩인턴십 1주차
- NextJs
- 프로젝트
- 인풋태그 엔터
- jsEvent Loop
- 향해99
- Today
- Total
SUIN
유저 권한별 페이지 접근처리 방법을 고민해보자 본문
프로젝트에서는 구매자와 판매자 사이트를 구현하면서 페이지별로 접근 제한을 어떻게 설정할지에 대해 고민하게 되었습니다. 이 과정에서 다양한 방법을 시도해보았고 처음에는 기존에는 개별 페이지마다 useEffect를 사용하여 접근 제한을 구현했으나, 이번에 이를 개선하여 Protected Route 컴포넌트를 활용한 중앙 관리 방식으로 전환했습니다.
문제 의식
각 구매자와 판매자의 접근 범위가 조금은 다릅니다. 예를들어 구매자는 로그인했을 경우 보여주어야하는 추가적인 페이지와 정보들이 필요하지만, 판매자의 경우 전체 서비스를 로그인된 사용자만이 접근할 수 있도록 설정해야 했습니다. 이러한 요구 사항을 충족시키기 위해 각 페이지별 로그인 유저의 접근 제한을 설정할 필요가 있었습니다.
📌 유저의 접근 제한을 확인하는 페이지 종류와 관련하여 다음과 같은 항목을 고려할 수 있습니다
판매자 : 모든 페이지에 로그인된 판매자만 접근가능
구매자 : 로그인된 사용자만 마이페이지(주문내역,주문취소), 장바구니페이지,결제페이지(결제진행, 결제완료) 접근가능
❎ 기존 접근 방식의 문제점
기존에는 다음과 같이 각 페이지 컴포넌트에서 useEffect를 사용하여 로그인 여부를 확인하고 로그인되지 않은 사용자를 리다이렉트하는 방식을 사용했습니다.
// .. import ...
const MyPage = () => {
const navigate = useNavigate();
const isLogin = useGetLocalStorage("token");
/** login check */
useEffect(() => {
if (isLogin) return;
navigate("/");
}, [isLogin]);
return (
<>
{isLogin && (
<MypageWrap>
<Nav>
<AsideNav />
</Nav>
<Section>
<UserHeadInfo />
<Outlet />
</Section>
</MypageWrap>
)}
</>
);
};
export default MyPage;
기존 방식의 문제점은 각 페이지마다 로그인 체크 로직을 중복 작성해야 했고, 이 로직이 여러 곳에 분산되어 있어 수정이나 업데이트가 어렵다는 점입니다. 또한, 접근 제한 로직이 중앙에서 관리되지 않아 코드의 일관성이 떨어졌습니다.
✅ 개선된 접근 방식→ Protected Route 구현
이 문제를 해결하기 위해 Protected Route 컴포넌트를 도입했습니다. 이 컴포넌트는 특정 경로에 접근하려는 사용자의 로그인 상태를 중앙에서 확인하고, 적절히 리다이렉트해주는 역할을 합니다.
ProtectedRoute 컴포넌트
Protected Route는 사용자의 인증 상태를 확인하고, 인증되지 않은 경우 로그인 페이지로 리다이렉트합니다.
//..import ..
interface IProps {
children: React.ReactNode;
redirectPath?: string;
}
const getLocalStorage = (name: string): string | null =>
localStorage.getItem(name);
const getIsToken = () => !!getLocalStorage('token');
export default function ProtectedRoute({ children, redirectPath }: IProps) {
const dispatch = useAppDispatch();
const isAuth = useAppSelector(state => state.authSlice.isAuth);
const isToken = getIsToken();
useEffect(() => {
if (isToken) {
dispatch(setAuth({ isAuth: true }));
} else return;
}, []);
if (!isAuth && !isToken) {
return <Navigate to={redirectPath} replace />;
}
return children ? <>{children}</> : <Outlet />;
}
라우터 설정
// .. import ..
export const routerData: RouterBase[] = [
{
id: 0,
path: '/',
element: <MainPage />,
withAuth: false,
},
{...}
{
id: 6,
element: <MyLayout />,
withAuth: true,
redirectPath: '/',
},
{
id: 7,
path: 'cart',
element: <CartPage />,
withAuth: true,
redirectPath: '/',
},
{...}
];
const Router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<Layout />}>
{routerData.map(router => {
if (router.withAuth) {
return (
<Route
key={router.id}
path={router.path}
element={
<ProtectedRoute redirectPath={router.redirectPath}>
{router.element}
</ProtectedRoute>
}
>
)}
</Route>
);
} else {
return (
<Route
key={router.id}
path={router.path}
element={<>{router.element} </>}
/>
);
}
})}
</Route>
)
);
export default Router;
routerData 라는 각페이지의 라우터 설정을 객체 형식으로 정의 후 withAuth 에서 유저의 로그인 상태를 확인해야하는 페이지 의 경우 로그인된 사용자가 아니라면 redirectPath 로 경로 이동을 해주는 방식을 적용했습니다.
Protected Route 방식을 변경하므로 다양한 이점이 생겼습니다.
- 중복 코드 제거가 가능했습니다.
rotected Route 컴포넌트를 도입함으로 각 페이지마다 중복되던 로그인 체크 로직을 한 곳에 중앙 집중시킬 수 있었습니다. 이로써 코드의 중복을 제거하고 유지보수를 더욱 용이하게 만들었습니다. - 중앙 관리와 일관성 유지가 가능해졌습니다.
접근 제한 관련 로직이 한 곳에 집중되어 일관성을 유지하고, 새로운 기능 추가나 변경 시에도 효율적으로 대응할 수 있게 되었습니다. - 확장성이 좋아졌습니다.
인증된 사용자만 접근 가능한 페이지를 보호할 수 있었습니다. 앞으로 추가될 새로운 기능이나 페이지에 대해서도 쉽게 접근 제한을 적용할 수 있게 되었습니다. - 코드 가독성이 향상되었습니다.
각 페이지 컴포넌트에서는 핵심 기능에만 집중할 수 있게 되었습니다. 개발자들이 코드를 더 쉽게 이해하고 유지보수할 수 있게 되었습니다.
이러한 점들을 통해, Protected Route를 활용한 중앙 관리 방식은 프로젝트의 효율성과 유지보수성을 높이는데 큰 도움이 되었습니다. 이번 프로젝트를 통해 이러한 개선점들을 발견하고, 중앙 관리된 접근 방식의 중요성을 깨달을 수 있었습니다.]
'개발일지' 카테고리의 다른 글
[React] 독립적인 DOM 노드로 렌더링하기. with React Portal (0) | 2024.06.07 |
---|