Auth.js (NextAuth v5) 패턴은(는) 무엇을 하나요?
빠른 가이드: 루트
auth.ts파일에 Auth.js를 설정하고NextAuth()에서{ auth, handlers, signIn, signOut }을 export합니다. 모든 곳(서버 컴포넌트, 라우트 핸들러, 미들웨어)에서 통합auth()함수를 사용합니다. 기본 세션 전략은 JWT(쿠키 기반)이며, 지속적인 세션을 위해 데이터베이스 어댑터를 추가합니다. 미들웨어 또는 페이지별auth()검사를 통해 경로를 보호합니다.
<critical_requirements>
중요: 이 스킬을 사용하기 전에
모든 코드는 CLAUDE.md의 프로젝트 규칙을 따라야 합니다 (kebab-case, named export, import 순서,
import type, 명명된 상수)
(루트 auth.ts 파일에 Auth.js를 설정하고 NextAuth()에서 { auth, handlers, signIn, signOut }을 export해야 합니다)
(서버 측 세션 접근에 통합 auth() 함수를 사용해야 합니다 - 더 이상 사용되지 않는 getServerSession(), getSession(), 또는 getToken()을 사용하지 마세요)
(AUTH_SECRET 환경 변수를 사용해야 합니다 - NEXTAUTH_SECRET은 v5에서 더 이상 사용되지 않습니다)
(프로바이더 자격 증명에는 AUTH_ 접두사가 붙은 환경 변수를 사용해야 합니다 (예: AUTH_GITHUB_ID, AUTH_GITHUB_SECRET) - 자동으로 감지됩니다)
(데이터베이스 세션을 미들웨어와 함께 사용하는 경우 인증 설정을 auth.config.ts(Edge 호환)와 auth.ts(어댑터 포함)로 분할해야 합니다)
(서버 액션과 API 라우트 내에서 세션을 반드시 확인해야 합니다 - 미들웨어만으로는 인증에 충분하지 않습니다)
</critical_requirements>
자동 감지: Auth.js, NextAuth, next-auth, authjs, auth.ts, auth.config.ts, NextAuth(), signIn, signOut, auth(), handlers, SessionProvider, useSession, AUTH_SECRET, OAuth 프로바이더, credentials 프로바이더, 데이터베이스 어댑터, @auth/prisma-adapter, @auth/drizzle-adapter, authorized 콜백, jwt 콜백, session 콜백, 프록시 auth, 미들웨어 auth
사용 시기:
- Next.js, SvelteKit, Express, Qwik 앱에 인증 추가
- 80개 이상의 내장 프로바이더로 OAuth 로그인 구현 (GitHub, Google, Discord 등)
- 이메일/매직 링크 인증 흐름 구축
- JWT 또는 데이터베이스 기반 세션 관리 필요
- Edge 호환 미들웨어 인증이 필요한 프로젝트
사용하지 말아야 할 시기:
- 처음부터 커스텀 인증 시스템 구축 (Auth.js는 정해진 방식이 있습니다)
- 즉시 사용 가능한 세분화된 조직/팀 관리가 필요
- 웹 프론트엔드 없는 모바일 전용 앱
- 플러그인 아키텍처로 자체 호스팅 인증이 필요
주요 패턴:
- 인증 설정 (
auth.ts,auth.config.ts) - OAuth 프로바이더 (GitHub, Google, Credentials, Email)
- 세션 전략 (JWT vs 데이터베이스)
- 세션 접근 (서버 컴포넌트, 라우트 핸들러, 클라이언트 컴포넌트)
- 미들웨어/프록시 경로 보호
- 데이터베이스 어댑터 (Prisma, Drizzle)
- 콜백 (jwt, session, signIn, redirect)
- 역할 기반 접근 제어
- Edge 호환성 분할 설정
상세 자료:
- 의사 결정 프레임워크 및 안티 패턴: reference.md 참조
핵심 패턴:
- examples/core.md - 인증 설정, 프로바이더, 콜백
- examples/session.md - 세션 전략, 세션 접근 패턴
- examples/middleware.md - 경로 보호, 미들웨어, Edge 호환성
- examples/database.md - 데이터베이스 어댑터, Prisma, Drizzle
- examples/patterns.md - 역할 기반 접근, 매직 링크, 계정 연결
철학
Auth.js (v5)는 인증을 단일 통합 API로 통합합니다. auth() 함수는 v4의 getServerSession, getSession, withAuth, getToken을 서버 측에서 대체합니다. useSession()은 여전히 올바른 클라이언트 측 API입니다. 설정은 API 라우트가 아닌 루트 파일에 위치합니다.
핵심 원칙:
- 프레임워크에 구애받지 않음 - Next.js, SvelteKit, Express, Qwik과 함께 작동
- 통합 API - 모든 서버 측 컨텍스트를 위한 단일
auth()함수 - 프로바이더 생태계 - 80개 이상의 내장 OAuth 프로바이더,
AUTH_*환경 변수 자동 감지 - 기본 JWT - 암호화된 쿠키의 무상태 세션, 데이터베이스 불필요
- Edge 호환 - 미들웨어는 Edge 런타임에서 실행 (Next.js 16 프록시는 Node.js에서 실행)
- 점진적 복잡성 - OAuth로 시작하고, 데이터베이스 어댑터를 추가한 다음 콜백을 커스터마이징
핵심 패턴
패턴 1: 인증 설정
중앙 설정 파일은 NextAuth()에서 필요한 모든 것을 export합니다.
기본 OAuth 설정
// auth.ts
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import Google from "next-auth/providers/google";
export const { auth, handlers, signIn, signOut } = NextAuth({
providers: [
GitHub, // AUTH_GITHUB_ID 및 AUTH_GITHUB_SECRET 자동 감지
Google, // AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET 자동 감지
],
});
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
이점: 단일 설정 파일이 모든 인증 유틸리티를 export하고, 프로바이더가 AUTH_* 환경 변수를 자동 감지하며, API 라우트가 최소화됨
환경 변수
# .env.local
AUTH_SECRET="npx-auth-secret으로-생성" # 필수
AUTH_GITHUB_ID="your-github-client-id" # GitHub 프로바이더가 자동 감지
AUTH_GITHUB_SECRET="your-github-secret" # GitHub 프로바이더가 자동 감지
AUTH_GOOGLE_ID="your-google-id" # Google 프로바이더가 자동 감지
AUTH_GOOGLE_SECRET="your-google-secret"
이점: v5에서 AUTH_ 접두사가 표준화되었고, AUTH_SECRET이 더 이상 사용되지 않는 NEXTAUTH_SECRET을 대체하며, 프로바이더가 자격 증명을 자동 감지함
패턴 2: 프로바이더
Auth.js는 OAuth, 이메일/매직 링크, 자격 증명 인증을 지원합니다. 80개 이상의 내장 OAuth 프로바이더가 AUTH_* 환경 변수를 자동 감지합니다.
// OAuth: 프로필 매핑 커스터마이징
GitHub({
profile(profile) {
return {
id: String(profile.id),
name: profile.name ?? profile.login,
role: "user",
};
},
});
// Credentials: 입력 유효성 검사, 실패 시 null 반환
Credentials({
async authorize(credentials) {
const parsed = LoginSchema.safeParse(credentials);
if (!parsed.success) return null;
const user = await getUserByEmail(parsed.data.email);
if (
!user ||
!(await verifyPassword(parsed.data.password, user.hashedPassword))
)
return null;
return { id: user.id, name: user.name, email: user.email };
},
});
핵심 규칙: DB 조회 전에 입력 유효성 검사, 항상 비밀번호 해싱, 실패 시 null 반환 (절대 throw하지 마세요 - 정보가 유출됩니다). 전체 구현은 examples/core.md를 참조하세요.
패턴 3: 콜백
네 가지 콜백이 인증 동작을 커스터마이징합니다. 데이터 흐름: jwt 콜백 (토큰 강화) -> session 콜백 (클라이언트에 노출).
callbacks: {
jwt({ token, user }) {
if (user) { token.id = user.id; token.role = user.role ?? "user"; }
return token;
},
session({ session, token }) {
session.user.id = token.id as string;
session.user.role = token.role as string;
return session;
},
}
핵심 규칙: JWT 콜백은 모든 auth() 호출 시 실행되므로 가볍게 유지, user 매개변수는 로그인 시에만 존재, OAuth 토큰을 클라이언트에 절대 노출하지 마세요. signIn 및 redirect를 포함한 전체 콜백 구현은 examples/core.md를 참조하세요.
패턴 4: 세션 접근
통합 auth() 함수는 v4의 getServerSession, getSession, getToken을 서버 측에서 대체합니다. useSession()은 클라이언트 컴포넌트용으로 유지됩니다.
| 컨텍스트 | 세션 접근 방법 |
|---|---|
| 서버 컴포넌트 | const session = await auth() |
| 라우트 핸들러 | export const GET = auth(function GET(req) { req.auth }) |
| 서버 액션 | const session = await auth() |
| 미들웨어/프록시 | export { auth as middleware } 또는 authorized 콜백 |
| 클라이언트 컴포넌트 | useSession() (레이아웃에 SessionProvider 필요) |
핵심 규칙: 서버 측 임포트는 @/auth에서, 클라이언트 측 임포트는 next-auth/react에서 가져옵니다. 클라이언트 컴포넌트에서 auth()를 호출하지 마세요. 전체 구현은 examples/session.md를 참조하세요.
패턴 5: 로그인 / 로그아웃 액션
두 가지 접근 방식: 서버 액션 (권장, 점진적 향상) 또는 클라이언트 측.
// 서버 측 (권장): @/auth에서 임포트, 폼에서 서버 액션 사용
import { signIn, signOut } from "@/auth";
// 폼 액션 내: await signIn("github", { redirectTo: "/dashboard" })
// 폼 액션 내: await signOut({ redirectTo: "/" })
// 클라이언트 측: next-auth/react에서 임포트, onClick 핸들러 사용
import { signIn, signOut } from "next-auth/react";
// onClick: signIn("github", { callbackUrl: "/dashboard" })
핵심 규칙: 서버 측은 redirectTo, 클라이언트 측은 callbackUrl을 사용합니다. signIn()은 내부적으로 NEXT_REDIRECT 예외를 throw합니다. 반환 값을 기대하며 try/catch로 감싸지 마세요. 전체 구현은 examples/core.md를 참조하세요.
패턴 6: TypeScript 확장
types/next-auth.d.ts에서 선언 병합을 통해 세션 및 JWT 타입을 확장합니다. Session, User, JWT 인터페이스에 커스텀 필드 (예: id, role)를 & DefaultSession["user"]와 함께 선언하여 기본값을 유지합니다. 전체 타입 선언 예제는 examples/core.md를 참조하세요.
통합 가이드
Auth.js는 인증 계층입니다. 신원 확인, 세션 관리, 경로 보호를 처리합니다. 권한 부여 로직 (역할 확인, 권한 시스템)은 처리하지 않습니다. 이는 애플리케이션 코드의 영역입니다.
프레임워크 지원: Auth.js는 프레임워크별 패키지 (next-auth, @auth/sveltekit, @auth/express)를 통해 여러 웹 프레임워크와 함께 작동합니다.
데이터베이스 어댑터: 데이터베이스 세션의 경우 Auth.js는 ORM과 통합되는 어댑터 패키지 (@auth/prisma-adapter, @auth/drizzle-adapter 등)를 제공합니다. examples/database.md를 참조하세요.
세션 전략은 필요에 따라 선택합니다:
- JWT (기본) - 데이터베이스 불필요, Edge에서 작동, 무상태
- 데이터베이스 - 어댑터 필요, 서버 측 세션 저장소, 즉시 해지 지원
Auth.js가 처리하지 않는 것: 세분화된 권한 부여/RBAC, 속도 제한, 인증 외 데이터베이스 쿼리 - 이는 애플리케이션 수준의 문제입니다.
<red_flags>
주의 사항
getServerSession(authOptions)사용 -- v5에서 더 이상 사용되지 않음;auth.ts의auth()를 사용하세요.NEXTAUTH_SECRET또는NEXTAUTH_URL사용 -- 더 이상 사용되지 않음;AUTH_SECRET을 사용하세요. (URL은 자동 감지됨)- 속도 제한 없는 Credentials 프로바이더 -- 무차별 대입 공격에 취약합니다.
- session 콜백을 통해 클라이언트에 OAuth 토큰 노출 --
accessToken/refreshToken은 서버 측에서만 유지하세요. - 미들웨어/프록시를 유일한 인증 수단으로 사용 -- 렌더링 전에 실행되지만 서버 액션/API 라우트의 경로별 검사를 대체하지는 않습니다.
- 미들웨어에서 데이터베이스 어댑터 임포트 -- 데이터베이스 ORM은 Edge 런타임에서 실행될 수 없습니다 (Next.js 14/15); 설정을
auth.config.ts+auth.ts로 분할하세요. signIn()을 try/catch로 감싸기 -- 내부적으로 NEXT_REDIRECT 예외를 throw합니다. (의도된 동작입니다)- JWT 콜백이 매 호출마다 데이터베이스 쿼리 -- 모든
auth()호출 시 실행되므로 가볍게 유지하세요.
전체 안티 패턴 목록, 주의사항 및 마이그레이션 테이블은 reference.md를 참조하세요.
</red_flags>
<critical_reminders>
중요 알림
모든 코드는 CLAUDE.md의 프로젝트 규칙을 따라야 합니다
(루트 auth.ts 파일에 Auth.js를 설정하고 NextAuth()에서 { auth, handlers, signIn, signOut }을 export해야 합니다)
(서버 측 세션 접근에 통합 auth() 함수를 사용해야 합니다 - 더 이상 사용되지 않는 getServerSession(), getSession(), 또는 getToken()을 사용하지 마세요)
(AUTH_SECRET 환경 변수를 사용해야 합니다 - NEXTAUTH_SECRET은 v5에서 더 이상 사용되지 않습니다)
(프로바이더 자격 증명에는 AUTH_ 접두사가 붙은 환경 변수를 사용해야 합니다 (예: AUTH_GITHUB_ID, AUTH_GITHUB_SECRET) - 자동으로 감지됩니다)
(데이터베이스 세션을 미들웨어와 함께 사용하는 경우 인증 설정을 auth.config.ts(Edge 호환)와 auth.ts(어댑터 포함)로 분할해야 합니다)
(서버 액션과 API 라우트 내에서 세션을 반드시 확인해야 합니다 - 미들웨어만으로는 인증에 충분하지 않습니다)
이 규칙을 따르지 않으면 인증 실패, 더 이상 사용되지 않는 패턴 노출 또는 보안 취약점이 발생할 수 있습니다.
</critical_reminders>