이 튜토리얼에서는 Auth.js 및 Upstash Redis를 사용하여 Next.js 애플리케이션에서 사용자 인증을 구현하는 방법을 배웁니다. 필요한 환경을 설정하고, 안전한 사용자 로그인 및 가입을 위한 사용자 정의 인증 공급자를 생성하고, 세션 관리를 위한 데이터베이스로 Upstash Redis를 통합하는 방법을 배우게 됩니다.
전제조건
다음이 필요합니다:
- Node.js 18 이상
- Upstash 계정
기술 스택
Upstash Redis 인스턴스 설정
Upstash 대시보드에서 Redis로 이동하세요. 탭을 클릭하고 데이터베이스를 생성하세요.

REST API 섹션을 찾을 때까지 아래로 스크롤하고 .env를 선택합니다. 버튼. 콘텐츠를 복사하여 안전한 곳에 저장하세요.

새 Next.js 애플리케이션 만들기
새로운 Next.js 프로젝트를 만들어 시작해 보겠습니다. 터미널을 열고 다음 명령을 실행하세요:
npx create-next-app@latest my-app 메시지가 나타나면 다음을 선택하세요:
YesTypeScript를 사용하라는 메시지가 표시될 때.NoESLint를 사용하라는 메시지가 표시되면YesTailwind CSS를 사용하라는 메시지가 표시되면Nosrc/을 사용하라는 메시지가 표시되면 디렉토리.Yes앱 라우터를 사용하라는 메시지가 표시될 때.NoTurbopack을 사용하라는 메시지가 표시될 때.No기본 가져오기 별칭(@/*)을 사용자 정의하라는 메시지가 표시되면 ).
완료되면 프로젝트 디렉터리로 이동하고 다음 명령을 실행하여 개발 모드에서 앱을 시작하세요.
cd my-app
npm run dev 앱은 localhost:3000에서 실행되어야 합니다. 다음 명령을 사용하여 개발 서버를 중지하고 필요한 종속성을 설치하십시오:
npm install @upstash/redis nanoid
npm install next-auth @auth/core @auth/upstash-redis-adapter 설치된 라이브러리는 다음과 같습니다:
nanoid:고유하고 안전한 ID를 생성하기 위한 라이브러리입니다.next-auth:Next.js용으로 구축된 인증 솔루션@auth/core:Auth.js에서 인증을 처리하기 위한 핵심 패키지@upstash/redis:HTTP 요청을 통해 Upstash Redis와 상호작용하는 SDK.@auth/upstash-redis-adapter:Auth.js를 Upstash Redis와 통합하기 위한 어댑터.
이제 .env을 생성하세요. 프로젝트 루트에 있는 파일입니다. AUTH_SECRET를 사용하게 됩니다. , UPSTASH_REDIS_REST_URL 및 UPSTASH_REDIS_REST_TOKEN 가치.
.env 파일에는 다음이 있어야 합니다:
# .env
# Auth.js Environment Variable
AUTH_SECRET="..."
# Upstash Redis Environment Variables
UPSTASH_REDIS_REST_URL="https://...upstash.io"
UPSTASH_REDIS_REST_TOKEN="..." Upstash Redis 클라이언트 인스턴스화
redis.ts이라는 파일을 만듭니다. lib에서 다음 코드가 포함된 디렉토리:
// File: lib/redis.ts
import { Redis } from '@upstash/redis'
export default new Redis({
url: process.env.UPSTASH_REDIS_REST_URL,
token: process.env.UPSTASH_REDIS_REST_TOKEN,
}) 위 코드에서는 Edge 호환 Redis 클라이언트 인스턴스를 내보내 애플리케이션 전체에서 사용하도록 했습니다.
사용자 유형 및 자격 증명 도우미 설정
types.ts이라는 파일을 만듭니다. lib에서 다음 코드가 포함된 디렉토리:
// File: lib/types.ts
export interface UserType {
id?: string
email: string
name?: string
image?: string
password?: string
emailVerified?: string
}
UserType 인터페이스는 애플리케이션의 사용자 개체 구조를 정의합니다. 여기에는 다음이 포함됩니다:
id(선택):사용자의 고유 식별자입니다.email(필수):사용자의 이메일 주소.name(선택):사용자의 이름.image(선택사항):사용자 프로필 이미지의 URL 또는 경로입니다.password(선택사항):사용자의 해시된 비밀번호.emailVerified(선택사항):사용자의 이메일이 확인되었는지 여부와 시기를 나타내는 타임스탬프 또는 문자열입니다.
이 인터페이스는 애플리케이션 전체에서 사용자 데이터에 대한 유형 정의 역할을 합니다.
그리고 credentials.ts라는 파일을 생성하세요. lib에서 다음 코드가 포함된 디렉토리:
// File: lib/credentials.ts
export function generateRandomToken() {
const array = new Uint8Array(20)
crypto.getRandomValues(array)
return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('')
}
export function generateRandomString(inputValue: string) {
const encoder = new TextEncoder()
const data = encoder.encode(inputValue)
return crypto.subtle.digest('SHA-256', data).then((hashBuffer) => {
return Array.from(new Uint8Array(hashBuffer))
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('')
})
}
export async function hashPassword(password: string) {
const encoder = new TextEncoder()
const data = encoder.encode(password)
const hashBuffer = await crypto.subtle.digest('SHA-256', data)
return Array.from(new Uint8Array(hashBuffer))
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('')
}
export async function comparePassword(password: string, hash: string) {
const hashedPassword = await hashPassword(password)
return hashedPassword === hash
} 위 코드에는 보안 토큰과 해시된 비밀번호를 생성하고 관리하기 위한 Edge 호환 유틸리티 함수가 정의되어 있습니다.
generateRandomToken:20바이트 무작위 배열을 생성하고 이를 16진수 문자열로 변환하여 암호화로 안전한 무작위 토큰을 생성합니다.generateRandomString:입력 문자열을 받아 바이트로 인코딩하고 SHA-256을 사용하여 해시한 다음 해시를 16진수 문자열로 반환합니다. 입력 값에서 파생된 일관되고 고유한 문자열을 생성하는 데 유용합니다.hashPassword:SHA-256을 사용하여 일반 텍스트 비밀번호를 해시하고 결과 해시를 16진수 문자열로 변환합니다. 비밀번호를 안전하게 저장하기 위해 사용됩니다.comparePassword:입력을 해싱하고 저장된 해시와 일치하는지 확인하여 일반 텍스트 비밀번호와 해시된 비밀번호를 비교합니다.
Auth.js와 함께 Upstash Redis 어댑터 사용
auth.ts라는 파일을 만듭니다. lib에서 다음 코드가 포함된 디렉토리:
// File: lib/auth.ts
import { UpstashRedisAdapter } from '@auth/upstash-redis-adapter'
import NextAuth from 'next-auth'
import providers from './providers'
import redis from './redis'
export const { handlers, signIn, signOut, auth } = NextAuth(() => ({
providers,
session: { strategy: 'jwt' },
adapter: UpstashRedisAdapter(redis),
}))
위 코드에서는 handlers 생성을 통해 인증이 설정됩니다. , signIn , signOut 및 auth 사용자 정의 구성을 사용하는 기능. JWT 기반 세션 전략인 UpstashRedisAdapter을 사용합니다. 사용자 데이터를 저장하기 위한 Upstash Redis 데이터베이스와 providers에 정의된 인증 공급자 배열에 연결합니다. 모듈. 이 설정을 통해 Upstash Redis를 백엔드로 사용하여 인증 및 세션 관리를 원활하게 통합할 수 있습니다.
Auth.js를 사용하여 맞춤 인증 공급자 설정
providers.ts라는 파일을 만듭니다. lib에서 다음 코드가 포함된 디렉토리:
// File: lib/providers.ts
import { nanoid } from 'nanoid'
import Credentials from 'next-auth/providers/credentials'
import { comparePassword, generateRandomString, hashPassword } from './credentials'
import redis from './redis'
import { UserType } from './types'
export default [
Credentials({
credentials: {
email: {},
password: {},
},
authorize: async (credentials, request) => {
let type
try {
const tmp = new URL(request.url).searchParams.get('kind')
if (tmp && typeof tmp === 'string') type = tmp
} catch (e) {}
if (!type || !credentials.email || typeof credentials.email !== 'string' || !credentials.password || typeof credentials.password !== 'string') return null
const randomizedPassword = await generateRandomString(credentials.password)
const userByEmail = await redis.get<string | null | undefined>(`user:email:${credentials.email}`)
if (userByEmail) {
if (type !== 'in') {
console.log(`can not sign in in a non sign-in mode.`)
throw new Error(`can not sign in in a non sign-in mode.`)
}
const user = await redis.get<UserType>(`user:${userByEmail}`)
if (!user) {
console.log(`Found the user by email from user:email:${userByEmail}, but the user object is missing at user:${userByEmail}`)
return null
}
if (user.password) {
const hashedPassword = await hashPassword(randomizedPassword)
const isPasswordCorrect = await comparePassword(user.password, hashedPassword)
if (isPasswordCorrect) {
const { password, ...rest } = user
return rest
}
throw new Error(`incorrect password for credentials.`)
}
throw new Error(`you are using some other authentication method already, but not credentials.`)
} else {
if (type !== 'up') {
console.log(`can not sign up in a non sign-up mode.`)
throw new Error(`can not sign up in a non sign-up mode.`)
}
const newUser = {
name: null,
image: null,
emailVerified: null,
email: credentials.email,
password: randomizedPassword,
}
const tmp = nanoid()
await redis.set(`user:email:${credentials.email}`, tmp)
await redis.set(`user:${tmp}`, newUser)
return newUser
}
},
}),
] 위 코드에서는 사용자 정의 자격 증명 기반 인증 공급자 배열을 내보냅니다. 자격 증명 공급자는 로그인 및 등록 논리를 모두 처리합니다. 즉, 사용자가 Redis에 존재하는지 확인하고 암호를 확인하거나 새 사용자를 생성합니다. 로그인하면 제공된 비밀번호(임의의 문자열을 사용하여 해시됨)와 저장된 비밀번호를 비교합니다. 가입하면 Upstash Redis에 새 사용자 항목이 생성됩니다. 이 코드는 사용자 데이터 저장을 위해 Upstash Redis를 사용하고 URL의 종류 매개변수를 기반으로 가입 또는 로그인 모드에서 프로세스가 수행되도록 합니다.
인증 API 경로 설정(Auth.js 기반)
route.ts라는 파일을 만듭니다. app/api/auth/[...nextauth]에서 다음 코드가 포함된 디렉토리:
// File: app/api/auth/[...nextauth]/route.ts
export const runtime = 'edge'
import { handlers } from '@/lib/auth'
export const { GET, POST } = handlers
위 코드에서는 두 개의 엔드포인트 핸들러 GET 및 POST handlers에 의해 처리되어 내보내집니다. @/lib/auth.ts에서 내보낸 함수 파일입니다.
route.ts이라는 파일을 만듭니다. app/api/refresh에서 다음 코드가 포함된 디렉토리:
// File: app/api/refresh/route.ts
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export const fetchCache = 'force-no-store'
import { auth } from '@/lib/auth'
import redis from '@/lib/redis'
import { UserType } from '@/lib/types'
import { encode } from '@auth/core/jwt'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
export async function GET(request: Request) {
const useSecureCookie = request.url.startsWith('https:')
const salt = useSecureCookie ? '__Secure-authjs.session-token' : 'authjs.session-token'
if (!process.env.AUTH_SECRET) return new NextResponse(null, { status: 500 })
const [session, cookieStore] = await Promise.all([auth(), cookies()])
if (!session?.user?.email) return new NextResponse(null, { status: 400 })
const userByEmail = await redis.get(`user:email:${session.user.email}`)
const userData = await redis.get<UserType>(`user:${userByEmail}`)
if (!userData?.email) cookieStore.set(salt, toString(), { secure: useSecureCookie, path: '/', httpOnly: true, sameSite: 'lax', maxAge: 0 })
else {
const { image, password, ...rest } = userData
const saltVal = await encode({ salt, secret: process.env.AUTH_SECRET, token: { ...rest, picture: image } })
cookieStore.set(salt, saltVal, { secure: useSecureCookie, path: '/', httpOnly: true, sameSite: 'lax' })
}
return new NextResponse()
} 위 코드에서는 사용자 세션을 새로 고치기 위한 Edge 호환 API 경로가 생성됩니다. Redis에서 사용자 세션 및 관련 데이터를 가져오고, 사용자의 이메일을 확인하고, 세션 쿠키를 업데이트합니다. 사용자 데이터가 유효하지 않거나 누락된 경우 세션 쿠키가 지워집니다. 그렇지 않으면 새로 서명된 토큰이 생성되어 쿠키에 저장됩니다.
route.ts이라는 파일을 만듭니다. app/api/user에서 다음 코드가 포함된 디렉토리:
// File: app/api/user/route.ts
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export const fetchCache = 'force-no-store'
import { auth } from '@/lib/auth'
import redis from '@/lib/redis'
import { UserType } from '@/lib/types'
import { NextResponse } from 'next/server'
export async function POST(request: Request) {
try {
const session = await auth()
if (!session?.user?.email) return new NextResponse(null, { status: 400 })
const body = await request.json()
const userByEmail = await redis.get(`user:email:${session.user.email}`)
const userData = await redis.get<UserType>(`user:${userByEmail}`)
if (!userData) return new NextResponse(null, { status: 404 })
if (body.name) userData.name = body.name
if (body.image) userData.image = body.image
await redis.set(`user:${userByEmail}`, userData)
return new NextResponse()
} catch (e: any) {
const message = e.message || e.toString()
console.log(message)
return new NextResponse(message, { status: 500 })
}
} 위 코드에서는 사용자 데이터 업데이트를 위한 Edge 호환 API 경로가 생성됩니다. 사용자를 인증하고 이메일을 사용하여 Redis에서 데이터를 가져오고 요청 본문을 기반으로 정보(예:이름 또는 이미지)를 업데이트합니다. 사용자를 찾을 수 없거나 오류가 발생하면 적절한 상태 코드와 응답이 반환됩니다.
Auth.js로 Next.js 미들웨어 설정
middleware.ts이라는 파일을 만듭니다. 다음 코드를 사용하여 프로젝트의 루트 디렉터리에:
// File: middleware.ts
export { auth as middleware } from '@/lib/auth'
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}
위 코드에서는 auth를 다시 내보내서 미들웨어를 생성합니다. @/lib/auth의 함수 모듈. 미들웨어는 matcher에 지정된 대로 API 경로, 정적 파일, 이미지 자산 및 파비콘을 제외한 모든 경로에 인증을 적용합니다. 구성. 이렇게 하면 제외되지 않은 경로가 Auth.js로 설정된 인증 논리로 보호됩니다.
Next.js 앱 라우터 구성요소에서 Auth.js 사용
NextAuthProvider.tsx라는 파일을 만듭니다. app에서 다음 코드가 포함된 디렉토리:
// File: app/NextAuthProvider.tsx
'use client'
import { SessionProvider } from 'next-auth/react'
type Props = {
children?: React.ReactNode
}
export default function ({ children }: Props) {
return <SessionProvider>{children}</SessionProvider>
}
위 코드에서는 NextAuth의 SessionProvider로 애플리케이션을 래핑하기 위해 클라이언트 측 React 구성 요소가 생성됩니다. . 구성 요소는 children을 허용합니다. props로 래핑된 구성 요소가 NextAuth에서 제공하는 사용자 세션 컨텍스트에 액세스할 수 있는지 확인합니다. 이 설정은 Next.js의 애플리케이션 전체에서 인증 상태를 관리하는 데 필수적입니다.
csrf.tsx라는 파일을 만듭니다. app에서 다음 코드가 포함된 디렉토리:
// File: app/csrf.tsx
'use client'
import { getCsrfToken } from 'next-auth/react'
import { useEffect, useState } from 'react'
export function CSRFInput() {
const [csrfToken, setCsrfToken] = useState<string>()
useEffect(() => {
getCsrfToken().then((res) => setCsrfToken(res))
}, [])
return <input type="hidden" name="csrfToken" defaultValue={csrfToken} />
}
위 코드에서는 NextAuth의 getCsrfToken를 사용하여 CSRF 토큰을 가져오는 클라이언트 측 React 구성 요소를 내보냅니다. 함수를 작성하여 상태 변수에 저장합니다. 구성 요소는 CSRF 토큰이 포함된 숨겨진 입력 필드를 렌더링하여 토큰을 숨겨진 값으로 포함하여 안전한 양식 제출을 허용합니다. 이는 교차 사이트 요청 위조 공격으로부터 보호하는 데 유용합니다.
provider.tsx이라는 파일을 만듭니다. app에서 다음 코드가 포함된 디렉토리:
// File: app/provider.tsx
'use client'
import { Button } from '@/components/ui/button'
import { Icon } from '@iconify/react'
import { signIn } from 'next-auth/react'
export default function ({ provider, prefix }: { prefix: string; provider: { name: string; id: string } }) {
return (
<Button onClick={() => signIn(provider.id)} key={provider.name} variant="outline" className="flex w-full gap-x-3">
{provider.id === 'google' && <Icon fontSize={18} icon="flat-color-icons:google" />}
<span className="text-black">
{prefix} with {provider.name}
</span>
</Button>
)
}
위 코드에서는 다양한 인증 공급자에 대한 사용자 정의 가능한 로그인 버튼을 렌더링하기 위한 React 구성 요소를 내보냅니다. provider을 허용합니다. (name 포함 및 id ) 및 prefix 소품으로. 버튼은 signIn을 트리거합니다. 지정된 공급자에 대한 기능을 수행하고 공급자의 id를 기반으로 아이콘과 레이블을 동적으로 표시합니다. .
layout.tsx이라는 파일을 업데이트하세요. app에서 다음 코드가 포함된 디렉토리:
// File: app/layout.tsx
import './globals.css'
import NextAuthProvider from './NextAuthProvider'
export default function ({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className="bg-white text-black antialiased">
<NextAuthProvider>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col">{children}</div>
</NextAuthProvider>
</body>
</html>
)
}
위 코드에서 Next.js 레이아웃은 전역 스타일과 인증 컨텍스트로 전체 페이지를 래핑합니다. globals.css을 가져옵니다. 전역 스타일 지정 및 NextAuthProvider 인증 상태를 관리합니다. children prop은 반응형 패딩과 최대 너비를 갖춘 스타일 컨테이너로 래핑되어 모든 페이지에 일관된 레이아웃을 제공하는 중첩된 페이지 콘텐츠를 나타냅니다.
클라이언트 측 페이지에 사용자 인증 상태 로드
page.tsx라는 파일을 업데이트하세요. app에서 다음 코드가 포함된 디렉토리:
// File: app/page.tsx
'use client'
import { signOut, useSession } from 'next-auth/react'
export default function () {
const { data, status } = useSession()
return (
<>
{JSON.stringify({ data, status })}
<button onClick={() => signOut()}>Sign Out</button>
</>
)
}
위 코드에서는 사용자의 세션 데이터를 표시하고 "로그아웃" 버튼을 제공하는 클라이언트 측 React 구성 요소를 내보냅니다. NextAuth의 useSession을 사용합니다. 세션 데이터와 상태를 검색하여 JSON 문자열로 표시하는 후크입니다. signOut 버튼을 클릭하면 함수가 호출되어 사용자가 로그아웃할 수 있습니다.
동적 로그인 페이지 구축(Auth.js 사용)
page.tsx이라는 파일을 만듭니다. app/signin에서 다음 코드가 포함된 디렉토리:
// File: app/signin/page.tsx
export const runtime = 'edge'
import { CSRFInput } from '@/app/csrf'
import Provider from '@/app/provider'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { auth } from '@/lib/auth'
import providers from '@/lib/providers'
import { unstable_noStore } from 'next/cache'
import Link from 'next/link'
import { redirect } from 'next/navigation'
export default async function () {
unstable_noStore()
const session = await auth()
if (session) redirect('/')
return (
<div className="border md:border-white/10 flex items-center justify-center py-12">
<div className="mx-auto grid w-[350px] gap-6">
<div className="grid gap-2 text-center">
<h1 className="text-3xl font-bold">Sign In</h1>
<p className="text-balance text-muted-foreground">Enter your email below to sign in to your account</p>
</div>
{providers
.filter((provider) => (typeof provider === 'function' ? provider({}).id : provider.id) !== 'credentials')
.map((provider) => (
<Provider
prefix="Sign in"
key={typeof provider === 'function' ? provider({}).name : provider.name}
provider={typeof provider === 'function' ? provider({}) : provider}
/>
))}
<p className="text-gray-300 text-xs text-center">OR</p>
<form method="POST" className="grid gap-4" action="/api/auth/callback/credentials?kind=in">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input name="email" id="email" type="email" placeholder="m@example.com" required />
</div>
<div className="grid gap-2">
<Label htmlFor="password">Password</Label>
<Input name="password" id="password" type="password" required />
<CSRFInput />
</div>
<Button type="submit" className="w-full">
Sign In
</Button>
</form>
<div className="mt-4 text-center text-sm">
Don't have an account?{' '}
<Link href="/signup" className="underline">
Sign up
</Link>
</div>
</div>
</div>
)
} 위 코드에서는 로그인 페이지가 생성됩니다. 사용자 세션이 이미 존재하는지 확인합니다. 그렇다면 홈페이지로 리디렉션됩니다. 이 페이지에는 사용자가 이메일과 비밀번호를 입력할 수 있는 로그인 양식과 함께 다양한 공급자를 사용하여 로그인할 수 있는 옵션이 표시됩니다. 또한 보안을 위한 CSRF 토큰과 신규 사용자를 위한 가입 페이지 링크도 포함되어 있습니다.
동적 가입 페이지 구축(Auth.js 사용)
page.tsx라는 파일을 만듭니다. app/signup에서 다음 코드가 포함된 디렉토리:
// File: app/signup/page.tsx
export const runtime = 'edge'
import { CSRFInput } from '@/app/csrf'
import Provider from '@/app/provider'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { auth } from '@/lib/auth'
import providers from '@/lib/providers'
import { unstable_noStore } from 'next/cache'
import Link from 'next/link'
import { redirect } from 'next/navigation'
export default async function () {
unstable_noStore()
const session = await auth()
if (session) redirect('/')
return (
<div className="border md:border-white/10 flex items-center justify-center py-12">
<div className="mx-auto grid w-[350px] gap-6">
<div className="grid gap-2 text-center">
<h1 className="text-3xl font-bold">Sign Up</h1>
<p className="text-balance text-muted-foreground">Enter your email below to sign up with an account</p>
</div>
{providers
.filter((provider) => (typeof provider === 'function' ? provider({}).id : provider.id) !== 'credentials')
.map((provider) => (
<Provider
prefix="Sign up"
key={typeof provider === 'function' ? provider({}).name : provider.name}
provider={typeof provider === 'function' ? provider({}) : provider}
/>
))}
<p className="text-gray-300 text-xs text-center">OR</p>
<form method="POST" className="grid gap-4" action="/api/auth/callback/credentials?kind=up">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input name="email" id="email" type="email" placeholder="m@example.com" required />
</div>
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
</div>
<Input name="password" id="password" type="password" required />
<CSRFInput />
</div>
<Button type="submit" className="w-full">
Sign Up
</Button>
</form>
<div className="mt-4 text-center text-sm">
Don't have an account?{' '}
<Link href="/signin" className="underline">
Sign In
</Link>
</div>
</div>
</div>
)
} 위 코드에서는 회원가입 페이지가 생성됩니다. 사용자 세션이 이미 존재하는지 확인합니다. 그렇다면 홈페이지로 리디렉션됩니다. 이 페이지에는 사용자가 이메일과 비밀번호를 입력할 수 있는 가입 양식과 함께 다양한 공급자를 사용하여 로그인할 수 있는 옵션이 표시됩니다. 또한 보안을 위한 CSRF 토큰과 기존 사용자를 위한 로그인 페이지 링크도 포함되어 있습니다.
정말 많이 배웠습니다! 이제 모든 작업이 완료되었습니다 ✨
참고자료
더 자세한 통찰력을 얻으려면 이 블로그에 인용된 참고 자료를 살펴보세요.
- GitHub 저장소
- Auth.js - 자격 증명 인증
- Auth.js - Upstash Redis 어댑터
- Next.js - 쿠키
결론
이 튜토리얼에서는 Auth.js 및 Upstash Redis를 사용하여 Next.js 애플리케이션에서 사용자 인증을 구현하는 방법을 배웠습니다. 환경 변수 설정, Redis 클라이언트 생성 및 사용자 정의 인증 공급자 구현을 배웠습니다. 또한 사용자 로그인 및 등록 프로세스는 물론 세션 관리를 처리하기 위해 Next.js에서 API 경로를 설정하는 방법도 배웠습니다. 다음 단계를 따르면 Upstash Redis를 사용하여 Next.js 애플리케이션에서 사용자 인증 및 데이터 저장소를 효과적으로 관리할 수 있습니다.