React + Firebase로 카카오 로그인 구현하기

ZenTechie·2023년 6월 2일
0

Troubleshooting

목록 보기
8/9
post-thumbnail

시작

먼저, 이전에 React + Firebase로 구글 로그인을 구현했었다.
아무래도 우리나라 대다수 국민이 카카오톡을 많이 사용하는 만큼, 카카오 로그인도 있으면 매우 편리할 것이라고 생각하기에 카카오 로그인 기능도 구현해보려고 한다.


Kakao

Javascript SDK 설정

먼저 Kakao Developers에 방문하여 Full SDK를 복사합니다.

그 다음으로 복사한 SDK 코드를 index.html의 <title> 아래에 추가합니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <-- 여기 -->
    <script src="https://t1.kakaocdn.net/kakao_js_sdk/2.2.0/kakao.min.js" integrity="sha384-x+WG2i7pOR+oWb6O5GV5f1KN2Ko6N7PTGPS7UlasYWNxZMKQA63Cj/B2lbUmUfuC" crossorigin="anonymous"></script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

플랫폼 등록

아래의 플랫폼 메뉴에서 플랫폼 설정하기 버튼을 눌러서 사용하고자 하는 플랫폼을 등록합니다. 저는 웹앱이므로 Web을 등록했습니다.

고유 JavaScript 키 설정

상단 메뉴의 내 애플리케이션을 눌러봅시다.

기존에 생성한 프로젝트가 있다면 해당 프로젝트를 클릭하고 JavaScript 키를 복사해줍니다.
프로젝트가 없다면 새로 생성해서 동일한 과정을 수행합시다.

복사한 키를 가지고 임의의 js파일에 다음과 같은 코드를 추가합니다.
저는 kakaologin.js라는 파일을 생성하고 여기에 추가했습니다.

const kakaologin = () => {
    if (!window.Kakao.isInitialized()) {
      window.Kakao.init('cfc1aaa067d4f612945273d5dac8a9c8');
    }
}

export default kakaologin;

예시에서는 JavaScript 키를 사용했는데, 앞으로의 구현은 REST API 키를 사용했다.

카카오 로그인 설정

[내 애플리케이션] > [제품설정] > [카카오 로그인]

내 애플리케이션에서 프로젝트에 들어갑니다.
왼쪽 메뉴에 카카오 로그인 항목을 클릭합니다.

처음에 활성화 설정의 상태는 OFF입니다. ON으로 변경해줍시다.

그 다음으로 Redirect URI설정해줘야 합니다.

다음으로는 동의항목을 설정해줍니다.
[내 애플리케이션] > [제품설정] > [카카오 로그인] > [동의항목]

아래의 정보들을 자신의 원하는대로 필요에 맞게 설정해주면 됩니다.
저는 테스트용으로 다음과 같이 설정했습니다.

문제 발생...

06.01

백엔드 코드를 작성하기 위해서 Cloud Functions을 사용했는데,

firebase deploy --only functions 

위 명령어 사용시 Blaze 요금제로 바꿔야 수행가능하다고 한다...
다른 사람들은 문제없이 하던데, 최신 글이 아니라서 그새 정책이 바뀌었나보다.

해당 오류
Error: Your project logintest-7c52f must be on the Blaze (pay-as-you-go) plan to complete this command. Required API cloudbuild.googleapis.com can't be enabled until the upgrade is complete. To upgrade, visit the following URL:

아무래도 다른 방법을 찾아봐야겠다.

06.04

React로 구현한 코드는 거의 없다시피해서 계속해서 관련 글을 찾다가 Vue로 구현한 블로그를 찾았다. 똑같이 Cloud Functions을 사용하는데, 이전에 발생했던 요금제 변경을 우회할 수 있는 방법이 있었다.

자세한 에러 발생 원인을 찾아보니 firebase에서 Node.js 10 이상 부터는 Blaze 요금제를 사용해야 한다는 것이었다. Node.js의 버전을 내리면 임시로 해결이 가능했다.

해결법은 여기서 찾아볼 수 있다.

그런데 배포 중 계속해서 에러가 발생해서 일단은 너무 삽질을 많이 한 관계로 포기했다. 😭(에러를 캡처해뒀어야 하는데 기억이 안난다..)

문제 해결!

솔직히 다른 환경(Flutter, Swift, Kotlin 등)에서 구현한 코드는 많은데 React는 자료가 너무 없어서 아무리 해도 안될 것 같아 구현 자체를 포기했었다.

근데 또 이놈의 성격이 끝내지를 못하면 머릿속에 계속 생각이 나서, 알고리즘 문제를 풀 때도 "아!!! 어떻게 해결될 것 같은데, 조금만 더 해볼까? 🧐" 하는 생각이 떠나질 않았다.

