NextAuth.js 구글 로그인 구현 (Next버전 13.4.2)

Jo yun hee·2023년 5월 18일
9
post-thumbnail

면접에서 소셜로그인 구현할 줄 아시나요? 라는 질문을 받아본 적이 있다.
"앗.. 아니요... 해본적이 없습니다..."

이번 프로젝트에서 소셜 로그인 구현하는 방법을 기록해보려고 한다.
다음 면접에서는 당당하게 대답할 수 있기를 바라며 :)

오늘의 기록 목표 2가지
1.NextAuth.js를 사용하여 구글 로그인을 구현해보기.
2.이 블로그를 따라 하면 소셜 로그인이 뚝딱 구현되고, 이해도 쉽게 되는 내용으로 글쓰기.

NextAuth.js?

  • NextAuth.js는 Node.js 기반의 오픈 소스 인증 라이브러리이다.
  • NextAuth.js는 다양한 인증 방법을 지원하며, 소셜 로그인 (Google, Facebook, Twitter 등) 및 기타 인증 프로토콜 (OAuth, OpenID Connect 등)을 통해 사용자 인증을 처리할 수 있다.
  • 개발자들이 복잡한 인증 로직을 구현하지 않고도 빠르고 안전하게 사용자 인증을 구현할 수 있도록 도와준다.

즉, NextAuth.js로 구글로그인을 쉽게 구현할 수 있다!

NextAuth.js 설치

yarn add next-auth

NextAuth.js 구현 방법

1. src/app/api/auth/[...nextauth]/route.ts 파일 만들기


위 공식문서 내용과 같이 13.2로 업데이트 된 후, pages가 없어지고 app디렉토리를 지원하고 있다.
공식문서

src/app/api/auth/[...nextauth]/route.ts 파일을 만들고 그 안에 공식문서 코드를 넣어준다.

import NextAuth from "next-auth"

const handler = NextAuth( //NextAuth.js를 사용하여 인증과 관련된 작업을 처리하는 핵심 함수이다.


{  ...})
export { handler as GET, handler as POST }

2. 위에 작성한 코드 {...}안에 providers를 구현한다.

구글, 카카오, 깃헙 등 정말 많은 서비스로그인을 구현할 수 있다. 아래 공식문서에서 각 사용법에 대해 확인이 가능하다.
Overview | NextAuth.js
공식문서에서 소셜로그인 코드 확인하기

나는 구글 로그인을 원하기 때문에 아래와 같이 코드를 작성해주면 된다.

import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google";

const handler = NextAuth({  
	providers: [
  GoogleProvider({
    clientId: process.env.GOOGLE_CLIENT_ID, 
    clientSecret: process.env.GOOGLE_CLIENT_SECRET
	  }),
	],
});

export { handler as GET, handler as POST };

2-1. clientId, clientSecret 환경변수를 읽어오기 위해 폴더의 최상위에서 .env.local 파일을 만들어 준다.

    GOOGLE_CLIENT_ID = 구글에서 받은 아이디 //3.에서 아이디 받아옴.
    GOOGLE_CLIENT_SECRET = 구글에서 받은 키 //3.에서 아이디 받아옴.

2-2. 타입에러 발생


해당 오류 메시지는 'clientId'의 예상 타입이 'string'이어야 한다고 오류를 보내고 있다.
만약 2-1.에 적힌 환경 변수에 GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET이 없다면 'undefined'일수도 있다. 이 타입 오류를 없애기 위해서는 'clientId'속성이 'undefined'가 아니라 항상 'string' 값으로 할당되도록 하면 된다. 결국! GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET가 없을 경우, 빈 문자열을 쓰도록 만들어주면 된다.

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";

const handler = NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID || "", // 수정!!!!
      clientSecret: process.env.GOOGLE_CLIENT_SECRET || "", // 수정!!!!
    }),
  ],
});

export { handler as GET, handler as POST };

3. google cloud에 방문하여 애플리케이션 등록, key를 발급 받는다.

구글 클라우드 링크

- Console 이동 버튼 클릭

- 상단바에서 그림에 보이는 1번 클릭 -> 2번 새 프로젝트 클릭

- 프로젝트이름 적어주고 만들기 버튼을 클릭.

