본문 바로가기
개발 Study/React

[Next.js/Typescript] Next-auth 소셜 로그인 연동하기

by jiyoon_92 2022. 9. 15.
반응형

소셜 로그인 연동(Kakao버전)

 

1. Next-auth 설치하기

session 관리를 위해서 next-auth라는 라이브러리로 쉽게 소셜 로그인을 구현할 수 있다고 한다. 

$npm install --save next-auth

https://next-auth.js.org/getting-started/typescript

 

TypeScript | NextAuth.js

NextAuth.js has its own type definitions to use in your TypeScript projects safely. Even if you don't use TypeScript, IDEs like VSCode will pick this up to provide you with a better developer experience. While you are typing, you will get suggestions about

next-auth.js.org


2. 프로젝트 생성 및 Next-auth 설정

테스트 프로젝트의 폴더 구조는 아래와 같이 구현했다.

폴더 구조

pages\api\auth에 [...nextauth].ts 파일을 생성하고 다음과 같이 작성한다.

import NextAuth from "next-auth";

import GoogleProvider from "next-auth/providers/google";
import NaverProvider from "next-auth/providers/naver";
import KakaoProvider from "next-auth/providers/kakao";

export default NextAuth({
  providers: [
    GoogleProvider({
      clientId : process.env.GOOGLE_ID as string,
      clientSecret: process.env.GOOGLE_SECRET as string,
    }),
    NaverProvider({
        clientId : process.env.NAVER_ID as string,
        clientSecret: process.env.NAVER_SECRET as string,
    }),
    KakaoProvider({
        clientId : process.env.KAKAO_ID as string,
        clientSecret: process.env.KAKAO_SECRET as string,
    })
  ],
  session: {
    strategy: 'jwt'
  },
  secret: process.env.SECRET as string,
});

각각 .env 에서 쓰이는 변수들은 .env.local 파일을 생성하여 그 안에 작성한다.

env파일

 

  • NEXTAUTH_URL : 접속할 nextjs 앱의 url
  • NEXTAUTH_SECRET: jwt를 암호화하거나 email token을 해쉬처리하기 위한 임의 string (openssl)을 이용하여 생성
  • KAKAO_ID: kakao로부터 발급받은 REST API 키
  • KAKAO_SECRET: kakao로부터 발급받은 Client Secret

2022.09.14 - [개발 Study/Node, js, react] - [Next.js] Kakao 로그인 API 발급 받기

 

[Next.js] Kakao 로그인 API 발급 받기

Kakao 로그인 API 발급 받는 법 1. 가입하기 https://developers.kakao.com/ Kakao Developers 카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 A..

chuun92.tistory.com

반응형

_app.tsx 에 SessionProvider를 추가해 준다.

import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { SessionProvider } from 'next-auth/react';

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <SessionProvider session={pageProps.session}>
      <Component {...pageProps} />
    </SessionProvider>
  );
}

export default MyApp

3. 페이지 구현

Next-auth는 기본적으로 Provider에 따라 로그인 화면을 제공해주지만 나는 Custom Login 화면을 구성하고 싶어서 직접 화면을 만들었다.

SSR을 이용하여 서버로부터 Session 정보를 받는 getServerSideProps를 이용하여 login page를 작성하였다.

import {NextPage} from 'next'
import {signIn, useSession, getSession, getProviders, getCsrfToken} from 'next-auth/react';
import Head from 'next/head'
import LoginButton from '../../components/LoginButton'
import Content from '../../components/ContentDiv'

const SocialLoginPage : NextPage = ()  => {
  const { data: session } = useSession();

  const login = async (provider : string) => {
    const res = await signIn(provider);
    console.log(res);
  }
  return (
    <div className="container">
      <Head>
        <title>Login</title>
        <meta name="description" content="Generated by jy" />
      </Head>
      {!session && (
        <Content>
          <LoginButton id="naver" text="네이버로 로그인" clickEventHandler={(e) => login('naver')}/>
          <LoginButton id="kakao" text="카카오로 로그인" clickEventHandler={(e) => login('kakao')}/>
          <LoginButton id="google" text="구글로 로그인" clickEventHandler={(e) => login('naver')}/>
        </Content>
      )}
    </div>
  );
}

export default SocialLoginPage;

export async function getServerSideProps(context : any) {
    const { req } = context;
    const session = await getSession({ req });
  
    if (session) {
      return {
        redirect: { destination: "/auth/home" },
      };
    }
  
    return {
      props: {
        providers: await getProviders(),
        csrfToken: await getCsrfToken(context),
      },
    };
  }

signIn('소셜')  함수로 provider에게 요청을 하여 세션정보를 받고 signOut() 함수로 세션을 종료하는데 세션을 받은 경우 /auth/home 으로 리디렉션하여 페이지 이동을 한다.

import {NextPage, InferGetServerSidePropsType } from 'next'
import {signOut, getSession} from 'next-auth/react';
import Head from 'next/head'
import LoginButton from '../../components/LoginButton'
import Content from '../../components/ContentDiv'

function HomePage({ session }: InferGetServerSidePropsType<typeof getServerSideProps>) {
    console.log(session)
    const logout = () => {
      signOut();
    }
    return (
      <div className="container">
        <Head>
          <title>Home</title>
          <meta name="description" content="Generated by jy" />
        </Head>
        {session && (
            <Content>
            <LoginButton id="" text="로그아웃" clickEventHandler={(e) => logout()}/>
            <></>
            </Content>
        )}
      </div>
    );
  }
    
export default HomePage;

export async function getServerSideProps(context : any) {
  const { req } = context;
  const session = await getSession({ req });

  if (!session) {
    return {
      redirect: { destination: "/auth/login" },
    };
  }

  return {
    props: {
      session: session
    },
  };
}

로그인 하여 홈으로 들어가면 로그아웃 버튼이 뜨고 로그아웃 클릭 시 session이 종료되며 sessionToken이 쿠키에서 삭제된다. session이 없는 경우 다시 로그인 화면으로 리디렉션 하도록 getServerSideProps() 함수를 구현하였다.

로그인이나 로그아웃 후 리디렉션을 그냥 next-auth에서 pages 값에 설정하는 방법이 있는데 뭔가 잘 안되서.. 다음 기회에 다시 해봐야 할 것 같다.


4. 구현된 로그인 화면

우선 Kakao만 진행했고 추후 Naver와 Google도 연동할 예정이다. 기회가 된다면 로그인 token과 DB 가 연동된 것 까지 해볼 것이다. Typescript가 아직 생소하긴한데 배워가면서 알아가야할 것 같다.

 

반응형

댓글