NextAuth를 사용하여 인증 기능을 구현할 때, Supabase 데이터베이스와 함께 사용할 경우 해당 OAuth를 이용해야 하지만, 다른 데이터베이스를 사용할 경우 NextAuth가 더 유용할 수 있습니다.
App Router를 사용하기 위해 beta 버전을 설치합니다.
yarn add next-auth@beta
그 다음, 터미널에서 다음 명령어를 실행하여 인증 비밀키를 생성합니다.
npx auth secret
이 명령어를 실행하면 .env 파일에 자동으로 비밀키가 생성됩니다.

src/auth.ts 파일을 생성하고 다음 코드를 추가합니다.
import NextAuth from 'next-auth';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [],
});
그 다음, app/api/auth/[...nextAuth]/route.ts 파일을 생성하고 다음과 같이 작성합니다.
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
auth.ts 파일을 다음과 같이 수정하여 providers를 설정합니다.
import NextAuth, { User } from "next-auth";
import Credentials from "next-auth/providers/credentials";
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Credentials({
name: "Credentials",
credentials: {
username: { label: "Username", type: "text", placeholder: "username" },
password: { label: "Password", type: "password" },
},
async authorize(credentials): Promise<User | null> {
const users = [
{
id: "test-user-1",
userName: "test1",
name: "Test 1",
password: "pass",
email: "test1@donotreply.com",
},
{
id: "test-user-2",
userName: "test2",
name: "Test 2",
password: "pass",
email: "test2@donotreply.com",
},
];
const user = users.find(
(user) =>
user.userName === credentials.username &&
user.password === credentials.password
);
return user ? { id: user.id, name: user.name, email: user.email } : null;
},
}),
],
basePath: "/api/auth",
secret: process.env.AUTH_SECRET,
});
이제 http://localhost:3000/api/auth/signin에 접속하면 로그인 화면이 나타납니다.
로그인 후 세션 정보를 확인하려면 다음 코드를 사용합니다.
import { auth } from "@/auth";
const session = await auth();
로그아웃하려면 http://localhost:3000/api/auth/signout에 접속하면 됩니다.
server-action.ts 파일을 생성하여 서버와 클라이언트 모두에서 사용할 수 있도록 설정합니다.
// server-action.ts
'use server';
import { signIn as _signIn, signOut as _signOut } from '@/auth';
export async function signIn() {
await _signIn();
}
export async function signOut() {
await _signOut();
}
AuthButton.tsx 파일을 생성합니다.
// AuthButton.tsx
import { auth } from "@/auth";
import { SessionProvider } from "next-auth/react";
import { ClientAuthButton } from "./ClientAuthButton";
export const AuthButton = async () => {
const session = await auth();
return (
<SessionProvider session={session}>
<ClientAuthButton />
</SessionProvider>
);
};
ClientAuthButton.tsx 파일을 생성합니다.
// ClientAuthButton.tsx
'use client';
import { signIn, signOut } from '@/server-action';
import { useSession } from "next-auth/react";
export const ClientAuthButton = () => {
const { data: session } = useSession();
return session ? (
<button onClick={async () => { await signOut(); await signIn(); }}>sign-out</button>
) : (
<button onClick={async () => { await signIn(); }}>sign-in</button>
);
};
auth.ts 파일에 다음과 같이 커스텀 로그인 페이지 경로를 추가합니다:
pages: {
signIn: '/signin', // 추가
},
src/app/signin/page.tsx 파일을 생성하여 로그인 페이지를 만듭니다:
// src/app/signin/page.tsx
import { signInCredentials } from "@/server-action";
export default function SignInPage() {
return (
<>
<h1>Sign In</h1>
<form action={signInCredentials} style={{ display: "flex", flexDirection: "column", alignItems: "start", gap: "10px" }}>
<label>
Username
<input name="username" type="text" />
</label>
<label>
Password
<input name="password" type="password" />
</label>
<button>Sign In</button>
</form>
</>
);
}
그리고 src/server-action.ts에 signInCredentials 함수를 추가합니다:
'use server';
export async function signInCredentials(formData: FormData) {
await _signIn("credentials", {
username: formData.get('username'),
password: formData.get('password'),
redirectTo: "/",
});
}
ClientAuthButton.tsx를 다음과 같이 수정합니다:
// app/ClientAuthButton.tsx
'use client';
import { signIn, signOut } from '@/server-action';
import { useSession } from "next-auth/react";
import { useRouter } from 'next/navigation';
export const ClientAuthButton = () => {
const { data: session } = useSession();
const router = useRouter();
return session ? (
<button onClick={async () => {
await signOut();
router.replace('/signin'); // 변경
}}>Sign Out</button>
) : (
<button onClick={async () => {
router.replace('/signin'); // 변경
}}>Sign In</button>
);
};
이렇게 Next.js와 NextAuth를 이용해 App Router에서 인증 기능을 사용하는 부분을 만들어봤습니다