소셜 로그인 구현하기 실전 feat. Next-Auth, 세션, DB 어댑터

H·2024년 1월 3일
post-thumbnail

코드 위주로 작성한 글입니다.
구조적으로 이해하고싶다면 Cookie + Session 조합 (DB로 보안강화까지) 를 읽어주세요!


Next-Auth 라이브러리

이거 있으면 next.js에서 Oauth (소셜로그인) 구현 가능하다
사용법은 매우 쉽다. 얼마나 쉽냐면 자기들 공식홈 소개란에 이렇게 써놈.


//package.json
"next": "latest",
"next-auth": "^4.21.1",
"mongodb": "^4.17.1",
"@next-auth/mongodb-adapter": "^1.1.3",

인증은 세션방식을 따릅니다


1. 라이브러리 설치

npm install next-auth

2. API 추가

//[...nextauth].js  
export const authOptions = {
import NextAuth from 'next-auth'
import AppleProvider from 'next-auth/providers/apple'
import FacebookProvider from 'next-auth/providers/facebook'
import GoogleProvider from 'next-auth/providers/google'
import EmailProvider from 'next-auth/providers/email'

export default NextAuth({
  providers: [
    // OAuth authentication providers...
    AppleProvider({
      clientId: process.env.APPLE_ID,
      clientSecret: process.env.APPLE_SECRET
    }),
    FacebookProvider({
      clientId: process.env.FACEBOOK_ID,
      clientSecret: process.env.FACEBOOK_SECRET
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET
    }),
    // Passwordless / email sign in
    EmailProvider({
      server: process.env.MAIL_SERVER,
      from: 'NextAuth.js <no-reply@example.com>'
    }),
  ]
})
  secret: process.env.NEXT_PUBLIC_SECRET,
};

export default NextAuth(authOptions); 

⚠️ pages/api/auth/[...nextauth].js 로 파일경로를 지정해야한다

[...nextauth].js 파일은 Next.js에서 동적 라우팅을 위한 파일로, /api/auth로 들어오는 요청에 대한 처리와 NextAuth.js를 활용한 사용자 인증 로직이 담겨 있다

저기 길게 나열된 Providers는 사용자가 해당 서비스를 통해 로그인할 수 있게 해주는건데
본인 프로젝트에서 사용할거 찾아서 가져오면 된다. (나는 구글)


3. 환경변수 추가
(해당 소셜에서 로그인 api를 받았다는 가정하에 .. 방법은 구글링하면 바로 나옵니다! )
발급받은 clientIdclientSecret은 루트 폴더 내 .env 파일에 적어둠

//.env

# 구글 OAuth 
NEXT_PUBLIC_GOOGLE_CLIENT_ID='구글에서 발급받은 ID'
NEXT_PUBLIC_GOOGLE_CLIENT_SECRET= '구글에서 발급받은 Secret'
NEXT_PUBLIC_SECRET= 마음대로지정
NEXTAUTH_URL=next.js가 실행될 URL 

NEXTAUTH_URL 저거 설정안했더니 터미널에 에러 뜸.

4. 로그인 / 로그아웃

'use client'

import { signIn, signOut } from 'next-auth/react'

<button onClick={()=>{ signIn() }}>로그인</button>
<button onClick={()=>{ signOut() }}>로그아웃</button> 

5. 클라이언트 호출
리액트 훅인 useSession()로 현재 로그인한 사용자 정보를 불러올 수 있다
대신 클라이언트 측에서 호출되는 함수라 html 다 보여주고나서 한 박자 늦게 실행될 수 있다.
getServerSession() 를 사용하면 서버에서 불러와서 클라이언트로 전송가능하다.

import { getServerSession } from 'next-auth'
import { authOptions } from '@/pages/api/auth/[...nextauth]'

export default async function Home() {

  let session = await getServerSession(authOptions);
  console.log('확인', session)
  
}

