NextAuth는 뭐가 편하지?

박성훈·2025년 5월 7일

dev_log

목록 보기
6/6
post-thumbnail

이번 글에서는 next-auth 라이브러리를 사용하여 소셜로그인(카카오)을 구현하면서, 그냥 소셜로그인을 구현하는 것보다 뭐가 편했고 간소화되었는지 느낀점들을 적어보려 합니다.
(어떻게 구현했는지가 아닌, 라이브러리를 사용했을 때 느낀점이 내용의 중점이기 때문에 구현 코드는 포함되어 있지 않음을 알려드립니다.)

인증 기능 구현을 위한 빌드업

기존 next.js로 구현했던 사이드프로젝트에 로그인 기능을 붙혀보고 싶었습니다.
그러던 중 nextAuth라는 라이브러리를 통해 쉽게 소셜로그인을 구현할 수 있다는 점을 알게 되었고, 관련해서 조금 더 알아보았습니다.

우선, next-auth를 구현하기 전 기본적으로 소셜로그인이 어떤 방식으로 작동하는지 확실하게 이해를 해야 next-auth라이브러리가 어떤 점을 간소화시켜주는 지 정확히 이해하고 사용할 수 있다고 생각했습니다.

OAuth 2.0


소셜로그인 중 카카오 로그인이 어떤 방식으로 이루어지는 지 살펴보았습니다.

  1. 우선 서비스 클라이언트에서 Kakao 로그인 버튼을 누르면 Kakao.Auth.authorize()가 호출되면서 카카오톡 로그인 페이지로 이동합니다.
  2. 계정이메일과 비밀번호를 입력 후 로그인을 클릭하면 우선, 카카오톡은 카카오 인증서버에 해당 사용자의 동의화면을 요청하고, 인증서버에서 동의항목을 확인한 다음 동의화면으로 이동시켜줍니다.
  3. 동의화면에서 동의여부를 체크하고 '동의하고 계속하기' 버튼을 클릭하면, 카카오 인증서버는 서비스에서 지정한 callback URI로 인증코드를 보내줍니다.
  4. 서비스에서는 받은 인증코드를 가지고 인증서버에 토큰을 요청합니다.
  5. 인증서버에서 유효한 인증코드인 것이 확인되면, 토큰을 발급해줍니다.
  6. 서비스에서는 받은 토큰들로 로그인 서비스를 제공할 수 있습니다.

위의 단계를 거쳐 로그인이 완료되게 됩니다.

이를 위해 개발단계에서는 특히 3번을 처리하기 위해

  1. redirect URL을 구성해야하고, 사용자 리디렉션을 별도로 구현해야 합니다.
  2. 그리고 인증코드나 토큰 정보들을 따로 관리하고 있어야하고, JWT토큰 또는 DB 기반 세션을 따로 관리해 주어야합니다.
  3. 보안을 위해서 별도의 백엔드 서버를 두고 인증코드와 같은 중요한 정보들을 관리해야합니다.

그렇다면 Next-Auth는 위의 단계에서 어떤 부분을 더 편리하게 간소화시켜주고 있는 걸까요??

Next Auth

NextAuth에 대해 알아봤을 때, 저는 위에서 살펴본 복잡한 OAuth 인증 플로우를 설정만으로 자동화해주는 라이브러리라고 이해했습니다.

파란색으로 동그라미 친 부분을 아래의 코드와 같은 NextAuth의 간단한 속성 설정 몇 개로 구현할 수 있기 때문입니다.

