NextAuth3로 진행된 내용입니다.
NextAuth는 인증 및 세션 관리에 도움을 주지만, 자체 사용자 계정 시스템을 운영할 경우 사용자 생성 로직은 직접 구현해야 합니다. NextAuth는 이미 존재하는 사용자를 인증하고 토큰을 발급하는 데 사용되며, 그 사용자를 생성하는 것은 우리의 몫입니다.
이 과정에서는 사용자 계정 생성을 위한 API 라우트를 구축합니다. 이 API는 이메일과 비밀번호를 입력받아 데이터베이스에 사용자를 저장하는 역할을 합니다.
데이터베이스 선택 및 설정
데이터베이스는 MongoDB를 사용합니다. MongoDB Atlas는 시작하기에 비용이 들지 않고, JavaScript와 함께 사용하기 쉬우며, 호스팅까지 해결해 주므로 편리합니다. (물론 다른 데이터베이스를 사용해도 무방합니다.)
먼저 mongodb 패키지를 설치해야 합니다.
npm install mongodb
데이터베이스 연결 헬퍼 (lib/db.js)
회원가입 API 외에도 로그인 등 여러 API 라우트에서 데이터베이스 연결 로직이 필요할 것입니다. 코드 중복을 피하기 위해, 프로젝트 루트에 lib 폴더를 생성하고 db.js 파일을 만듭니다. 이 파일은 MongoDB 연결을 관리하는 함수를 가집니다.
- mongodb에서 MongoClient를 가져옵니다.
- connectToDatabase라는 async 함수를 정의합니다.
- MongoClient.connect()를 사용하여 MongoDB Atlas에서 제공하는 연결 문자열로 데이터베이스에 연결합니다.
- 연결 문자열의 사용자 이름, 비밀번호, 데이터베이스 이름을 실제 값으로 대체해야 합니다. (예: 데이터베이스명 auth-demo)
- 연결에 성공하면 client 객체를 반환합니다.
[lib/db.js]
import { MongoClient } from 'mongodb';
export async function connectToDatabase() {
const client = await MongoClient.connect(
'mongodb+srv://maximilian:ZbJcz3dJ88LSUMlM@cluster0.ntrwp.mongodb.net/auth-demo?retryWrites=true&w=majority'
);
return client;
}
비밀번호 암호화 헬퍼 (lib/auth.js)
보안상 가장 중요한 부분입니다. 절대로 사용자의 비밀번호를 원본 텍스트 그대로 데이터베이스에 저장해서는 안 됩니다. 만약 데이터베이스가 유출되면 모든 사용자의 계정 정보가 노출됩니다. 항상 비밀번호를 해시(hash)하여 저장해야 합니다. 해싱은 단방향 암호화이며, 원본 값을 복호화할 수 없습니다. 이를 위해 bcryptjs 패키지를 설치합니다.
npm install bcryptjs
데이터베이스 헬퍼와 마찬가지로 lib 폴더에 auth.js 파일을 생성하여 관련 로직을 관리합니다.
- bcryptjs에서 hash 함수를 가져옵니다.
- hashPassword라는 async 함수를 만듭니다.
- hash 함수는 두 개의 인자를 받습니다: 해시할 원본 비밀번호, 그리고 솔트 라운드(salt rounds) 횟수.
- 솔트 라운드 횟수(여기서는 12)는 해시의 강도를 결정합니다. 숫자가 높을수록 안전하지만 처리 시간이 길어집니다. 12는 현재 기준으로 안전한 값입니다.
- 해시된 비밀번호를 반환합니다.
(참고: lib/auth.js의 전체 코드에는 나중에 로그인을 위해 사용할 verifyPassword 함수도 포함되어 있습니다.)
[lib/auth.js]
import { hash, compare } from 'bcryptjs';
export async function hashPassword(password) {
const hashedPassword = await hash(password, 12);
return hashedPassword;
}
export async function verifyPassword(password, hashedPassword) {
const isValid = await compare(password, hashedPassword);
return isValid;
}
회원가입 API 라우트 (pages/api/auth/signup.js)
이제 실제 회원가입 로직을 담을 API 라우트를 생성합니다. pages/api/auth/signup.js 경로에 파일을 만듭니다. 이 파일은 handler 함수를 export default로 내보냅니다. 이 함수는 Next.js에 의해 API 요청이 있을 때마다 실행됩니다.
API 로직 상세 설명
- HTTP 메소드 확인: 이 API는 새 리소스를 생성하므로 POST 요청만 허용해야 합니다. req.method가 'POST'가 아니면 즉시 종료합니다.
- 데이터 추출: req.body에서 email과 password를 추출합니다.
- 입력 유효성 검사:
- 데이터베이스 연결: lib/db.js에서 만든 connectToDatabase 함수를 호출하여 DB에 연결합니다.
- 기존 사용자 확인 (보안):
- 비밀번호 해싱: lib/auth.js의 hashPassword 함수를 호출하여 사용자가 제출한 원본 비밀번호를 해시합니다.
- 새 사용자 저장:
- 성공 응답: 사용자가 성공적으로 생성되었음을 알리는 201 Created 상태 코드와 성공 메시지를 반환합니다.
- 연결 종료: client.close()를 호출하여 데이터베이스 연결을 닫습니다.
[pages/api/auth/signup.js]
import { hashPassword } from '../../../lib/auth';
import { connectToDatabase } from '../../../lib/db';
async function handler(req, res) {
if (req.method !== 'POST') {
return;
}
const data = req.body;
const { email, password } = data;
if (
!email ||
!email.includes('@') ||
!password ||
password.trim().length < 7
) {
res.status(422).json({
message:
'Invalid input - password should also be at least 7 characters long.',
});
return;
}
const client = await connectToDatabase();
const db = client.db();
const existingUser = await db.collection('users').findOne({ email: email });
if (existingUser) {
res.status(422).json({ message: 'User exists already!' });
client.close();
return;
}
const hashedPassword = await hashPassword(password);
const result = await db.collection('users').insertOne({
email: email,
password: hashedPassword,
});
res.status(201).json({ message: 'Created user!' });
client.close();
}
export default handler;
'NextJS > NextAuth' 카테고리의 다른 글
| [NextAuth] 클라이언트 사이드 페이지 가드 (라우트 보호) 추가하기 - 6 (0) | 2025.11.18 |
|---|---|
| [NextAuth] 클라이언트 컴포넌트 인증 : 로그인, 로그아웃 -5 (0) | 2025.11.17 |
| [NextAuth] 로그인 API 구현 [...nextauth].js - 4 (0) | 2025.11.16 |
| [NextAuth] 회원가입 컴포넌트 및 API 연동 - 3 (0) | 2025.11.12 |
| [NextAuth] React/NextJS 인증(Authentication)의 원리와 적용 - 1 (0) | 2025.11.06 |