로그인 완료하고 콘솔 유저정보를 확인해보면
로그아웃하면 null 로 나옴.


DB adapter로 보안강화

세션 정보에는 사용자의 중요한 데이터가 포함될 수 있습니다. 이 정보를 데이터베이스에 저장함으로써 클라이언트 측에서의 노출과 조작이 어려워지며, 보안 측면에서 강화됩니다.
자세한 설명은 로그인 보안 취약점 읽어주세요!

DB adapter 작동 방식
1. 첫 로그인시 자동으로 회원가입 -> DB에 회원정보 저장
2. 로그인시 자동으로 세션정보를 DB에 보관.
3. 서버에서 지금 로그인된 사용자정보가 필요하면 DB에 있던 세션정보를 조회해서 가져옴.
4. 로그아웃시 사용자 세션정보는 DB에서 삭제.


MongoDB 세팅

npm install mongodb
// MongoDB의 클라이언트를 가져옵니다.
import { MongoClient } from 'mongodb';

// MongoDB 서버의 URL입니다. 실제 URL 여기에 입력
const url = 'DB접속URL';

// connectDB 변수를 선언
let connectDB;

// 개발 환경에서 실행될 때
if (process.env.NODE_ENV === 'development') {
    // global 객체에 _mongo라는 키로 MongoClient의 인스턴스를 저장합니다.
    // 이미 저장된 값이 없는 경우에만 MongoClient의 인스턴스를 생성하여 저장합니다.
    if (!global._mongo) {
        global._mongo = new MongoClient(url).connect();
    }
    // connectDB 변수에 global 객체에 저장된 MongoClient의 인스턴스를 할당합니다.
    connectDB = global._mongo;
} else {
    // 프로덕션 환경에서 실행될 때
    // 항상 새로운 MongoClient의 인스턴스를 생성하여 connectDB 변수에 할당합니다.
    connectDB = new MongoClient(url).connect();
}

// connectDB 변수를 내보냅니다.
export { connectDB };
  • MongoClient는 MongoDB 서버와의 연결을 나타내는 객체
  • 개발환경에서는 MongoDB 연결을 재사용 :
    개발 중에는 여러 번 코드를 수정하고 테스트를 반복하므로.
    연결을 재사용함으로써 불필요한 연결 생성을 방지하고 효율적으로 작업할 수 있다.
  • 프로덕션 환경에서 항상 새로운 연결 생성:
    안정성과 신뢰성을 유지하기 위한 선택으로, 각각의 요청이 독립적으로 처리되고 이전 연결의 상태에 영향을 받지 않도록 한다. (이전 연결에서 발생한 잠재적인 문제가 현재 연결에 영향미칠 수 있음)

라이브러리 설치

npm install @next-auth/mongodb-adapter 

[...nextauth].js 코드추가

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { connectDB } from "@/db/dababase";
import { MongoDBAdapter } from "@next-auth/mongodb-adapter";

export const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
      clientSecret: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_SECRET,
    }),
  ],
  secret: process.env.NEXT_PUBLIC_SECRET,
  adapter : MongoDBAdapter(connectDB), //nextauth와 db연결을 위해 추가된 코드
};

export default NextAuth(authOptions); 

이제 세션 DB 생성 완료!

확인

몽고디비 사이트 들어가서 확인해보면 'test'라는 db와 그안에 3개의 컬렉션이 만들어졌다.

accounts 모든 계정을 보관 (구분은 이메일로.)
sessions 현재 로그인된 사용자 정보. 여기서 sessionToken 으로 현재 쿠키값을 확인할 수 있음
users 사용자 정보 보관(소셜로그인에 사용된 대표 이메일 저장)

저장된 사용자 정보 불러오기

const db = (await connectDB).db('test'); //test 데이터베이스 연결
const collection = db.collection('sessions');//sessions 컬렉션 가져오기 

참고
next-auth.js
TCP

profile
Hello

0개의 댓글