SUIN

유저 권한별 페이지 접근처리 방법을 고민해보자 본문

개발일지

유저 권한별 페이지 접근처리 방법을 고민해보자

choi suin 2024. 5. 28. 21:15
728x90

프로젝트에서는 구매자와 판매자 사이트를 구현하면서 페이지별로 접근 제한을 어떻게 설정할지에 대해 고민하게 되었습니다. 이 과정에서 다양한 방법을 시도해보았고 처음에는 기존에는 개별 페이지마다 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 방식을 변경하므로 다양한 이점이 생겼습니다.

  1. 중복 코드 제거가 가능했습니다.
    rotected Route 컴포넌트를 도입함으로 각 페이지마다 중복되던 로그인 체크 로직을 한 곳에 중앙 집중시킬 수 있었습니다. 이로써 코드의 중복을 제거하고 유지보수를 더욱 용이하게 만들었습니다.
  2. 중앙 관리와 일관성 유지가 가능해졌습니다.
    접근 제한 관련 로직이 한 곳에 집중되어 일관성을 유지하고, 새로운 기능 추가나 변경 시에도 효율적으로 대응할 수 있게 되었습니다.
  3. 확장성이 좋아졌습니다.
    인증된 사용자만 접근 가능한 페이지를 보호할 수 있었습니다. 앞으로 추가될 새로운 기능이나 페이지에 대해서도 쉽게 접근 제한을 적용할 수 있게 되었습니다.
  4. 코드 가독성이 향상되었습니다.
    각 페이지 컴포넌트에서는 핵심 기능에만 집중할 수 있게 되었습니다. 개발자들이 코드를 더 쉽게 이해하고 유지보수할 수 있게 되었습니다.

 

이러한 점들을 통해, Protected Route를 활용한 중앙 관리 방식은 프로젝트의 효율성과 유지보수성을 높이는데 큰 도움이 되었습니다. 이번 프로젝트를 통해 이러한 개선점들을 발견하고, 중앙 관리된 접근 방식의 중요성을 깨달을 수 있었습니다.]

 

프로젝트 보러가기 -> 

 

GitHub - whl5105/Team-adEarth-client-v2.0: [Team Project] CPC 키워드 광고를 적용한 이커머스 플랫폼

[Team Project] CPC 키워드 광고를 적용한 이커머스 플랫폼. Contribute to whl5105/Team-adEarth-client-v2.0 development by creating an account on GitHub.

github.com