Next-Auth와 Vercel을 활용한 소셜 로그인 구현

meek·2024년 7월 26일
post-thumbnail

Next-auth? Vercel?

next-auth는 Next.js 프로젝트에서 소셜 로그인을 간단하게 구현할 수 있는 라이브러리 입니다.

국내에서는 구글, 카카오, 네이버, 페이스북, 애플 등 다양한 소셜 로그인을 이용하고 사용합니다.해당 사이트가 늘어나면 늘어날 수록 로직은 달라지고 복잡해지는데 next-auth를 이용하면 한번에 쉽고 간단하게 구현 가능합니다. 

vercel은 Next.js 개발 팀에서 만든 프론트엔드 배포 자동화할 수 있게 빌드,배포,호스팅 서비스를 제공하는 호스팅 사이트입니다. 비슷한 서비스로는 Netlify가 있습니다.

vercel은 GitHub, GitLab, Bitbucket 등의 버전 관리 시스템과 연동하여 코드 변경이 발생하면 자동으로 빌드하고 배포할 수 있습니다. 이로써 개발자는 별도의 배포 작업 없이도 변경사항을 신속하게 고객에게 제공할 수 있다는 장점이 있습니다.

Next-auth 설치하기

npm install next-auth

API Route 추가하기

// app/api/auth/[...nextauth]/route.js
import NextAuth from "next-auth"
import GitHubProvider from "next-auth/providers/github"

// authOptions를 정의합니다.
const authOptions = {
    providers: [
        GitHubProvider({
            clientId: process.env.GITHUB_ID,
            clientSecret: process.env.GITHUB_SECRET,
        }),
    ],
    pages: {
        signIn: "/auth/signin",
        error: "/auth/error",
    },
}

// NextAuth 핸들러를 정의합니다.
const handler = NextAuth(authOptions)

// GET 및 POST 요청을 처리할 수 있도록 핸들러를 내보냅니다.
export { handler as GET, handler as POST }

.env 작성 및 등록

GITHUB_ID="YOUR_CLIENT_ID"
GITHUB_SECRET="YOUR_SECERT_ID"

GITHUB_ID와 GITHUB_SECRET은 Github developer setting에서 발급가능합니다.

Vercel Environment Variables

vercel에서도 사용하기 위해 환경 변수로 등록해주어야 합니다.

Session Provider 감싸주기

import { SessionProvider } from "next-auth/react"
import { Inter } from "next/font/google"
import "./globals.css"

const inter = Inter({ subsets: ["latin"] })

	@@ -14,8 +14,7 @@ export default function RootLayout({ children }) {
    return (
        <html lang="en">
            <body className={inter.className}>
                <SessionProvider session={session}>{children}</SessionProvider>
            </body>
        </html>
    )
}

문제상황) Error: React Context is unavailable in Server Components

Error: React Context is unavailable in Server Components

해결 방법

https://stackoverflow.com/questions/75902311/next-js-13-and-next-auth-issues-with-usesession-and-sessionprovider

//app/_components/providers/session-provider.js
"use client"
import { SessionProvider } from "next-auth/react"

export const NextAuthProvider = ({ children }) => {
    return <SessionProvider>{children}</SessionProvider>
}

NextAuthProvider 컴포넌트를 따로 생성해 작성 후 최상위 파일인 layout.js에 import해주는 식으로 수정해주니 해결되었습니다.

파일은 Next.js 파일구조 공식문서를 참고해 라우팅이 되지 않게 _components 폴더를 생성해 만들어주었습니당

import { Inter } from "next/font/google"
import "./globals.css"
import { NextAuthProvider } from "./_components/providers/session-provider"

const inter = Inter({ subsets: ["latin"] })

export const metadata = {
    title: "a",
    description: "a",
}

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

Sign In, Sign out 버튼 추가

import { signIn, signOut, useSession } from "next-auth/react"

const AuthButtons = () => {
    const { data: session } = useSession()

    return (
        <div className="mb-4">
            {session ? (
                <>
                    <p>Logged in as {session.user.email}</p>
                    <button
                        onClick={() => signOut()}
                        className="px-4 py-2 bg-red-500 text-white rounded-md hover:bg-red-600"
                    >
                        Sign out
                    </button>
                </>
            ) : (
                <>
                    <p>You are not logged in</p>
                    <button
                        onClick={() => signIn("github")}
                        className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
                    >
                        Sign in with GitHub
                    </button>
                </>
            )}
        </div>
    )
}

export default AuthButtons

comment 작성 폼 추가

문제2) secret 추가

/api/auth/_log

[next-auth][error][NO_SECRET]
https://next-auth.js.org/errors#no_secret Please define a secret in production. MissingSecret [MissingSecretError]: Please define a secret in production.
at t.assertConfig (/var/task/.next/server/chunks/720.js:6:104752)
at AuthHandler (/var/task/.next/server/chunks/720.js:6:97923)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async NextAuthRouteHandler (/var/task/.next/server/chunks/720.js:30:19986)
at async e.length.t (/var/task/.next/server/chunks/720.js:30:21456)
at async /var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:14:39709 {
code: 'NO_SECRET'
}

Vercel 배포 log를 확인했을 때 위와 같이 확인할 수 있었습니다.
그 중 MissingSecret [MissingSecretError]: Please define a secret in production. 를 확인했으며,

//.env
GITHUB_ID=
GITHUB_SECRET=
NEXTAUTH_SECRET=

NEXTAUTH_SECRET은 따로 발급받을 필요없이 원하는 값을 넣어주면 됩니다.
그리고 route에 secret: process.env.NEXTAUTH_SECRET를 추가해주면 해결!

//app/api/auth/[...nextauth]/route.js
import NextAuth from "next-auth"
import GitHubProvider from "next-auth/providers/github"

// authOptions를 정의합니다.
const authOptions = {
    providers: [
        GitHubProvider({
            clientId: process.env.GITHUB_ID,
            clientSecret: process.env.GITHUB_SECRET,
        }),
    ],
    pages: {
        signIn: "/auth/signin",
        error: "/auth/error",
    },
    // 💫secret 추가💫
    secret: process.env.NEXTAUTH_SECRET,
}

const handler = NextAuth(authOptions)

export { handler as GET, handler as POST }

완성

profile
hello, world!

0개의 댓글