Nuxt 3에서 Auth.js (NextAuth.js)를 이용한 원활한 인증
Wenhao Wang
Dev Intern · Leapcell

서론: 안전한 인증으로 사용자 경험 향상
빠르게 발전하는 현대 웹 개발 환경에서 안전하고 확장 가능하며 사용자 친화적인 애플리케이션을 만드는 것이 최우선입니다. 이러한 노력의 초석은 강력한 인증입니다. Nuxt 3를 활용하는 개발자에게는 신뢰할 수 있는 인증 시스템을 처음부터 구축하는 것이 복잡하고 시간이 많이 소요되는 작업일 수 있으며, 종종 보안상의 함정이 있습니다. 바로 여기서 이전의 NextAuth.js였던 Auth.js가 강력하고 유연한 솔루션으로 등장합니다. 이 솔루션은 다양한 인증 제공업체 및 전략을 지원하는 안전한 오픈 소스 프레임워크를 제공하여 전체 인증 프로세스를 단순화합니다.
이 글에서는 Nuxt 3와 Auth.js를 통합하여 완전하고 안전한 인증 흐름을 구축하는 과정을 안내합니다. 핵심 개념을 명확히 설명하고, 실제 구현을 살펴보고, 이 강력한 조합의 이점을 강조하여 궁극적으로 Nuxt 3 애플리케이션에서 원활하고 안전한 사용자 경험을 제공할 수 있도록 지원합니다.
Auth.js 및 Nuxt 3를 사용한 인증 명확히 이해하기
구현을 시작하기 전에 논의의 중심이 될 몇 가지 주요 용어를 명확히 합시다.
- 인증 (Authentication): 사용자가 주장하는 자신이 맞는지 확인하여 사용자의 신원을 확인하는 프로세스입니다.
- 권한 부여 (Authorization): 인증된 사용자가 수행할 수 있는 작업을 결정하는 프로세스입니다.
- Auth.js (이전 NextAuth.js): JavaScript 프레임워크를 위해 설계된 포괄적인 오픈 소스 인증 라이브러리로, 다양한 제공업체, 데이터베이스 및 전략을 지원하는 완전한 인증 솔루션을 제공합니다.
- 제공업체 (Provider): 사용자의 실제 인증을 처리하는 외부 서비스(예: Google, GitHub, OAuth 2.0 서버)입니다. Auth.js는 이러한 다양한 서비스와의 상호 작용의 복잡성을 추상화합니다.
- 세션 (Session): 일반적으로 쿠키 또는 토큰을 통해 관리되는 사용자 및 애플리케이션 간의 지속적인 상호 작용 기간입니다. Auth.js는 사용자 세션을 안전하게 관리합니다.
- 콜백 (Callbacks): Auth.js가 인증 흐름의 특정 시점(예: 로그인 성공 후, 세션이 생성될 때)에 실행하는 함수입니다. 이를 통해 사용자 역할 첨부 또는 추가 프로필 정보 저장과 같이 동작을 사용자 지정할 수 있습니다.
- 미들웨어 (Middleware): 라우트 핸들러에서 요청을 처리하기 전에 실행되는 함수입니다. Nuxt에서 미들웨어는 라우트를 보호하고 인증되지 않은 사용자를 리디렉션하는 데 중요합니다.
Nuxt 3와의 Auth.js 통합의 핵심 원칙은 인증의 복잡한 세부 사항을 추상화하면서 사용자 지정을 위한 유연한 API를 제공하는 능력에 있습니다. Auth.js는 클라이언트 측 상호 작용(로그인/로그아웃 버튼)과 서버 측 논리(제공업체와 통신, 세션 관리, 콜백 생성)를 처리합니다. 그런 다음 Nuxt 3의 서버 라우트와 미들웨어는 요청을 Auth.js로 전달하고 애플리케이션 전체에서 인증 정책을 적용하는 다리 역할을 합니다.
완전한 인증 흐름 구현
GitHub와 같은 소셜 로그인 제공업체와 함께 간단한 이메일/비밀번호 제공업체를 예로 사용하여 Nuxt 3 프로젝트에 Auth.js를 통합하는 단계를 살펴보겠습니다.
1. 프로젝트 설정 및 종속성
아직 새 Nuxt 3 프로젝트를 생성하지 않았다면 생성하세요.
npx nuxi init nuxt3-authjs-example cd nuxt3-authjs-example npm install
그런 다음 Auth.js와 해당 Nuxt 모듈을 설치합니다.
npm install @next-auth/core @sidebase/nuxt-auth
2. Auth.js 구성
server/api/auth/[...].ts
파일을 생성합니다. 이 파일은 Auth.js를 통해 모든 인증 요청을 처리합니다.
// server/api/auth/[...].ts import { NuxtAuthHandler } from '#auth' import GitHubProvider from 'next-auth/providers/github' import CredentialsProvider from 'next-auth/providers/credentials' export default NuxtAuthHandler({ secret: process.env.NUXT_SECRET, // 강력한 비밀번호를 생성해야 합니다. providers: [ // GitHub Provider GitHubProvider({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, }), // 이메일/비밀번호용 자격 증명 제공업체 CredentialsProvider({ name: 'Credentials', async authorize(credentials: Record<'email' | 'password', string> | undefined) { // 여기에 고유한 자격 증명 유효성 검사 논리를 구현하세요. // 이것은 단순화된 예제입니다. 실제 애플리케이션에서는 // 사용자 데이터베이스를 쿼리하고 비밀번호를 확인합니다. if (credentials?.email === 'test@example.com' && credentials?.password === 'password') { return { id: '1', name: 'Test User', email: 'test@example.com' } } return null }, }), ], // 세션 데이터를 사용자 지정하거나 이벤트를 처리해야 하는 경우 여기에 콜백을 추가하세요. callbacks: { async jwt({ token, user }) { if (user) { token.id = user.id } return token }, async session({ session, token }) { if (session.user) { session.user.id = token.id as string } return session }, }, // `server/api/auth/[...].ts`가 직접 사용되지 않는 경우 사용자 지정 경로를 설정하는 옵션 pages: { signIn: '/login', // 사용자 지정 로그인 페이지로 리디렉션 }, })
환경 변수: 프로젝트 루트에 .env
파일을 생성하고 비밀번호 및 제공업체 자격 증명을 추가합니다.
NUXT_SECRET="super-secret-key-replace-with-a-randomly-generated-one"
GITHUB_CLIENT_ID="your_github_client_id"
GITHUB_CLIENT_SECRET="your_github_client_secret"
NUXT_SECRET
에 대해 강력하고 무작위로 생성된 비밀번호를 꼭 생성하세요.
3. 클라이언트 측 통합
이제 로그인 페이지를 만들고 사용자 정보를 표시해 보겠습니다.
사용자 지정 로그인 페이지 (pages/login.vue
):
<template> <div> <h1>Login</h1> <form @submit.prevent="credentialSignIn"> <input type="email" v-model="email" placeholder="Email" required /> <input type="password" v-model="password" placeholder="Password" required /> <button type="submit">Sign in with Email</button> </form> <p>Or</p> <button @click="signIn('github')">Sign in with GitHub</button> <div v-if="error">{{ error }}</div> </div> </template> <script setup> import { ref } from 'vue' import { useRouter } from 'vue-router' import { useAuth } from '#auth' const { signIn } = useAuth() const router = useRouter() const email = ref('') const password = ref('') const error = ref(null) async function credentialSignIn() { try { const result = await signIn('credentials', { email: email.value, password: password.value, redirect: false, // Auth.js가 직접 리디렉션하는 것을 방지 }) if (result?.error) { error.value = result.error } else { router.push('/') // 성공적으로 로그인하면 홈 페이지로 리디렉션 } } catch (e) { error.value = 'An unexpected error occurred.' } } </script>
보호된 홈페이지 (pages/index.vue
):
<template> <div> <h1>Welcome!</h1> <div v-if="status === 'authenticated' && data?.user"> <p>Hello, {{ data.user.name || data.user.email }}!</p> <button @click="signOut()">Sign out</button> <pre>{{ data.user }}</pre> </div> <div v-else> <p>You are not logged in.</p> <NuxtLink to="/login">Go to Login</NuxtLink> </div> </div> </template> <script setup> import { useAuth } from '#auth' const { data, status, signOut } = useAuth() </script>
4. 미들웨어를 사용한 라우트 보호
라우트를 보호하고 인증된 사용자만 액세스할 수 있도록 하려면 Nuxt 미들웨어를 사용합니다.
middleware/auth.ts
생성:
// middleware/auth.ts export default defineNuxtRouteMiddleware((to, from) => { const { status } = useAuth() if (status.value === 'unauthenticated' && to.path !== '/login') { return navigateTo('/login') } })
이제 이 미들웨어를 보호하려는 페이지에 적용합니다. 예를 들어 /login
을 제외한 모든 페이지를 보호하려면 다음을 수행합니다.
<!-- pages/index.vue --> <script setup> definePageMeta({ middleware: ['auth'], // 'auth' 미들웨어 적용 }) import { useAuth } from '#auth' const { data, status, signOut } = useAuth() </script>
애플리케이션 시나리오:
- 소셜 로그인: 제공업체 구성을 추가하기만 하면 Google, Facebook, Twitter 등과 같은 인기 있는 제공업체를 쉽게 통합할 수 있습니다.
- 사용자 지정 로그인 양식:
CredentialsProvider
에서와 같이 자체 로그인 양식을 구축하고 기존 사용자 데이터베이스에 대해 유효성 검사를 수행할 수 있습니다. - 보호된 API 라우트: 미들웨어 개념을 Nuxt 3 서버 라우트로 확장하여 백엔드 API를 보호하고 인증된 사용자만 민감한 데이터에 액세스하거나 특정 작업을 수행할 수 있도록 합니다.
- 역할 기반 액세스 제어 (RBAC):
session
및jwt
콜백을 확장하여 사용자 역할을 세션에 첨부한 다음 이 정보를 미들웨어 또는 컴포넌트 내에서 사용하여 사용자 권한을 기반으로 UI 요소 또는 데이터 액세스를 제어할 수 있습니다.
Nuxt 3와 Auth.js의 이점
- 즉시 사용 가능한 보안: Auth.js는 CSRF 공격, 세션 하이재킹, 암호화적으로 안전한 토큰 관리와 같은 일반적인 보안 취약점을 처리하여 애플리케이션 논리에 집중할 수 있습니다.
- 개발 간소화: 일반적으로 인증에 필요한 상용구 코드를 줄여 개발 시간을 단축합니다.
- 유연성 및 확장성: 광범위한 인증 제공업체를 지원하며 콜백 및 어댑터를 통해 심층적인 사용자 지정을 허용합니다.
- 원활한 통합:
@sidebase/nuxt-auth
모듈은 즐거운 개발자 경험을 위해 Nuxt별 통합, 컴포저블 및 자동 가져오기를 제공합니다. - 서버 측 렌더링 (SSR) 지원: Nuxt 3의 SSR 기능과 완벽하게 호환되어 성능이 뛰어나고 SEO 친화적인 사용자 경험을 보장합니다.
결론: 안전한 사용자 인증으로 Nuxt 3 애플리케이션 강화
Nuxt 3 애플리케이션에 Auth.js를 통합함으로써 개발 프로세스를 크게 간소화하는 강력하고 안전하며 유연한 인증 솔루션을 얻을 수 있습니다. 다양한 제공업체를 처리하는 것부터 안전한 세션을 관리하고 미들웨어로 라우트를 보호하는 것까지 Auth.js를 통해 강력한 사용자 인증 흐름을 자신 있게 구축할 수 있습니다. Nuxt 3의 개발자 친화적인 프레임워크와 Auth.js의 포괄적인 인증 기능을 결합하면 현대적이고 안전하며 매력적인 웹 애플리케이션을 구축하기 위한 견고한 기반을 제공합니다. Nuxt 3 프로젝트의 보안 및 사용자 경험을 향상시키려면 Auth.js를 채택하세요.