HOC 패턴으로 보호된 라우트 레이아웃 컴포넌트 구현 Thumbnail

사용자 검증 로직을 추상화하고 재사용해보자

4 min read
HOC

HOC 패턴으로 보호된 라우트 구현

반복되는 인가된 사용자 검증 로직을 추상화하고 재사용해보자

프리뷰 썸네일프리뷰 썸네일

문제 상황

사용자의 인증 여부가 필요한 페이지들은 늘어나지만, 항상 같은 로직을 사용하는 코드가 있었다. 바로 인증 여부를 검증하는 로직이다. 사용자가 로그인한 상태라면 허용하고 아니라면 거부하는 로직이 중복되고 있었기 때문에 이를 분리하고 재사용할 방법을 찾아본다.

고민한 점

어떻게 코드를 분리할 수 있을까? 단순히 커스텀 훅을 사용하는 방법도 있을 것 같다.

예를 들어 useAuthCheck 훅을 만들어, isLoggedIn 상태를 가져와 여부에 따른 toast 메시지 처리 등을 하나의 훅으로 만들어 분리해볼 수 있을 것이다.

하지만 더 깔끔한 방법을 시도해보고 싶었다. HOC 패턴을 사용해서.

HOC 패턴은 쉽게 이야기하면 컴포넌트를 감싸는 컴포넌트, Nextjs에서의 layout.tsx와 같은 역할을 하는 패턴이다. HOC패턴은 보통 아래와 같은 형식이다. 핵심은 children을 받아서 그대로 렌더링하고, 핵심 로직의 중복을 분리하는 것이다.

const HOCPattern = ({children:React.ReactNode}) => {
	return <div>{children}</div>
}

const Page = () => {
	return <HOCPattern>
		<div>
			<h1>안녕하세요</h1>
		</div>
	</HOCPattern>
}

주요 기능

아래는 우리 서비스에서 인증 검증 로직을 분리한 코드이다. 인가 여부 검증을 하는 코드를 하나의 레이아웃 컴포넌트에 분리되어있으며, 이제 재사용하기만 하면 된다.

import { useEffect } from "react";
import useAuth from "@hooks/useAuth.ts";
import useToast from "@hooks/useToast.ts";
import { useLocation, useNavigate } from "react-router-dom";

interface ProtectedRouteLayoutProps {
  children: React.ReactNode;
}

const ProtectedRouteLayout = ({ children }: ProtectedRouteLayoutProps) => {
  const { isLoggedIn } = useAuth();
  const toast = useToast();
  const location = useLocation();
  const navigate = useNavigate();

  useEffect(() => {
    if (!isLoggedIn) {
      toast.error("로그인이 필요한 서비스입니다.");
      navigate("/login", { state: { from: location }, replace: true });
    }
  }, [isLoggedIn]);

  return <>{children}</>;
};

export default ProtectedRouteLayout;

재사용하는 예시는 아래와 같다. ProtectedRouteLayout을 사용하여 감싸기만 하면 된다. 이제 CreateQuestionPage는 인증해야 접근 가능한 페이지가 된다.

  {
    element: (
      <ProtectedRouteLayout>
        <CreateQuestionPage />
      </ProtectedRouteLayout>
    ),
    path: "/questions/create",
  },
  {
    element: <ErrorPage />,
    path: "/*",
  },

이전에 계속 반복되는 로직을 분리했기 때문에 개발 생산성이 크게 올랐다.

📌 Table of Contents

0
추천 글