MEI

Next.js Supabase 세팅 및 Auth (1) 구글 로그인 본문

TECH

Next.js Supabase 세팅 및 Auth (1) 구글 로그인

mei.zy 2025. 5. 14. 18:25

Next.js 프로젝트에 Supabase 를 이용하기로 했습니당.

로그인까지 넣어보았는데 너무 쉽고 공식 문서가 잘되어있어서 재밌게 했습니다 .. 👍

폴더 구조들은 현재 fsd 방식으로 가져가고 있어서 공식 문서에서 제안해주는 방식과 다를 수 있습니다.

프로젝트는 Next.js 15버전(app router)과 typescript를 사용하고 있습니다 !

초기 세팅

Build a User Management App with Next.js를 참고했습니다.

설치

npm install @supabase/supabase-js @supabase/ssr

서버 컴포넌트거나 서버 액션 등등 서버와 관련된 기능을 사용하지 않으신다면 server.ts 파일은 스킵해주어도 괜찮습니다.

 

 

src/shared/lib/supabase/client.ts

import { createBrowserClient } from "@supabase/ssr";

export function createClient() {
  return createBrowserClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!);
}

 

src/shared/lib/supabase/server.ts

import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";

/**
 * Next.js의 App Router과 Server Component 환경
 */
export async function createClient() {
  const cookieStore = await cookies();

  return createServerClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, {
    cookies: {
      getAll() {
        return cookieStore.getAll();
      },
      setAll(cookiesToSet) {
        try {
          cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options));
        } catch {
          // The `setAll` method was called from a Server Component.
          // This can be ignored if you have middleware refreshing
          // user sessions.
        }
      },
    },
  });
}

 

서버 컴포넌트를 사용할때는 쿠키를 쓸 수 없기 때문에 추가적으로 next.js의 middleware 설정이 필요하다.

 

서버 컴포넌트는 html을 미리 생성해주는 컴포넌트이기 때문에 쿠키를 읽을 순 (read) 있지만, 쓰는 것 (write)는 불가능하다.

supabase는 jwt 기반의 쿠키를 통해 로그인 유무를 체크하고 있는데, 서버 컴포넌트에서는 불가능하니까 이 작업을 Middleware 에게 위임을 해주게 된다. 

=> 미들웨어가 대신 토큰을 갱신하고 쿠키를 설정 ! server.ts 파일에서는 쿠키에서 토큰을 읽기만 한다.

 

src/shared/lib/supabase/middleware.ts

import { createServerClient } from "@supabase/ssr";
import { type NextRequest, NextResponse } from "next/server";

export async function updateSession(request: NextRequest) {
  let supabaseResponse = NextResponse.next({
    request,
  });
  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll();
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value));
          supabaseResponse = NextResponse.next({
            request,
          });
          cookiesToSet.forEach(({ name, value, options }) => supabaseResponse.cookies.set(name, value, options));
        },
      },
    },
  );
  // refreshing the auth token
  await supabase.auth.getUser();
  return supabaseResponse;
}

 

 

middleware.ts

import { type NextRequest } from "next/server";

import { updateSession } from "@/shared/lib/supabase/middleware";

export async function middleware(request: NextRequest) {
  // update user's auth session
  return await updateSession(request);
}
export const config = {
  matcher: [
    "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
  ],
};

이렇게 세팅해두면 supabase를 쓸 준비가 완료됩니다. 이건 공식문서에서 나온 스탭대로 따라한거니까 어렵지 않았습니다.
저는 구글/카카오 로그인과 같은 소셜 로그인을 프로젝트에서 사용할 것이기 때문에 auth 쪽을 먼저 보면 될 것 같습니다.

 

 

1. 구글 클라우드 등록

console.cloud.google.com 에 접속해서 프로젝트를 선택해줍니다.

(먼저 만들어놓은 구글 클라우드 프로젝트가 있어서 이걸로 이용하려고 합니다)

API 및 서비스 > OAuth 동의 화면에 들어가서 먼저 만들어줍니다.

 

사내 서비스가 아니기 때문에 [외부]를 선택해주었습니다.

 

 

 만들고 나면, 클라이언트 쪽으로 이동해서 신규 클라이언트를 만들어줍니다.

 

 

그리고 어느 범위의 데이터를 엑세스 할 것인지 선택이 가능한데 일단은 email 정보만 필요해서 그걸로 넣었는데 다양하게 제공하고 있으니까 필요한 범위대로 저장해주시면 될 것 같아요 !

 

2. Supabase Auth Provider 등록

supabase에 접속해서 Provider를 등록해줍니다. google 이 disabled 로 처리 되어 있을 것 같은데 enabled로 변경해줍니다.

 

그럼 이런 화면이 뜨게 되는데, Client IDS 랑 password 는 구글 클라우드에있습니다.

아까 만들었던 클라이언트 탭 상세에 들어가서 복사해서 붙여넣어줍니다

 

 

supabase 의 client IDs 에 복붙해주고, secret 에 복붙해줍니다.

 

그리고 여기 있는 callback URL 은 복사해서 다시 구글 클라우드에 넣어줍니다.

 

 

이게 구글 로그인의 세팅 끝입니다.

 

3. 코드 작성

server action을 사용해주기로 했습니당.

 

src/app/signIn/page.tsx

import { signInGoogle } from "./actions";

const SignInPage = () => {
  return (
    <form>
      <button formAction={signInGoogle}>구글로 로그인</button>
    </form>
  );
};

export default SignInPage;

 

 

src/app/signIn/actions.ts

"use server";

import { Provider } from "@supabase/supabase-js";
import { redirect } from "next/navigation";

import { createClient } from "@/shared/lib/supabase/server";

export const signIn = async (provider: Provider, redirectUrl: string): Promise<void> => {
  const supabase = await createClient();

  const { data, error } = await supabase.auth.signInWithOAuth({
    provider,
    options: {
      redirectTo: redirectUrl,
    },
  });

  redirect(data.url as string);
};

export const signInGoogle = async () => signIn("google", process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_CALLBACK as string);

 

 

이렇게 하면 끝입니다 😮

항상 프로젝트를 진행하면서 회원가입/로그인이 가장 어려웠던 부분인데 너무 쉽게 되는 것 같아서 놀랐습니당.. 그리고 문서도 너무 잘되어있어요. 근데 구글 클라우드도 왔다갔다해야해서 공식 문서론 안될 것 같고, 다른 블로그들도 참고해서 보았습니다.

 

https://supabase.com/docs/guides/auth/social-login/auth-google#application-code

 

Login with Google | Supabase Docs

Use Sign in with Google on the web, in native apps or with Chrome extensions

supabase.com

 

 

 

문서는 이쪽을 보았어용. 서버액션을 처음 써봐서 신기했어용.. ☺️