Next.js에서 Clerk.js 사용하여 구글 연동 로그인 만들기

 

Clerk | Authentication and User Management

The easiest way to add authentication and user management to your application. Purpose-built for React, Next.js, Remix, and “The Modern Web”.

clerk.com

✨Clerk.js ?

clerk.js 라이브러리는 로그인 구현을 도와주는 무료 JS라이브러리입니다.

clerk.com 홈페이지의 메인 화면에는 인증 뿐만 아니라, 유저 매니징까지 할 수 있는 라이브러리라고 소개하는데요, React, Next.js 뿐만 아니라 다양한 프레임워크, 바닐라 JS에서도 사용할 수 있는 도구라고 합니다!

clerk.js는 정말 간단하게 로그인을 구현할 수 있다는 장점이 있습니다. 그러면 바로 하나 만들어보겠습니다!

❗만들어 봅시다!

clerk.com 에 로그인을 하고, 어플리케이션을 만들어 줍시다.

구글, 애플, 디스코드, 깃허브 등등 다양한 웹 서비스와 연동할 수 있는데요, 원하는 서비스와 연결하여 만들어 주시면 됩니다. 저는 구글을 연동하여 만들겠습니다.

 

Next.js의 App router를 기준으로 코드를 작성하겠습니다.

npm install @clerk/nextjs

우선 clerk을 인스톨 해주시구요.

 

//.env
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=***
CLERK_SECRET_KEY=***

//생략시 Clerk의 Sign In, Sign Up 페이지 접근이 불가능합니다.
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/

루트 디렉토리에 .evn 파일을 만들고, api key와 Clerk에서 사용할 urL를 적어주시면 됩니다.

순서대로 로그인 페이지, 회원가입 페이지, 로그인 이후 이동할 URL, 회원가입 이후 이동 될 URL을 적어줍니다. 이를 적지 않으면 회원가입 페이지, 로그인 페이지에 접근할 수 없게 됩니다.

 

// app.layout.js
import { ClerkProvider } from "@clerk/nextjs";

...
export default function RootLayout({ children }) {
  return (
    <ClerkProvider>
      <html lang="en">
        <body className={inter.className}>{children}</body>
      </html>
    </ClerkProvider>
  );
}

그리고 ClerkProvider 라는 요소로 html 요소를 감싸주어야 합니다.

 

//middleware.js
import { authMiddleware } from "@clerk/nextjs";
 
// This example protects all routes including api/trpc routes
// Please edit this to allow other routes to be public as needed.
// See <https://clerk.com/docs/references/nextjs/auth-middleware> for more information about configuring your Middleware
export default authMiddleware({
	// 로그인 없이 갈 수 있는 루트를 표시합니다.
	publicRoutes: ["/"],
});
 
export const config = {
  matcher: ['/((?!.+\\\\.[\\\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
};

마지막 세팅으로 미들웨어 세팅을 해줘야 합니다. 위와 같이 해주시면 되구요.

publicRoutes 부분에는 로그인 없이 진입할 수 있는 URL을 적어주시면 됩니다.

이렇게 Clerk을 사용할 준비는 끝이 났습니다.

 

저는 간단하게 아래 코드로 SignIn, SignUp 페이지를 만들어 주었습니다.

위에서 .env 파일에 URL을 Sign-in, Sign-up으로 설정했기 때문에 App router를 사용하고 있는 저는 app/sign-in/page.js, app/sign-up/page.js 위치에 파일을 만들어 주었습니다.

// app/sign-in/page.js
import { SignIn } from "@clerk/nextjs";

export default function Page() {
  return (
    <div className="flex h-screen justify-center items-center">
      <SignIn />;
    </div>
  );
}
// app/sign-up/page.js
import { SignUp } from "@clerk/nextjs";

export default function Page() {
  return (
    <div className="flex h-screen justify-center items-center">
      <SignUp />
    </div>
  );
}

그리고 위의 페이지에 접근하면 다음과 같이 Clerk의 로그인 화면을 만나실 수 있습니다!

❓유저 정보를 받아오는법?

Clerk에는 유저 정보를 받아볼 수 있는 Hook을 제공합니다.

하나는 useAuth(), 나머지 하나는 useUser() 입니다.

const { isLoaded, userId, sessionId, getToken } = useAuth();

useAuth() 는 보시면 아시겠지만, 외부로 비추어지면 안되는 정보들이 있습니다. 이는 서버 사이드 단에서 사용해주시면 좋을 것 같습니다.

 

const { isLoaded, isSignedIn, user } = useUser();

useUser() 는 반대로 민감한 정보가 없습니다. 클라이언트 사이드에서 사용하면 좋겠네요!

저는 useUser()를 이용하여 다음과 같은 header를 만들어 봤습니다.

 

"use client";

import { SignOutButton, UserButton, useUser } from "@clerk/nextjs";
import Link from "next/link";

export default function Header() {
  const { isLoaded, isSignedIn, user } = useUser();
  
  return (
    <main>
      <nav>
        <ul className="flex">
          {isSignedIn ? (
            <>
              <li className="m-5">
                <UserButton afterSignOutUrl="/" />
              </li>
              <li className="m-5">
                <SignOutButton>SignOut</SignOutButton>
              </li>
            </>
          ) : (
            <>
              <li className="m-5">
                <Link href={"/sign-in"}>Sign In</Link>
              </li>
              <li className="m-5">
                <Link href={"/sign-up"}>Sign Up</Link>
              </li>
            </>
          )}
        </ul>
      </nav>
    </main>
  );
}

로그인을 하지 않으면 Sign In, Sign Up을 표시하고, 로그인이 된다면 Clerk에서 제공하는 UserButton 요소와 SignOutButton을 이용해 아이콘과 로그아웃을 함께 표시했습니다.

이렇게 간단하게 Clerk을 Next에서 사용해 보았습니다!