코드 출처 : https://github.com/Cluster-Taek/next14-boilerplate
login-form.tsx
'use client';
import Button from '@/components/common/button';
import { ILoginFormValue } from '@/lib/common/account';
import { sva } from '@/styled-system/css';
import { Box } from '@/styled-system/jsx';
import { signIn } from 'next-auth/react';
import { useSearchParams } from 'next/navigation';
import { Controller, useForm } from 'react-hook-form';
const LoginForm = () => {
const loginFormStyle = LoginFormSva();
const searchParams = useSearchParams();
const {
handleSubmit: formHandleSubmit,
formState,
control,
} = useForm<ILoginFormValue>({
defaultValues: {
login: 'test@gmail.com',
password: '1234',
},
});
const handleSubmit = formHandleSubmit(async (data) => {
await signIn('login-credentials', { ...data, callbackUrl: searchParams.get('callbackUrl') ?? '/' });
});
return (
<Box className={loginFormStyle.wrapper}>
<Box className={loginFormStyle.title}>Login</Box>
<form className={loginFormStyle.form} onSubmit={handleSubmit}>
<Controller
control={control}
name="login"
rules={{ required: 'Email is required' }}
render={({ field }) => <input type="text" {...field} className={loginFormStyle.input} placeholder="email" />}
/>
{formState.errors.login && <Box className={loginFormStyle.error}>{formState.errors.login.message}</Box>}
<Controller
control={control}
name="password"
rules={{ required: 'Password is required' }}
render={({ field }) => (
<input type="password" {...field} className={loginFormStyle.input} placeholder="password" />
)}
/>
{formState.errors.password && <Box className={loginFormStyle.error}>{formState.errors.password.message}</Box>}
<Button type="submit">Submit</Button>
</form>
{searchParams.get('error') === 'CredentialsSignin' && (
<Box>
<Box className={loginFormStyle.error}>Invalid email or password</Box>
</Box>
)}
</Box>
);
};
export default LoginForm;
...
signIn 함수가 어떻게 auth-options.ts에서 정의된 인증 핸들러를 찾아 요청을 처리하는가?
이를 이해하려면 NextAuth의 동작 방식을 알아야 합니다.
1. NextAuth와 API 라우트의 연결
NextAuth는 pages/api/auth/[...nextauth].ts 파일을 사용하여 모든 인증 요청을 처리합니다.
Next.js의 API 라우트는 파일 시스템 기반으로 동작하며, [...] 패턴은 동적 경로를 나타냅니다.
요청 경로: /api/auth/*
파일 경로: pages/api/auth/[...nextauth].ts
즉, 클라이언트에서 /api/auth/*로 보내는 모든 요청이 pages/api/auth/[...nextauth].ts에 정의된 NextAuth 핸들러로 전달됩니다.
2. signIn 함수의 역할
signIn 함수는 next-auth/react 라이브러리에서 제공하며, 특정 Provider에 인증 요청을 보냅니다.
await signIn('login-credentials', { ...data });
- 첫 번째 인자: 'login-credentials'
- NextAuth에서 설정된 Provider의 id입니다.
- 이 값은 auth-options.ts에서 정의된 CredentialsProvider의 id: 'login-credentials'와 일치해야 합니다.
- 두 번째 인자: 옵션 객체
- 사용자 입력값(이메일, 비밀번호 등)을 포함.
signIn 함수는 내부적으로 /api/auth/callback/:provider 경로로 HTTP POST 요청을 만듭니다.
- 여기서 :provider는 첫 번째 인자로 전달된 'login-credentials'입니다.
3. NextAuth 핸들러의 요청 처리
pages/api/auth/[...nextauth].ts는 NextAuth의 엔트리포인트입니다.
import NextAuth from 'next-auth';
import { authOptions } from '@/lib/auth-options';
export default NextAuth(authOptions);
- authOptions는 NextAuth의 설정 객체로, auth-options.ts에서 정의된 내용을 가져옵니다.
- 이 객체에는 인증 로직(Provider, Callbacks 등)이 포함되어 있습니다.
signIn 요청의 흐름
- 라우트 매칭: 클라이언트가 /api/auth/callback/login-credentials로 요청 → [...nextauth].ts가 해당 요청을 수신.
- Provider 탐색: NextAuth는 authOptions.providers에서 id: 'login-credentials'인 Provider를 찾음.
- authorize 호출: CredentialsProvider의 authorize 함수가 호출되어 인증 처리.
4. Provider의 식별과 연결
signIn에서 전달한 'login-credentials' 값이 Provider를 식별하는 핵심입니다.
이 값은 authOptions.providers에 정의된 Provider의 id와 일치해야 요청을 처리할 수 있습니다.
export const authOptions: NextAuthOptions = {
providers: [
CredentialsProvider({
id: 'login-credentials', // Provider ID
name: 'Credentials',
credentials: {
login: { label: 'Email', type: 'text' },
password: { label: 'Password', type: 'password' },
},
async authorize(credentials) {
// 사용자 인증 로직
},
}),
],
};
어떻게 요청이 이어지는가
- 클라이언트에서 signIn('login-credentials') 호출:
- /api/auth/callback/login-credentials로 요청이 전송됩니다.
- NextAuth 핸들러가 요청 수신:
- [...nextauth].ts 파일에서 NextAuth가 모든 인증 요청을 처리.
- Provider 매핑:
- NextAuth는 authOptions.providers에서 id가 'login-credentials'인 Provider를 찾음.
- authorize 실행:
- 해당 Provider의 authorize 함수가 호출되어 사용자 인증이 이루어짐.
이 모든 과정은 Next.js의 파일 기반 라우팅과 NextAuth의 설정 시스템 덕분에 자동으로 연결됩니다.
'개발 공부 > React' 카테고리의 다른 글
| React.memo (1) (1) | 2025.01.22 |
|---|---|
| NextAuth.js 요약 (1) | 2025.01.19 |
| NextAuth.js 사용자 인증 로직 (2) (1) | 2025.01.12 |
| NextAuth.js 사용자 인증 로직 (1) (0) | 2025.01.11 |
| Next.js usePathname, useRouter, useSearchParams (0) | 2025.01.08 |