nextjs, supabase auth 관련 오류

이진호·2024년 1월 24일
1

최종프로젝트

목록 보기
12/18
post-thumbnail
post-custom-banner

nextjs에서 제공하는 middleware를 사용하여 supabase의 인증 access token을 쿠키로 넘겨줘야 했는데 이 부분에서 굉장히 애를 많이 먹었다.

결론적으로, 아래와 같은 내용들을 알게 됐다.

  • middleware는 prefetch를 하게 되면 해당 페이지로 넘어가도 다시 middlware에 들어오지 않는다
  • supabase의 auth-helper를 이용한다면 그냥 supabase client가 아닌 auth-helper에서 제공하는 client를 사용해야 한다. 그래야 자동으로 서버 사이드에서 cookie가 생성이 된다
  • supabase에서 에러가 발생하면 왜인지 모르겠지만 error를 뱉지 않는다..(실행조차 안됨...)

위 내용을 정리해서 코드를 작성한 내용은 다음과 같다

// middleware.ts
import { createMiddlewareClient } from "@supabase/auth-helpers-nextjs";
import { NextRequest, NextResponse } from "next/server";

export async function middleware(request: NextRequest) {
  const response = NextResponse.next();

  const supabase = createMiddlewareClient({ req: request, res: response });

  const {
    data: { session },
  } = await supabase.auth.getSession();

  const { pathname } = request.nextUrl;

  if (
    !session &&
    (pathname.startsWith("/dashboard") || pathname.startsWith("/metaverse"))
  ) {
    console.log("세션이 없는데 dashboard, metaverse에 들어옴");
    return NextResponse.redirect(new URL("/signin", request.nextUrl.basePath));
  }

  if (
    session &&
    (pathname.startsWith("/signin") || pathname.startsWith("/signup"))
  ) {
    console.log("세션은 있는데 signin singup 페이지에 들어옴");
    return NextResponse.redirect(new URL("/", request.nextUrl.basePath));
  }

  return response;
}

export const config = {
  matcher: [
    "/dashboard/:path*",
    "/metaverse/:path*",
    "/signin/:path",
    "/signup/:path",
  ],
};
// checkUserSession 컴포넌트
import { getUserSessionHandler } from "@/api/supabase/auth";
import { supabase } from "@/supabase/supabase";
import useAuth from "@/zustand/authStore";
import { useEffect } from "react";

export default function CheckUserSession() {
  const { logout, login } = useAuth();

  useEffect(() => {
    const channel = supabase.auth.onAuthStateChange((event, session) => {
      console.log(event);
      if (event === "INITIAL_SESSION" || event === "SIGNED_IN") {
        if (!session) return;
        getUserSessionHandler(session)
          .then((user) => {
            login(user);
          })
          .catch((error) => {
            console.log(error);
          });

        // 여기가 실행이 안됨
      } else if (event === "SIGNED_OUT") {
        logout();
      }
    });

    return () => {
      channel.data.subscription.unsubscribe();
    };
  }, []);

  return <></>;
}

export const getServerSideProps = async () => {
  return {
    props: {},
  };
};
// auth.ts 
export const getUserSessionHandler = async (session: Session): Promise<any> => {
  
  const { data: currentUserInfo, error } = await supabase
    .from("users")
    .select(`*`)
    .eq("id", session.user.id!)
    .single();

  if (error) return Promise.reject(error); // 여기서 오류를 제대로 뱉질 않는다
  
  return currentUserInfo;
};
profile
dygmm4288
post-custom-banner

0개의 댓글