nextjs nextauth를 활용해서 인증시스템을 구현하기 위한 가장 좋은 조합은?
Next.js와 NextAuth.js를 활용해 안정적이고 확장 가능한 인증 시스템을 구축하기 위한 최적의 조합은 다음과 같습니다. 각 레이어별 접근 방식을 조합해 보안, 성능, 유지보수성을 균형 있게 확보할 수 있습니다.
1. 미들웨어(Middleware): 전역 인증 검사
역할
모든 라우트 진입 전 인증 상태 확인: 사용자가 보호된 경로에 접근할 때마다 세션 유효성을 검사합니다.
기본 리디렉션 처리: 미인증 사용자를 로그인 페이지로 자동 이동시킵니다.
구현
typescript
// middleware.ts
import NextAuth from 'next-auth';
import { authConfig } from './auth.config';
export default NextAuth(authConfig).auth;
export const config = {
matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
};
typescript
// auth.config.ts
import type { NextAuthConfig } from 'next-auth';
export const authConfig = {
pages: { signIn: '/login' },
callbacks: {
authorized({ auth, request }) {
const isLoggedIn = !!auth?.user;
const isProtectedRoute = request.nextUrl.pathname.startsWith('/dashboard');
return isProtectedRoute ? isLoggedIn : true;
},
},
providers: [], // OAuth 또는 Credentials 공급자 추가
} satisfies NextAuthConfig;
장점
성능 최적화: 라우트 렌더링 전에 차단하여 불필요한 작업 방지.
일관된 정책 적용: 모든 보호된 경로에 동일한 규칙 적용.
2. 서버 컴포넌트: 세부 권한 관리
역할
역할 기반 접근 제어(RBAC): 사용자 역할(admin, user)에 따라 콘텐츠 제한.
서버 측 데이터 페칭: 민감한 데이터를 클라이언트에 노출 없이 처리.
구현
typescript
// app/dashboard/page.tsx
import { getServerSession } from 'next-auth';
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
export default async function Dashboard() {
const session = await getServerSession(authOptions);
if (!session?.user) redirect('/login');
if (session.user.role !== 'admin') redirect('/unauthorized');
const data = await fetchSensitiveData(); // 서버에서 직접 호출
return <AdminContent data={data} />;
}
장점
SEO 친화적: 서버에서 완성된 HTML 제공.
보안 강화: 권한 검증을 서버에서 수행.
3. API 라우트: 백엔드 보호
역할
엔드포인트 보안 강화: 클라이언트-서버 통신 시 이중 검증.
데이터 무결성 보장: API 수준에서 인증/권한 확인.
구현
typescript
// app/api/admin/route.ts
import { getServerSession } from 'next-auth';
import { authOptions } from '../auth/[...nextauth]/route';
export async function GET() {
const session = await getServerSession(authOptions);
if (!session?.user || session.user.role !== 'admin') {
return new Response('Unauthorized', { status: 401 });
}
return Response.json({ data: '관리자 전용 데이터' });
}
장점
무단 접근 차단: 직접 API 호출 시에도 보호.
유연한 에러 처리: 맞춤형 상태 코드 반환.
4. 클라이언트 컴포넌트: 실시간 UX
역할
동적 UI 업데이트: 로그인 상태에 따른 버튼/메뉴 변경.
로딩 상태 표시: 사용자에게 진행 상황 피드백.
구현
typescript
'use client';
// components/UserMenu.tsx
import { useSession } from 'next-auth/react';
export default function UserMenu() {
const { data: session, status } = useSession();
if (status === 'loading') return <Skeleton />;
return session ? <ProfileMenu user={session.user} /> : <LoginButton />;
}
장점
사용자 경험 개선: 즉각적인 UI 반응.
세션 동기화: 탭 간 상태 일관성 유지.
5. NextAuth.js 설정: 확장성 확보
권장 구성
typescript
// auth.config.ts
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import Credentials from 'next-auth/providers/credentials';
export const authOptions = {
providers: [
Google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
Credentials({
async authorize(credentials) {
// 커스텀 로그인 로직 (예: 이메일/비밀번호)
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) token.role = user.role; // 역할 정보 추가
return token;
},
async session({ session, token }) {
session.user.role = token.role; // 클라이언트에 역할 전달
return session;
},
},
};
보안 강화 설정
Cookie 옵션: Secure, HttpOnly, SameSite=Strict 적용.
세션 갱신: updateAge: 24 * 60 * 60 (24시간마다 갱신).
종합 비교 및 권장 조합
방법 사용 사례 보안 성능 구현 복잡도
미들웨어 전역 인증 검사 ⭐⭐⭐ ⭐⭐⭐ 낮음
서버 컴포넌트 역할 기반 접근 제어, SEO 최적화 ⭐⭐⭐ ⭐⭐⭐ 중간
API 라우트 백엔드 API 보호 ⭐⭐⭐ ⭐⭐ 중간
클라이언트 실시간 UI 업데이트 ⭐ ⭐⭐ 낮음
최적화 조합 전략
미들웨어로 기본 인증 검사 → 서버 컴포넌트에서 세부 권한 확인 → API 라우트에서 이중 검증.
클라이언트 컴포넌트는 보조적 UI 업데이트용으로만 사용.
NextAuth.js 설정: JWT + 세션 콜백으로 역할 정보 확장.
보안 추가 권장 사항
HTTPS 강제: next.config.js에서 HTTPS 리디렉션 설정.
환경 변수 관리: NEXTAUTH_SECRET 반드시 설정.
로그인 시도 제한: IP 기반 차단 또는 CAPTCHA 통합.
2FA(이중 인증): 중요한 기능에 대해 추가 인증 계층 적용.
이 조합을 통해 Next.js 애플리케이션의 인증 시스템을 견고하게 구축할 수 있으며, 확장성과 유지보수성도 함께 확보됩니다.