본문 바로가기
이론/Frontend

Next.js 13에서 Kakao 로그인 처리하기 with Firebase (1)

by 유세지 2023. 10. 16.

 

 

 

들어가며

오늘은 Next.js 13에서 Firebase와의 연동을 이용해 Kakao 로그인을 구현하는 방법을 알아보겠습니다. 비교적 공식 문서가 자세히 설명되어있고, 각종 정보가 많은 편이라 어렵지 않게 구현할 수 있습니다.

 

먼저 로그인을 적용하는 과정을 크게 한 번 살펴보겠습니다.

 

 

로그인 시퀀스 다이어그램 (Kakao Developers > 문서)

 

 

크게 보면 카카오 로그인, 회원 확인 및 가입, 서비스 로그인의 세 단계로 나뉘어집니다.

이 포스트에서 알아볼 것은 step1의 카카오 로그인 부분입니다. 

 

 

 

서비스 등록

카카오 API를 사용하기 위해서는 먼저 사용할 서비스를 등록해야 합니다.

Kakao Developers에서 "애플리케이션 추가하기" 를 통해 서비스를 등록해줍니다.

 

 

 

 

 

환경 설정

 

 

서비스가 등록되었다면, [요약 정보] 메뉴의 [앱 키] 에서 서비스 인증에 사용될 키 값들을 확인할 수 있습니다.

이 값들을 통해 요청을 보내는 주체가 나의 서비스임을 확인받고, API를 사용할 수 있게 됩니다.

 

이제 이 키 값들을 프로젝트에 넣어서 사용해야 하는데, 일반적인 리액트 프로젝트나 CRA 환경에서는 .env를 이용하여 환경 변수를 관리하는 것처럼 Next.js에서는 .env.local 파일에 넣어 관리할 수 있습니다. 외부에 노출되면 안되는 민감한 정보이니, 따로 관리해줍시다.

 

 

민감한 정보는 환경 변수 파일에 넣어 관리합니다.

 

NEXT_PUBLIC_KAKAO_JS_KEY=1234567890abcdefg

 

Node.js 환경에서는 환경변수의 이름을 아무렇게나 정해도 괜찮지만,

브라우저 환경에서 사용하려면 NEXT_PUBLIC 접두어를 반드시 붙여주어야 합니다.

 

준비가 끝났다면 sdk를 이용해 API 파일을 내려받아야 합니다.

별도의 컴포넌트 하나를 만들어 불러오겠습니다.

 

"use client";
import Script from "next/script";

export default function KakaoInit() {
  function kakaoInit() {
    window.Kakao.init(process.env.NEXT_PUBLIC_KAKAO_JS_KEY);
    console.log(window.Kakao.isInitialized());
  }

  return (
    <Script
      src="https://developers.kakao.com/sdk/js/kakao.js"
      onLoad={kakaoInit}
    />
  );
}

 

 

Next.js의 <Script /> 태그를 사용하기 때문에,

컴포넌트가 클라이언트에서 실행된다는 정보를 알 수 있도록 최상단에 "use client" 를 붙여줍니다.

 

이제 이 컴포넌트를 최상위 Layout 컴포넌트에 붙여주면 됩니다.

최상위 Layout에서는 글로벌에서 접근할 수 있도록 Window에 Kakao 속성을 함께 선언해줍니다.

 

 

app/layout.tsx

import Layout from "components/Layout";
import KakaoInit from "components/KakaoInit";

declare global {
  interface Window {
    Kakao: any;
  }
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <KakaoInit />
      <body>
        <Layout>{children}</Layout>
      </body>
    </html>
  );
}

 

 

이제 프로젝트 단에서 카카오 API의 세팅은 끝났으니, 바로 사용해보겠습니다.

 

 

 

로그인

카카오 로그인 버튼은 공식 디자인 가이드를 따라야합니다.

[카카오싱크] 메뉴에서 원하는 크기와 모양의 공식 이미지를 내려받아줍니다.

페이지에 들어갈 버튼이니 본인 서비스의 디자인을 고려하여 고르는 것이 좋습니다.

 

 

 

이미지를 내려 받았다면, 이미지를 public 디렉토리에 넣어줍니다.

