Next.js Middleware를 사용하여 유저정보 유무에 따라 리다이렉트 시키기

Ji Won·2024년 5월 11일
post-thumbnail

프로잭트를 하면서 가장 골머리를 앓았던 부분을 정리해보고자 한다.

로그인 된 유저와 로그인 되지 않은 유저를 분리하여 각자 접근할 수 있는 페이지를 나누고자 했다.
ex)마이페이지 등

기존엔 아래와 같이 각각의 privateRouteWarpper와 publicRouteWrapper를 만든 후 해당 컴포넌트로 라우팅처리가 필요한 컴포넌트를 감싸주는 방식으로 코드를 구성했다.

  • 기존 코드
privateRouteWrapper.tsx

function PrivateRouteWrapper({ children }: { children: React.ReactNode }) {
  const { errorTopRight } = useToast();
  const user = useAuth((state) => state.user);
  const router = useRouter();
  if (!user) {
    errorTopRight({ message: '로그인이 필요한 페이지입니다' });
    router.push('/auth/login');
    return null;
  }

  return children;
}



export default PrivateRouteWrapper;
login.tsx

const PublicLoginPage = () => {
  return (
    <PublicRouteWrapper>
      <LoginPage />
    </PublicRouteWrapper>
  );
};

  • 리다이렉트 될 때 화면


이와같이 구성했을때 기능상에는 크게 문제가 없었지만 라우팅처리가 필요한 모든 페이지에 위와 같은 처리를 해줘야 해서

1) 코드가 여기저기 분산되어 관리가 어려웠고
2) 화면에서 라우팅 처리될 때 미세한 깜빡임이 나타나 UI상 좋지 않아보인다

는 사소한 문제가 있었다.



이러한 문제를 어떻게 개선할지 할지 방법을 찾아보다가 Next.js에서 제공하는 Middleware 의 존재를 알게되어 도입하기로 했다.

  • 개선한 코드
Middleware.ts

export async function middleware(req: NextRequest) {
  const res = NextResponse.next();
  const cookie = res.cookies.get('sb-mbcnyqlazlnrnrncctns-auth-token')?.value;

  // Create a Supabase client configured to use cookies
  const supabase = createMiddlewareClient<Database>({ req, res });
  const { pathname } = req.nextUrl;

  // 현재 세션 정보 가져오기
  const { data } = await supabase.auth.getSession();

  // 리다이렉트 부분 : 멍스타그램 작성/수정, 중고물품 작성/수정, 마이페이지
  if (data.session !== null && pathname.startsWith('/auth')) {
    return NextResponse.redirect(new URL('/', req.url));
  }
  if (data.session === null && pathname.startsWith('/profile')) {
    return NextResponse.redirect(
      new URL('/auth/login?alert=로그인 후 이용가능한 서비스입니다', req.url)
    );
  }
  if (data.session === null && pathname.startsWith('/used-goods/create')) {
    return NextResponse.redirect(
      new URL('/auth/login?alert=로그인 후 이용가능한 서비스입니다', req.url)
    );
  }
  if (data.session === null && pathname.startsWith('/used-goods/update')) {
    return NextResponse.redirect(
      new URL('/auth/login?alert=로그인 후 이용가능한 서비스입니다', req.url)
    );
  }
  if (data.session === null && pathname.startsWith('/mungstagram/create')) {
    return NextResponse.redirect(
      new URL('/auth/login?alert=로그인 후 이용가능한 서비스입니다', req.url)
    );
  }

  return res;
}

export const config = {
  matcher: [
    '/facilities',
    '/used-goods/create',
    '/profile',
    '/used-goods/update/:path*',
    '/mungstagram/create',
    '/auth/login',
    '/auth/signup'
  ]
};

원래는 프론트엔드에서 받아오는 유저정보에 접근하고자 했으나 middleware의 경우 서버컴포넌트로 간주되기 때문에 프론트엔드에서 받아오는 user정보를 끌어올 수 없었다.

그렇기에 보통은 로그인정보를 cookie에 저장후 cookie에 접근하여 라우팅처리를 하도록 하는게 일반적이라고 한다.

하지만 내가 Bass로 사용하고 있던 Supabase에서는 Next.js 전용 라이브러리를 제공하여 Middleware에서 Session에 직접 접근할 수 있도록 지원하고 있었다.

나는 이 부분을 사용하여 Middleware에서 직접 session에 접근하여 session안에 제공되는 user의 정보 유무에 따라 라우팅 처리를 할 수 있도록 했다.


  • 코드 개선 후 화면

그 결과 각 Wrapper들과 각 컴포넌트의 불필요한 코드를 삭제하고 Middleware에서 코드를 중앙관리할 수 있도록 했으며 라우팅 처리될 때 화면상의 미세한 깜빡임도 없어져서 UX상 조금 더 나은 결과를 얻어낼 수 있었다.

profile
1인분 하고 싶은 코린이

0개의 댓글