Project

next-auth 적용하여 소셜 로그인 구현하기

프도의길 2023. 8. 22. 00:27

NextJS 에서 next-auth 라는 라이브러리를 이용하면 google , facebook , naver 같은 소셜 로그인 기능을 쉽게 관리 및 추가 할 수 있습니다.

이번 포스트에서는 next-auth 를 통해 소셜 로그인을 구현하는 방법에 대해서 알아보겠습니다.

 

먼저 next-auth 라이브러리 설치를 진행 해줍니다
npm i next-auth
  1. pages/api 경로에 auth 폴더를 생성하고 그 안에 [...nextauth].js 파일을 생성 한 뒤 next-auth 관련 설정 작성합니다.
  2. 원하는 소셜로그인의 provider를 providers 객체에 추가해줍니다. 여기서는 google 로그인을 기능을 위해 GoogleProvider를 추가하겠습니다.
  3. .env 환경 변수에 clientId와 clientSecret 값을 추가하여 provider에 해당 값들을 제공합니다.
// pages/api/auth/[...nextauth].ts
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export default NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    GoogleProvider({
      clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_SECRET as string,
    }),
  ],
  secret: process.env.NEXT_PUBLIC_NEXTAUTH_SECRET,
  callbacks: {
    async session({ session, token, user }) {
      console.log("INSIDE OF THE SESSION CALLBACK");

      return { ...session, user: { ...session.user, ...user } };
    },
  },
});

7번째 줄에 prisma는 프로젝트하면서 prisma 사용해줘서 선언 했습니다

 

SessionProvider 설정

next-auth/react 에서 제공하는 SessionProvider로 Component를 감싸 nextjs에서 useSession 훅을 통해 session 정보를 접근 할 수 있도록 합니다.

import { SessionProvider } from "next-auth/react";
import { ChakraProvider } from "@chakra-ui/react";
import type { AppProps } from "next/app";
import { theme } from "@/chakra/theme";
import { Toaster } from "react-hot-toast";

export default function App({
  Component,
  pageProps: { session, ...pageProps },
}: AppProps) {
  return (
      <SessionProvider session={session}>
        <ChakraProvider theme={theme}>
          <Component {...pageProps} />
          <Toaster />
        </ChakraProvider>
      </SessionProvider>
   
  );
}

로그인 및 세션 정보 접근

기본 설정은 완료 됬으니 이제 실제 로그인 그리고 로그아웃 하는 방법에 대해서 알아보겠습니다.

어려운거 없습니다 그저 next-auth/react 에서 제공하는 signIn , signOut 그리고 useSession 을 활용하면 됩니다.

import Auth from "@/components/Auth/Auth";
import Chat from "@/components/Chat/Chat";
import { Box } from "@chakra-ui/react";
import type { NextPageContext } from "next";
import { getSession, useSession } from "next-auth/react";


export default function Home() {
  const { data: session } = useSession();
  console.log("clientSession", session);
  
  const reloadSession = () => {
    const event = new Event("visibilitychange");
    document.dispatchEvent(event);
  };

  return (
    <Box>
      {session?.user?.username ? (
        <Chat session={session} />
      ) : (
        <Auth session={session} reloadSession={reloadSession} />
      )}
    </Box>
  );
}

export async function getServerSideProps(context: NextPageContext) {
  const session = await getSession(context);

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

서버로 데이터 받아오기 위해서 getServerSideProps로 진행했습니다

import { CreateUsernameData, CreateUsernameVariables } from "@/util/types";
import { useMutation } from "@apollo/client";
import { Button, Center, Image, Input, Stack, Text } from "@chakra-ui/react";
import { Session } from "next-auth";
import { signIn } from "next-auth/react";
import { useState } from "react";
import toast from "react-hot-toast";
import UserOperations from "../../graphql/operations/user";

interface IAuthProps {
  session: Session | null;
  reloadSession: () => void;
}

const Auth = ({ session, reloadSession }: IAuthProps) => {
  const [username, setUsername] = useState("");

  const [createUsername, { loading, error }] = useMutation<
    CreateUsernameData,
    CreateUsernameVariables
  >(UserOperations.Mutations.createUsername);

  const onSubmit = async () => {
    if (!username) return;
    try {
      const { data } = await createUsername({ variables: { username } });

      if (!data?.createUsername) {
        throw new Error();
      }

      if (data.createUsername.error) {
        const {
          createUsername: { error },
        } = data;

        throw new Error(error);
      }

      toast.success("Username Successfully");

      reloadSession();
    } catch (error: any) {
      toast.error(error?.message);
      console.log("err", error);
    }
  };
  console.log("se", session);
  return (
    <Center height="100vh">
      <Stack spacing={8} align="center">
        {session ? (
          <>
            <Text fontSize="3xl">Creat a Username</Text>
            <Input
              placeholder="Enter a username"
              value={username}
              onChange={(e) => setUsername(e.target.value)}
            />
            <Button width="100%" onClick={onSubmit} isLoading={loading}>
              Save
            </Button>
          </>
        ) : (
          <>
            <Text fontSize="3xl">MessengerQL</Text>
            <Button
              onClick={() => signIn("google")}
              leftIcon={<Image height="20px" src="/images/googlelogo.png" />}
            >
              Continue with Google
            </Button>
          </>
        )}
      </Stack>
    </Center>
  );
};

export default Auth;

import { signIn } from "next-auth/react" 여기서 가져와서 signIn하면 

 

로그인한 데이터 정보가 나타납니다.

import { Button, Flex } from "@chakra-ui/react";
import { Session } from "next-auth";
import { signOut } from "next-auth/react";
import ConversationsWrapper from "./Conversations/ConversationsWrapper";
import FeedWrapper from "./Feed/FeedWrapper";

interface ChatProps {
  session: Session;
}

const Chat = ({ session }: ChatProps) => {
  return (
    <Flex height="100vh" bg="#1F1F1F">
      <ConversationsWrapper session={session} />
      <FeedWrapper session={session} />
      <Button onClick={() => signOut()}>Logout</Button>
    </Flex>
  );
};

export default Chat;

로그아웃은 간단합니다 import { signOut } from "next-auth/react" 가져온걸 사용하면 됩니다,

 

결론

next-auth를 통해 간단하게 소셜 로그인을 구현하는 방법에 대해서 알아봤습니다. provider 설정 외에 db에 연동하여 회원 정보를 저장 그리고 로그인 성공 여부 관련 설정 등등 여러 설정을 진행 할 수 있어 아주 유용하다고 생각됩니다.

또한 사용하기 쉽기 때문에 NextJS 에서 빠르게 로그인을 구현하고자 한다면 라이브러리 사용을 추천드립니다.

'Project' 카테고리의 다른 글

WebSocket/ Subscription  (0) 2023.08.29
GraphQL 대화 생성  (0) 2023.08.28
GraphQL- 유저 검색 기능  (0) 2023.08.23
Graphql Query, prisma  (0) 2023.08.22
Graphql 리액트 연결  (0) 2023.08.22