Next.js에선 public 디렉토리에 들어있는 이미지를 바로 불러올 수 있습니다.

 

 

app/login/page.tsx

"use client";
import Image from "next/image";
import styles from "./page.module.css";

function kakaoLogin() {
  window.Kakao.Auth.authorize({
    redirectUri: "http://localhost:8080/kakao",
  });
}

export default function Home() {
  return (
    <main className={styles.container}>
      <div className={styles.introduction}>
        <h5>안녕하세요! 링꾹입니다.</h5>
        <p>링꾹을 이용하시려면 로그인이 필요합니다.</p>
      </div>
      <button onClick={kakaoLogin}>
        <Image
          src="/kakao_login.png"
          alt="Login with Kakao"
          width={300}
          height={45}
          priority
        />
      </button>
    </main>
  );
}

 

 

클릭 함수에는 Kakao.Auth.authorize() 메서드를 넣어줍니다.

속성의 redirectUri에는 리다이렉트로 인가 코드를 발급받을 주소를 넣습니다.

 

그 뒤, app 디렉토리 하위에 해당 리다이렉트를 받아줄 주소로 디렉토리를 만들어주고,

해당 디렉토리의 page.tsx에서 코드를 받아 사용할 수 있도록 해줍니다.

 

 

 

 

"use client";

import { useEffect } from "react";

export default function Kakao() {
  const getResponse = async (code: string) => {
    try {
      const params = {
        grant_type: "authorization_code",
        client_id: process.env.NEXT_PUBLIC_KAKAO_JS_KEY || "",
        REDIRECT_URI: "http://localhost:8080/kakao",
        code: code,
      };

      const queryString = new URLSearchParams(params).toString();

      const response = await fetch(
        `https://kauth.kakao.com/oauth/token?${queryString}`,
        { method: "POST" }
      );
      const { access_token } = await response.json();

      return access_token;
    } catch (e) {
      console.log(e);
    }
  };

  useEffect(() => {
    const code = new URL(window.location.href).searchParams.get("code");

    if (!code) return;

    getResponse(code);
  }, []);

  return <p>redirect...</p>;
}

 

 

실제 서비스에서는 주소 부분에 http://localhost 대신 서비스가 사용하는 도메인을 넣어주시면 되겠습니다.

개발 모드와 프로덕션 모드를 분리한다면 환경변수를 통해 관리해주는것도 좋은 방법입니다.

 

 

 

 

 

깔끔하게 나오고 있는 모습이네요.

그러나 이대로 클릭해보면 허용되지 않은 주소로 리다이렉트 된다는 오류가 발생하게 됩니다.

 

카카오 API는 보안상의 이유로 지정된 주소가 아니면 리다이렉트 요청을 받아들이지 않습니다.

일종의 화이트리스트를 이용하는 것과 같습니다.

 

 

 

 

[카카오 로그인] 메뉴의 [Redirect URI] 탭에서 리다이렉트를 받을 주소를 등록해줍니다.

최대 10개까지 가능하며, 추가로 필요한 경우 별도로 요청해야합니다.

 

 

 

 

이제 다시 시도해보면, 정상적으로 접근이 가능해졌습니다.

 

 

데이터도 잘 받아오고 있습니다! (모자이크 부분)

 

// response from redirect
{
  access_token: "1234567890abcdefghijklmn"
  expires_in: 7199
  refresh_token: "1234567890abcdefghijklmn"
  refresh_token_expires_in: 5183999
  token_type: "bearer"
}

 

응답으로 jwt 인증에 사용될 access_tokenrefresh_token,

그리고 각각의 토큰 만료 시간과 토큰 타입(bearer)이 들어오는걸 확인할 수 있네요.

 

 

 

마치며

오늘은 카카오 API를 이용하기 위해 프로젝트에 환경 설정을 하고,

카카오 서버와 통신까지 진행해보았습니다.

 

다음 포스팅에서는 받아온 데이터를 토대로 Firebase와 연동하여 저장하는 과정을 알아보겠습니다.

읽어주셔서 감사합니다.

 

 

참고문서

 

반응형

댓글