Javascript/NextJS

[NextJS] Google OAuth 연동 (feat. next-auth)

  • -
728x90

어느정도 구조 파악이 됐으니 구글 소셜 로그인을 구현해보자.  

  

next-auth

https://next-auth.js.org/

 

NextAuth.js

Authentication for Next.js

next-auth.js.org

next-auth는 next 전용 라이브러리로 인증 로직을 보다 쉽게 구현할 수 있도록 해준다. 마치 django의 drf 같은 녀석인가??  

 

설치부터 해주자.

> yarn add next-auth

 

공식문서를 확인해보면 API route를 만들어주기 위해 pages/api/auth/[...nextauth].js 에 위와 같이 설정할 수 있다고 나와있다.

하지만 지금 나는 Next 13 버전을 쓰고 있으므로 nextjs의 공식문서를 확인해보면 app/api 디렉토리 아래의 route 파일에서 api 경로를 처리할 수 있다고 나와있다.

https://nextjs.org/docs/app/building-your-application/routing/router-handlers

 

Routing: Route Handlers | Next.js

Using App Router Features available in /app

nextjs.org

위 그림을 보면 이해할 수 있다.

 

여기서 Rounting files Convention에 있던걸 생각하면, 가변 동적 라우팅을 사용하면 더욱 편하게 작업할 수 있다.

가변 동적 라우팅은 [...folder]를 의미하는데, 때에 따라 크기가 달라지는 배열을 받고 싶다면, pages/post/[...slug].js 와 같이 경로를 구성하면 된다. slug 는 [...param] 과 같이 원하는 이름으로 바꾸어도 된다. (예를들면 api/user/id)

 

/app/api/auth/[...nextauth]/route.ts

route.ts 파일에 아래와 같이 원하는 소셜 로그인의 Provider의 초기값을 설정할 수 있다.

 

client id, secret key를 만드는 법은 wontube때도 간단하게 다뤘고, 잘 모르겠다면 구글링 해주세요~

(참고, redirect_uri는 승인된 리디렉션 URI에 http://localhost:3000/api/auth/callback/google를 넣어주면 된다)

import NextAuth, { NextAuthOptions } 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_KEY,
    }),
  ],
});

export { handler as GET, handler as POST };

 

dotenv에 설정되있는 환경변수들을 자동완성으로 사용하고싶다면 아래 파일을 root 디렉토리에 추가하면 된다.

environment.d.ts

declare namespace NodeJS {
  export interface ProcessEnv {
    readonly GOOGLE_CLIENT_ID: string;
    readonly GOOGLE_CLIENT_SECRET_KEY: string;
  }
}

다음으로 환경 변수 설정이 더 필요한데, NEXTAUTH_SECRET, NEXTAUTH_URL이 필요하다. 배포할때 필요한거 같깉한데.. 미리 해두자.

NEXTAUTH_SECRET=
NEXTAUTH_URL=

GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET_KEY=

dotenv 파일에 이런식으로 환경변수를 구성해주면 된다.

NEXTAUTH_SECRET은 터미널에서 $ openssl rand -base64 32 이 명령어로 쉽게 만들 수 있다.

 

SessionProvider

위 과정이 완료되었으면 이제 SessionProvider를 이용하여 프로젝트에 뿌려주면 되는데, next-auth에 들어있는 SessionProvider는 client 코드에서만 사용할 수 있다. 그럴때 파일 최상단에 'use client'라고 적어주면되는데 RootLayout에는 metadat 설정 같은 서버에서 사용하는 코드들 때문에 'use client'를 사용할 수 없다. 따라서 AuthProvider라는 클라이언트 컴포넌트를 만들어서 사용해야 한다.

 

'src/components/provider/AuthProvider.tsx'

"use client";
import React, { ReactNode } from "react";
import { SessionProvider } from "next-auth/react";

interface AuthProviderProps {
  children: ReactNode;
}

const AuthProvider = ({ children }: AuthProviderProps) => {
  return <SessionProvider>{children}</SessionProvider>;
};

export default AuthProvider;

 

'src/app/layout.tsx'

import type { Metadata } from "next";
import { Inter } from "next/font/google";

import "./globals.css";
import Header from "@/components/Header";
import AuthProvider from "@/components/provider/AuthProvider";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "chat-app",
  description: "Generated by create next app",
};

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Header />
        <AuthProvider>{children}</AuthProvider>
      </body>
    </html>
  );
}

 

그런 다음 session 값이 필요한 클라이언트 컴포넌트에서 session 값이 잘 들어오는지 확인해보자.

"use client";
import { useSession } from "next-auth/react";

export default function Home() {
  const session = useSession();

  console.log(session);

  return <main>Home</main>;
}

위와 같이 useSession을 이용하면 src/app/api/auth/[...nextauth]/route.ts 에서 설정한 값들을 사용할 수 있다.

useSession은 클라이언트 컴포넌트에서만 사용할 수 있다.

 

콘솔을 확인해보면 다음과 같이 나온다.

로그인 행동을 취하지 않았기 때문에 unauthenticated가 나오는거고 잘 작동하는 듯하다.

 

로컬로 작업시 환경변수에 설정을 안해주면 에러가난다.

NEXTAUTH_URL=http://localhost:3000

 

 

LoginButton

 

로그인 버튼을 만들기 위해서 login 페이지를 만들어주고, 아래와 같이 코드를 작성해주자.

 

src/app/(auth)/login/page.tsx

"use client";
import { signIn, useSession } from "next-auth/react";
import React from "react";

const Login = () => {
  const session = useSession();
  console.log(session);
  return (
    <div>
      <button onClick={() => signIn("google")}>signin with Google</button>
    </div>
  );
};

export default Login;

따로 콜백 처리도 없고 토큰 처리도 필요 없다. 너무 간편하지 않은가...

 

로그인 하기 전

로그인 후

로그아웃

 

 

예전에 WONTUBE 하면서 직접 로그인 요청부터 토큰 받는것까지 구현해봤었지만, 그 뒤에 youtube api를 받아오는거에 있어서 헤메다가 결국 라이브러리를 썻던 기억이... ㅠ

 

직접 로그인 요청부터 다 짜봐도 좋겠지만, next-auth를 공부하는것도 재밌다.

 

 

 

https://next-auth.js.org/providers/google

 

Google | NextAuth.js

Documentation

next-auth.js.org

 

 

 

 

728x90
300x250
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.