해결 방법은 2가지 이다.

  1. Cloud Functions 대신 Node.js 서버(express 사용)를 구현하고, Cloud Functions에 작성했던 코드들을 다 옮기는 것이다.
  2. OpenID Connect 사용하기

이 중 나는 일단은 서버 구축이라면 거부감이 들어, OpenID Connect를 사용해서 구현했다. 추후 필요에 따라 Node.js 서버를 사용해서 구현을 해보겠다.

이어서..

일단 들어가기 전, 위에서 JavaScript 키를 사용했는데 이제부터 구현할 코드는 REST API 키를 사용했다.

본 포스팅은 모든 코드에 대해 설명하지 않습니다. 전체 코드가 필요하다면 이곳에서 확인해주세요.
+) 코드가 좀 지저분하고 세세한 디테일까지는 신경쓰지 못했습니다. 작동 여부만 참고하는 것을 추천드립니다.


✅ 기능에 대한 간단한 설명

일단, 거창한 CSS 같은 건 필요없이 기능 동작 여부만 확인하면 되므로 아주 간단하게 작성했다.

첫 페이지(localhost:3000)에서 Kakao 로그인이라는 버튼을 하나 만들고, 해당 버튼을 클릭하면 간편 로그인을 할 수 있다.


프로젝트 구조 살펴보기

├── README.md
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src
    ├── App.js
    ├── Kakao.js
    ├── KakaoLogin.js
    ├── config.js
    └── index.js

OpenID Connect 활성화 설정

[공지] 카카오 로그인 OpenID Connect 지원을 살펴보면 카카오 로그인이 이제 OpenID Connect를 지원한다고 한다.

먼저, 카카오 Developer에 들어가서 왼쪽의 카카오 로그인 항목을 선택하자.

항목에 OpenID Connect 활성화 설정이 있다. 처음 상태는 OFF이다.
이를 ON으로 바꿔주자.


firebaseConfig 설정

React + Firebase로 구글 로그인 구현하기에서 했던 작업과 똑같다.
만약, 똑같은 프로젝트를 사용하고 있다면 그대로 사용하면 된다.

// ✅ /src/config.js

import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  apiKey: "[본인 프로젝트의 값]",
  authDomain: "[본인 프로젝트의 값]",
  projectId: "[본인 프로젝트의 값]",
  storageBucket: "[본인 프로젝트의 값]",
  messagingSenderId: "[본인 프로젝트의 값]",
  appId: "[본인 프로젝트의 값]"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);

export { app, auth };

콜백 페이지 설정하기

추후에 필요한 콜백 페이지부터 설정해야 한다.
위의 프로젝트 구조에서 KakaoLogin.js는 로그인 버튼을 나타내는 컴포넌트이고, 인가 코드 받기를 요청한다.

Kakao.jsRedirect URI를 의미하는 콜백 페이지이고, KakaoLogin에서 받은 인가 코드를 바탕으로 ID 토큰Access Token을 요청하는 함수들이 모여있다.

위 정보를 바탕으로 react-router-dom을 사용해서 index.jsRoute를 설정해야 한다.

// ✅ /src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Route, Routes, BrowserRouter as Router } from "react-router-dom";
import Kakao from "./Kakao";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <Router>
    <Routes>
      <Route path="/" element={<App />} />
      <Route path="/callback/kakaotalk" element={<Kakao />} />
    </Routes>
  </Router>
);

/callback/kakaotalk은 내가 설정한 Redirect URI이다.
본인이 설정한 값에 맞게 변경해줘야 한다.


카카오 간편 로그인 요청하기

카카오 로그인 함수Kakao.Auth.authorize()간편 로그인을 요청해야 한다.

Kakao.Auth.authorize()를 통해 카카오계정 ID 및 비밀번호 입력 없이 카카오톡을 통해 사용자를 인증하고 인가 코드를 발급받을 수 있다.

코드는 아래와 같다.

// ✅ /src/KakaoLogin.js
const restkey = "본인 REST API 키";

if (!window.Kakao.isInitialized()) {
    window.Kakao.init(restkey);
    console.log(window.Kakao.isInitialized());
}

const handleKakaoSign = () => {
  	const redirectUri = `${window.location.origin}/callback/kakaotalk`;

    const scope = [
      "profile_nickname",
      "profile_image",
      "account_email",
      "gender",
      "age_range",
      "birthday",
      "friends",
      "openid",
    ].join(",");

    window.Kakao.Auth.authorize({
      redirectUri,
      scope,
    });
};

