Auth.js(Next-Auth)를 사용하여 이메일/비밀번호로 회원가입을 구현해 보자.
Auth.js와 더불어 mongoDB를 사용할 것이기 때문에 prisma도 함께 설치해 준다.
layout.tsx
의 body를 감싸준다."use client";
import React from "react";
import { SessionProvider } from "next-auth/react";
import { RecoilRoot } from "recoil";
const Providers = ({ children, session }: any) => {
return (
<RecoilRoot>
<SessionProvider session={session}>{children}</SessionProvider>
</RecoilRoot>
);
};
export default Providers;
api/register/route.js
import { NextResponse } from "next/server";
export async function POST(req) {
const { email, password, name } = await req.json();
return null;
}
회원 가입 시에 이메일, 비밀번호와 닉네임도 받아온다. 클라이언트 쪽에서 유효성 검사를 하지만, 사용자가 임의로 해당 기능을 해제했을 등의 상황에 대비하여 서버 측에서도 검사를 진행하는 편이 좋다고 한다.
따라서 세 필드가 비어있는지를 확인하는 로직을 추가해 준다.
api/register/route.js
import { NextResponse } from "next/server";
export async function POST(req) {
const { email, password, name } = await req.json();
if (!email || !password || !name) {
return NextResponse.json({
message: "이메일이나 비밀번호, 닉네임이 비어 있습니다.",
ok: false,
});
}
return null;
}
다음으로 유저가 이미 가입했는지를 prisma.user.findUnique
를 사용해 검사한다.
import { NextResponse } from "next/server";
const prisma = new PrismaClient(); // ! PrismaClient를 추가해 준다.
export async function POST(req) {
const { email, password, name } = await req.json();
// 아이디 비밀번호 닉네임 전부 존재 확인
if (!email || !password || !name) {
return NextResponse.json({
message: "이메일이나 비밀번호, 닉네임이 비어 있습니다.",
ok: false,
});
}
// 이미 가입한 유저인지 확인
const exist = await prisma.user.findUnique({
where: {
email,
},
});
if (exist) {
return NextResponse.json({
message: "이미 가입된 유저입니다.",
ok: false,
});
}
return null;
}
이메일, 비밀번호, 닉네임이 모두 존재하고, 가입되지 않은 유저라면 가입을 진행한다. 이 때 비밀번호를 DB에 저장할 때는 보안을 위해 암호화해야 한다. 이를 위해 bcrypt
라이브러리를 사용했다.
import { PrismaClient } from "@prisma/client";
import { NextResponse } from "next/server";
import bcrypt from "bcrypt";
const prisma = new PrismaClient();
export async function POST(req) {
const { email, password, name } = await req.json();
// 아이디 비밀번호 닉네임 전부 존재 확인
if (!email || !password || !name) {
return NextResponse.json({
message: "이메일이나 비밀번호, 닉네임이 비어 있습니다.",
ok: false,
});
}
// 이미 가입한 유저인지 확인
const exist = await prisma.user.findUnique({
where: {
email,
},
});
if (exist) {
return NextResponse.json({
message: "이미 가입된 유저입니다.",
ok: false,
});
}
// 가입 로직 작성
const hashedPassword = await bcrypt.hash(password, 10);
const user = await prisma.user.create({
data: {
email,
password: hashedPassword,
name,
image:
"https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png", // TODO: 임시 빈 프로필 사진. 추후 수정
},
});
return NextResponse.json(user);
}
이대로 모든 검사를 통과하면 정상적으로 유저 정보가 DB에 저장된다.
클라이언트 측에서 유저 정보에 접근하기 위해서는 useSession
훅을 사용하면 접근할 수 있다.
const { data: session } = useSession({
required: true,
onUnauthenticated() {
router.push("/login");
},
});
useSession
의 onUnauthenticated
를 사용하면 특정 페이지에 로그아웃 상태로 접근했을 때의 경우를 처리해 줄 수 있다.