export const authOptions: NextAuthOptions = {
  providers: [
    KakaoProvider({
      clientId: process.env.KAKAO_CLIENT_ID as string,
      clientSecret: process.env.KAKAO_CLIENT_SECRET as string,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  session: {
    strategy: 'jwt',
  },
  callbacks: {
    ...
  },
};

좀 더 자세히 제가 느꼈던 간편한 점들을 살펴보도록 하겠습니다.

1️⃣ 백엔드 없이 안전하게 인증 처리

좀 전에 기본적으로 OAuth를 구현하기 위해 별도의 백엔드 서버를 두고 인증코드와 같은 중요한 정보들을 관리해야 한다고 했습니다.

NextAuth는 Next.js의 API Routes 기능으로 /api/auth/[...nextauth] 경로를 통해 백엔드 역할을 수행합니다.

이를 통해 인증코드, token등 민간한 정보들을 서버 측에서만 다루고 자연스럽게 클라이언트는 직접 토큰을 다루지 않아도 되기 때문에 보안 이슈를 최소화 할 수 있습니다.

왜냐하면, 로그인된 사용자만 접근할 수 있는 API를 호출할 때도, 클라이언트에서 토큰을 보내는 것이 아니라 api routes에서 세션 정보를 가져와서 인증여부를 판단하기 때문이죠.
아래의 코드처럼 말이에요.

import { getServerSession } from "next-auth"
import { authOptions } from "../auth/[...nextauth]/route"

export async function GET(req: Request) {
  const session = await getServerSession(authOptions)

  if (!session) {
    return new Response(JSON.stringify({ message: "Unauthorized" }), {
      status: 401,
    })
  }

  return new Response(JSON.stringify({ message: "Welcome!", user: session.user }), {
    status: 200,
  })
}

Next.js는 풀스택 프레임워크니까요!

즉, 별도의 백엔드 서버를 가지고 있지 않아도 간편하게 그리고 안전하게 인증절차를 구현할 수 있는거죠!

2️⃣ 상태관리가 필요없다

로그인 기능을 구현하면 일단 토큰은 어디에 저장할 것이며, 로그인 여부에 대한 상태와 유저 정보에 대한 상태까지 관리해야할 상태가 많습니다.

하지만, NextAuth에서는

const { data, status } = useSession();

useSession() 훅을 통해 로그인 여부, 유저정보에 접근할 수 있습니다.
useSession()훅의 리턴 값들은 최초에만 fetch("/api/auth/session")를 통해 가져오고 그 이후에는 캐싱된 값을 리턴하기 때문에 서버 트래픽이 폭증하는 걱정도 할 필요가 없죠.

그래서, 로그인 여부에 따라 달라지는 컴포넌트도 다음과 같이 쉽게 구현할 수 있습니다.

{status !== 'authenticated' && <ButtonAtom ...>로그인</ButtonAtom>}
{status === 'authenticated' &&<ButtonAtom ...>로그아웃</ButtonAtom>}

3️⃣ 별도의 callback URI를 만들 필요가 없다

소셜로그인의 인증코드는 서비스에서 지정한 callback URI로 들어옵니다.

https://www.example.com/callback?code=123524545ffa...

이런 식으로 말이죠.

그래서 개발단에서 이 callback URI를 위해 따로 라우트를 만들어줘야 했습니다.

NextAuth는 이 callback URI를 따로 만들어 줄 필요가 없습니다.
/api/auth/[...nextauth] 여기서 알아서 다 해주기 때문이죠.

애초에 동적라우팅 기법으로 되어있기 때문에 callback URI는 물론 auth와 관련된 모든 api를 여기서 처리해줍니다.

4️⃣ 별도로 로그인, 로그아웃 기능을 구현할 필요가 없다.

카카오 로그인만 보더라도 로그인 버튼을 클릭했을 때부터의 과정을 별도로 구현해야하고, 로그아웃 또한 관련 로직을 구현해서 관리하던 토큰 값이나 사용자 정보값들을 초기화 시켜주어야합니다.

NextAuth는 자체적으로 signIn() signOut() 함수를 제공합니다.

signIn()은 사용자가 특정 제공자(예: 카카오, 구글 등)로 로그인을 시도할 때 사용됩니다. 이 함수는 사용자가 로그인하려는 제공자와 관련된 인증 플로우를 시작하게 합니다.

signOut()은 사용자가 로그아웃할 때 호출하는 함수입니다. 로그아웃을 하면 사용자의 세션 정보가 삭제되거나 무효화됩니다.

그래서 기본적인 로그인, 로그아웃 기능이라면 별도로 구현할 필요가 없습니다.

결론

이번 NextAuth를 통한 카카오 로그인을 구현해보면서 개발자로서 느낀점이 있습니다.
라이브러리를 사용하기까지의 제 개인적인 흐름에 대해 다시 생각해보는 계기가 되었다는 점인데요!

그동안은 라이브러리를 사용할 때, 이렇게까지 깊게 생각하지는 않았던 것 같습니다.
뭐 예를 들어 socket 통신을 구현할 때 이 라이브러리를 사용하면 좋다더라! 하면, 음 그렇구나 하고 사용했었죠..

사실 그러다보니 라이브러리를 사용하지 않고는 어떤 원리로 구현되는지 어떻게 구현해야하는지 제대로 알지 못했고, 종종 라이브러리 이슈로 추가적인 대응이 필요한 상황에 제대로 대응하지 못했던 경험이 있었습니다.

이번에 NextAuth를 사용하지 않은 상황에서 어떤 원리로 구현되는지를 먼저 이해하고 NextAuth의 공식문서를 보니 라이브러리에서 제공하는 기능이 어떤 부분을 간소화시켜주었는지 파악할 수 있게 되었고,

결과적으로, 단순히 "편리하니까 쓰자"는 접근이 아닌, "직접 구현했을 때 어떤 어려움이 있었고, 그걸 NextAuth가 어떻게 해결해주는가"를 먼저 고민한 덕분에 이번 경험은 단순한 기능 구현을 넘어서 라이브러리를 바라보는 관점 자체를 바꿔준 계기가 되었습니다.

앞으로도 새로운 라이브러리나 도구를 접할 때 단순히 사용법만 익히는 데 그치지 않고, 그 도구가 왜 필요한지, 어떤 원리를 감추고 있는지를 먼저 고민해보려 합니다.
이러한 태도가 개발자로서 더 깊이 있는 성장을 만들어줄 것이라 믿습니다.

profile
2년차 프론트엔드 개발자입니다.

0개의 댓글