공식문서에 따르면, redirectUri인가 코드 발급을 전달받을 URI를 의미한다. 이는 우리가 처음에 등록Redirect URI의미한다.

window.location.originlocalhost:3000을 의미한다.

위에서 설정한 동의 항목IDscope전달해야 한다.
동의항목의 ID여기서 살펴보면 된다.

함수의 자세한 설명은 Kakao Developer에서 확인하자.

이제 버튼을 클릭하게 되면 카카오 간편 로그인을 수행하게 된다. 모든 과정이 끝나면 설정한 Redirect URIquery string으로 인가 코드(code)가 주어진다.

그 다음으로 URLSearchParams사용하여 code값을 가져온다.

// ✅ /src/Kakao.js
const params = new URL(document.location.toString()).searchParams;

const code = params.get("code");

이제 가져온 code를 통해서 ID 토큰을 가져오면 된다.


ID 토큰 가져오기

토큰 가져오기에 대한 자세한 설명은 카카오 Developer에서 확인하자.

코드는 아래와 같다.

// ✅ /src/Kakao.js

const [idToken, setIdToken] = useState(null);
const [accessToken, setAccessToken] = useState(null);

const getKakaoToken = async (code) => {
    await fetch("https://kauth.kakao.com/oauth/token", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: `grant_type=authorization_code&client_id=${restkey}&redirect_uri=${window.location.origin}/callback/kakaotalk&code=${code}`,
    })
      .then((res) => res.json())
      .then((data) => {
        // OIDC 사용하는 경우 id_token으로 접근해야 한다.
        if (data.id_token) {
          setIdToken(data.id_token);
        } else {
          navigate("/");
        }
        if (data.access_token) {
            setAccessToken(data.access_token);
            window.Kakao.Auth.setAccessToken(data.access_token);
        }
      });
};

getKakaoToken은 인자인 code에 위에서 얻은 인가 코드를 넘겨서 호출하면 된다.
우리는 OpenID Connect를 통한 로그인 구현이므로 ID 토큰이 필요하다.

위에서 OpenID Connect 설정을 했으므로, 토큰을 요청했을 때 응답 데이터안에 ID 토큰이 함께 발급된다. ID 토큰은 응답 데이터 내부에서 id_token으로 표시되며,
코드에서 data.id_token을 의미한다.

Firebase와 연동할 때 ID 토큰을 사용한다는 점을 꼭 기억하자.

access_token은 사용자의 프로필 이미지, 나이, 생일 등 여러 정보를 추후에 사용할 수도 있을 것 같아 일단 받아와서 설정은 해뒀다.


Firebase OpenID Connect 설정하기

이제 Firebase에서 로그인 제공업체를 설정해야 한다.
이전에 했던 그대로 [내 프로젝트] → [Authentication] → [Sign-in method]로 이동하자.

새 제공업체 추가를 누르고 OpenID Connect 항목을 선택하자.

다음과 같은 설정이 표시되는데 아래와 같이 설정하자.

  • 이름 : kakao
  • 클라이언트 ID : 카카오 내 애플리케이션의 REST API 키
  • 발급자(URL) : https://kauth.kakao.com/
  • 클라이언트 보안 비밀번호 : 발급 받은 Client Secret 코드
    ([카카오 로그인] → [보안] → [Client Secret 코드 발급])

모두 작성했다면 추가로 작성해야 하는 코드가 있다.
웹 앱에서 OpenID Connect를 사용하여 인증을 살펴보자.

추가되어야 하는 코드는 다음과 같다.

// ✅ /src/Kakao.js

const provider = new OAuthProvider("oidc.kakao");
const credential = provider.credential({
  idToken: idToken,
});

signInWithCredential(auth, credential)
  .then((result) => {
  const credential = OAuthProvider.credentialFromResult(result);
  const acToken = credential.accessToken;
  const idToken = credential.idToken;
}).catch((error) => {
  // Handle error.
  console.log(error);
});

위 코드는 콜백 페이지에 해당하는 js파일에 작성했다. 나의 경우 Kakao.js이다.


결과는?

이렇게 모두 코드를 작성했다. 결과를 살펴보자.

짜잔, 카카오 로그인도 유저로 등록이 됐다!


근데 이렇게 만드는게 맞나 싶나? 하는 생각이 든다. 뭔가 하나씩 빠져있는 느낌?

Client Secret에 대한 처리도 하지 못했고, 그저 작동이 되는지 안되는지만 구현을 했기에... 이미 존재하는 유저가 로그인 했을 때 처리해주는 로직도 없다.

일단 작동은 확인했으니, 추가적으로 구현이 필요한 부분은 나중에 구현해보도록 하겠다.

profile
데브코스 진행 중.. ~ 2024.03

0개의 댓글