Next.jsNext.js 기초강의 8개 중 6번째난이도 기초

인증 구현 — NextAuth.js로 소셜 로그인

발행 읽는 시간 약 1 분

  • Next.js
  • NextAuth
  • 인증
  • 소셜로그인
  • 세션

강의 소개

NextAuth.js v5(Auth.js)로 Google, GitHub 소셜 로그인과 이메일/비밀번호 인증을 구현합니다. 세션 관리와 라우트 보호 방법도 배웁니다.

NextAuth.js 설치#

Bash
npm install next-auth@beta

기본 설정#

TypeScript
// auth.ts (루트에 위치)
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
import GitHub from "next-auth/providers/github";
import Credentials from "next-auth/providers/credentials";
import { db } from "@/lib/db";

export const { handlers, signIn, signOut, auth } = NextAuth({
    providers: [
        Google({
            clientId: process.env.GOOGLE_CLIENT_ID!,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
        }),
        GitHub({
            clientId: process.env.GITHUB_CLIENT_ID!,
            clientSecret: process.env.GITHUB_CLIENT_SECRET!,
        }),
        Credentials({
            credentials: {
                email: { label: "이메일", type: "email" },
                password: { label: "비밀번호", type: "password" },
            },
            async authorize(credentials) {
                const user = await db.users.findByEmail(credentials.email as string);
                if (!user) return null;

                const valid = await verifyPassword(
                    credentials.password as string,
                    user.hashedPassword
                );
                if (!valid) return null;

                return { id: user.id, name: user.name, email: user.email };
            },
        }),
    ],
    callbacks: {
        async session({ session, token }) {
            if (token.sub) session.user.id = token.sub;
            return session;
        },
    },
});

API Route Handler 연결#

TypeScript
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth";

export const { GET, POST } = handlers;

환경 변수#

Bash
# .env.local
AUTH_SECRET=your-secret-key  # openssl rand -base64 32

GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...

GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

로그인/로그아웃 버튼#

TSX
// components/AuthButtons.tsx
import { signIn, signOut, auth } from "@/auth";

// 서버 컴포넌트에서 세션 확인
export default async function AuthButtons() {
    const session = await auth();

    if (session?.user) {
        return (
            <div>
                <p>안녕하세요, {session.user.name}님!</p>
                <form action={async () => {
                    "use server";
                    await signOut();
                }}>
                    <button type="submit">로그아웃</button>
                </form>
            </div>
        );
    }

    return (
        <div>
            <form action={async () => {
                "use server";
                await signIn("google");
            }}>
                <button>Google로 로그인</button>
            </form>
            <form action={async () => {
                "use server";
                await signIn("github");
            }}>
                <button>GitHub로 로그인</button>
            </form>
        </div>
    );
}

미들웨어로 라우트 보호#

TypeScript
// middleware.ts
import { auth } from "@/auth";

export default auth((req) => {
    const isLoggedIn = !!req.auth;
    const pathname = req.nextUrl.pathname;

    if (!isLoggedIn && pathname.startsWith("/dashboard")) {
        return Response.redirect(new URL("/login", req.url));
    }
});

export const config = {
    matcher: ["/dashboard/:path*"],
};

클라이언트에서 세션 사용#

TSX
"use client";
import { useSession } from "next-auth/react";

function UserMenu() {
    const { data: session, status } = useSession();

    if (status === "loading") return <span>로딩 중...</span>;
    if (!session) return <a href="/api/auth/signin">로그인</a>;

    return (
        <div>
            <img src={session.user.image ?? ""} alt="아바타" />
            <span>{session.user.name}</span>
        </div>
    );
}

정리#

Diagram · Mermaid
항목설명
handlersAPI Route에 연결
auth()서버 컴포넌트 세션 확인
signIn()로그인
signOut()로그아웃
useSession()클라이언트 세션 훅

다음 편에서는 환경 변수와 배포 — .env 설정과 Vercel 배포 방법을 배웁니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.