- 상단바에서 내가 만든 프로젝트 이름을 클릭 -> 왼쪽 햄버거 아이콘을 클릭하면 왼쪽 메뉴창이 뜬다. -> API 및 서비스 클릭 -> 사용자 인증 정보 클릭

- 현재 아무런 정보가 없다. 상단에 동의화면구성 버튼을 클릭.

- 외부 버튼을 체크하고 만들기 버튼 클릭.

- 앱이름과 사용자 지원 이메일 그리고 개발자 연락처 정보를 작성한다. (나는 지금 필수적으로 작성해야하는 것만 입력하였다. 승인된 도메인 입력칸에는 나중에 서비스를 배포 후 도메인을 추가해줄 예정이다)

- 저장 후 계속을 클릭 클릭 클릭 후 대시보드로 돌아가기 버튼 클릭!

- 다시 사용자 인증정보 메뉴 클릭 → 사용자 인증 정보 만들기 클릭 → OAuth 클라이언트 ID 클릭

- 아래 화면처럼 내가 원하는 어플리케이션 유형과 이름, 승인된 자바스크립트 원본, 승인된 리디렉션 URL을 작성해주고 만들기 버튼 클릭!

승인된 자바스크립트 원본, 승인된 리디렉션 URL 현재 로컬 주소를 적어주었다. 배포 후 주소 바꿔줄 예정이다. 이 칸을 입력하지 않으면 오류가 난다.

- 만들기 버튼을 클릭한 후 아래와 같은 창이 뜬다!! 옆에 copy 아이콘을 클릭하여 아이디와 비밀번호를 복사하여 .env.local파일에 코드를 넣어준다!

4. src/context/AuthContext.tsx 파일를 만들고 AuthContext.tsx 파일을 만든다. 그리고 Session Provider를 감싸주자.

로그인한 사용자 정보를 가지고 있는 context를 만든다.
context안에 SessionProvider가 실제 로그인한 데이터를 가지고 있다.

"use client"; //next에서 context를 사용하기 위해서는 csr 렌더링으로 명시해주어야 한다.context는 상태를 가지고 있기 때문에!!! 서버컴포넌트는 상태에 접근 할 수 없다.
import { SessionProvider } from "next-auth/react";

type Props = {
  children:React.ReactNode;
}

export default function AuthContext({ children }: Props) {
  return <SessionProvider>{children}</SessionProvider>;
}

Session Provider가 뭘까?
로그인에 대한 세션 정보를 얻어오기 위해서 Session Provider를 사용한다. 또한 세션 정보를 접근하기 위해서는 useSession이라는 리액트 훅을 사용해야 접근이 가능하다.

5. arc/app/layout에서 <AuthContext>를 자식컴포넌트에 감싸주자.

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en" className={openSans.className}>
      <body className="w-full max-w-screen-xl overflow-auto mx-auto">
        <AuthContext>
          <header className="sticky top-0 bg-white z-10 border-b">
            <Navbar />
          </header>
          <main className="px-6">{children}</main>
        </AuthContext>
      </body>
    </html>
  );
}

6. navbar 컴포넌트로 이동하여 useSession 훅을 사용하여 로그인 정보를 가져온다.

공식문서
업로드중..
const { data: session } = useSession() //세션 정보를 가져옴

export default function Navbar() {
  const pathname = usePathname();
  const { data: session } = useSession(); //세션 정보를 가져옴

  return (
    <nav className="flex items-center justify-between px-6">
      <Link href="/">
        <h1 className="text-3xl font-bold">unigram</h1>
      </Link>

      <ul className="flex gap-4 items-center p-4">
        {menu.map((item) => (
          <li key={item.href}>
            <Link href={item.href}>
              {pathname === item.href ? item.clickedIcon : item.icon}
            </Link>
          </li>
        ))}

        {session ? ( //세션 정보가 있으면 signOut()호출
          <ColorButton text="Sign out" onClick={() => signOut()} />
        ) : ( //세션 정보가 없으면 signIn()호출
          <ColorButton text="Sign in" onClick={() => signIn()} />
        )}
      </ul>
    </nav>
  );
}

7. yarn dev로 로컬에서 열어 실행해보기~! 끗!

0개의 댓글