npm install next-auth
Next-auth 라이브러리를 사용하면 기본적으로 JWT 방식.
유저 세션데이터를 DB에 저장해두지 않고 JWT만 유저에게 보내고
유저가 로그인이 필요한 페이지 방문시 유저가 제출한 JWT만 검사해서 입장시켜주는 방식
/app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth"
const handler = NextAuth({
...
})
export { handler as GET, handler as POST }
import NextAuth from "next-auth";
import { connectDB } from "@/utils/database";
import { MongoDBAdapter } from "@next-auth/mongodb-adapter";
import GithubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
import KakaoProvider from "next-auth/providers/kakao";
const authOptions = {
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
KakaoProvider({
clientId: process.env.KAKAO_CLIENT_ID,
clientSecret: process.env.KAKAO_CLIENT_SECRET,
}),
],
secret: process.env.NEXTAUTH_SECRET, //jwt생성시쓰는암호
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST, authOptions };
SessionProvider
- NextAuth.js 라이브러리의 일부로, 애플리케이션 내에서 사용자 세션을 관리하는 컴포넌트.
- 로그인, 로그아웃 상태를 추적하고, 사용자의 세션 정보를 애플리케이션 전반에 걸쳐 유지한다.
- 애플리케이션의 최상위에 위치하여, 애플리케이션 전체에서 사용자의 인증 상태와 세션 정보에 쉽게 접근할 수 있도록 한다.
- 컨텍스트 제공: SessionProvider는 React의 컨텍스트(Context) API를 사용하여, 하위 컴포넌트들이 현재 사용자의 세션 정보에 쉽게 접근할 수 있도록 한다. 이를 통해 개발자는 어느 컴포넌트에서든지 사용자의 로그인 상태나 세션 데이터를 활용할 수 있다.
- useSession이라는 리액트 훅을 통해 접근하며, 주로 layout에 세션 컨텍스트인 로 감싸준다.
단, SessionPrvider는 클라이언트 컴포넌트에서 사용하기 때문에 별도의 AuthProvider 컴포넌트를 생성하여 SessionPrvider로 감싼 뒤 layout에 넣어주었다.
// board/src/components/provider/AuthProvider.js
"use client";
import { SessionProvider } from "next-auth/react";
export default function AuthProvider({ children }) {
return <SessionProvider>{children}</SessionProvider>;
}
// board/src/app/layout.js
import { Inter } from "next/font/google";
import "./globals.css";
import AuthProvider from "../components/provider/AuthProvider";
import Header from "@/components/Header";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "✨게시판 프로젝트",
description: "게시판 ~~~~",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
<AuthProvider>
<Header />
{children}
</AuthProvider>
</body>
</html>
);
}
// board/src/components/AuthButton.js
"use client";
import TextButton from "./UI/TextButton";
import { useSession, signIn, signOut } from "next-auth/react";
export default function AuthButton({}) {
const { data: session } = useSession();
if (session) {
console.log(session);
return (
<div className="flex">
<img
className="avatar"
src={session.user.image}
alt={session.user.name}
/>
{session.user.email ? (
<span className="px-1">{session.user.email}</span>
) : (
<span className="px-1">{session.user.name}</span>
)}
<TextButton
text="logOut"
onClickFn={() => {
signOut();
}}
/>
</div>
);
}
return (
<>
<TextButton text="logIn" onClickFn={() => signIn()} />
</>
);
}
MongoDB adapter 설정
npm install @next-auth/mongodb-adapter
import { connectDB } from "@/utils/database";
import { MongoDBAdapter } from "@next-auth/mongodb-adapter";
const authOptions = NextAuth({
providers: [
//깃헙,구글,카카오 등..
],
secret: process.env.NEXTAUTH_SECRET,
//어댑터 추가!
adapter: MongoDBAdapter(connectDB),
});
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
어댑터 추가해 준 뒤 로그인 하면 몽고db에 3개의 폴더가 생성된다.
![]()
- sessions : 현재 로그인된 유저 정보, 로그인 유효기간 포함
- users는 유저(이메일로 구분)
- accounts는 유저 계정
하나의 유저는 여러개의 계정을 가지고 있을 수 있음.
유저는 1명이지만 계정은 2개 이상 생성이 가능(이메일이 같으면 같은 유저라고 자동으로 간주)
getServerSession(authOptions); 사용하여 유저의 세션정보 가져와서, 유저가 글을 등록할 때 유저 이름, 이메일, 프로필 이미지 모두 db에 저장되도록 수정해주었다.
로그아웃 상태일 때 401에러를 응답하도록 하였는데, 이후 추가적으로 글 작성 페이지에서 로그인하지 않은 유저는 로그인페이지로 리다이렉트 시켜주었다.
// board\src\app\api\new\route.js
import { connectToDatabase } from "@/utils/database";
import { NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { authOptions } from "../auth/[...nextauth]/route";
export async function POST(req) {
const { postCollection } = await connectToDatabase();
const session = await getServerSession(authOptions);
console.log(session);
if (!session) {
return NextResponse.json(
{ error: "로그인이 필요합니다." },
{ status: 401 }
);
}
try {
const data = await req.json();
// 생략..
const postData = {
...data,
email: session.user.email,
name: session.user.name,
image: session.user.image,
};
console.log(postData);
await postCollection.insertOne(postData);
return NextResponse.json(postData);
} catch (error) {
// 에러처리
}
}
import { useSession } from "next-auth/react";
export default function ListItem({ userInfo, id }) {
const { data: session } = useSession();
const isAuthor = session?.user?.email === userInfo.email;
return (
{isAuthor ?
({/*수정삭제아이콘 노출 */})
:
({/*userInfo.image, userInfo.name 노출 */})
}
)}

에러메시지가 왕창..
next-auth/mongodb-adapter 패키지가 mongodb 버전 5.x 또는 4.x를 요구하기 때문에 충돌이 발생.
mongodb 4.0버전으로 재설치..
npm uninstall mongodb
npm install mongodb@4
사용자가 처음에 GitHub으로 가입했고, 같은 이메일로 Google을 통해 가입하려고 시도할 때 발생

NextAuth에서 제공하는 GitHub, Google, Kakao 같은 여러 소셜 로그인 방법을 사용할 때, 하나의 이메일 주소에 여러 제공자를 연결하는 것은 기본적으로 지원되지 않는다. 보안상의 이유로 자동으로 계정을 연결하는 기능을 제공하지 않기 때문..
관련 이슈 : stackoverflow
공식 문서 : allowDangerousEmailAccountLinking: true
allowDangerousEmailAccountLinking: true,추가해주면 해결!
const authOptions = {
providers: [
GithubProvider({
// 생략...
allowDangerousEmailAccountLinking: true,
}),
],
};
몽고 DB setting
MongoDB 입출력
글 목록 조회 기능(/list)
글 상세 페이지(/detail/[id]/page.js)
글 작성 페이지
글 수정 페이지
글 삭제 페이지
404페이지 만들기
error 페이지 만들기
loading 페이지 만들기
Next-auth 회원인증기능
S3 파일업로드
글 작성 페이지 마크다운 작성페이지로 변경
캐싱, 에러처리 등 부가기능
스타일링
AWS 클라우드 배포