Programming/React

카카오 소셜 로그인

gitit 2024. 9. 15. 15:19

프로젝트 중에 해당 서비스 회원가입은 카카오 소셜 로그인 + 추가 정보 받아오기 방식으로 진행하기로 했다. 

 

처음 해보는 방식이라 경험이 있던 백엔드 분께 방법을 물어보니,

 

1. 프론트 → 카카오한테 인가코드 받아오기 → 인가코드 전송해서 카카오한테 엑세스 토큰 받아오기

→ 백엔드한테 엑세스 토큰 전달하기 (프론트 복잡도 ↑)

2. 프론트 → 카카오한테 인가코드 받아오기 → 백엔드한테 인가코드 전달하기 (프론트 복잡도 ↓)

 

2가지 방법 중에 선택하라고 하셨는데, 한 번 할 거 프론트가 해야할 게 많은 걸 해보고 싶었기에 1번을 선택하였다.

 

우선 카카오 소셜 로그인은 kakao developers에서 애플리케이션을 추가해야한다.

 

https://developers.kakao.com/

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

 

해당 애플리케이션을 클릭하고 스크롤을 조금만 내리면 [설정] 이 보인다.

아래 3가지 모두를 필수로 설정해야 한다.

(동의항목을 안눌러서 애를 먹었던..)

- 카카오 로그인

- 동의 항목

- Redirect URI

 

- [앱 키] 에서 REST API 키 확인하기

 

아래는 해당 프론트 코드이다.

에러 코드는 프로젝트마다 다를 것이기에 그저 참고용.

 

- 카카오 Redirect URI 이동

import React from "react";
import * as s from "../styles/MainStyle";
const KAKAO_CLIENT_ID = "{ REST API 앱키 작성 }";
const REDIRECT_URI = "http://localhost:5173/auth/callback";

const Kakao: React.FC = () => {
  const handleLogin = () => {
    const authUrl = `https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${KAKAO_CLIENT_ID}&redirect_uri=${REDIRECT_URI}`;
    window.location.href = authUrl;
  };
  return (
      <s.LoginButton onClick={handleLogin}>
        <p>카카오 로그인</p>
      </s.LoginButton>
  );
};

export default Kakao;

 

- 카카오한테 인가 코드 → 액세스 토큰 받아와서 백엔드한테 전달하기

import React, { useEffect, useRef } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import axios from "axios";

const KAKAO_CLIENT_ID = "{ REST API 앱키 작성 }";
const KAKAO_REDIRECT_URI = "http://localhost:5173/auth/callback";

const AuthCallback: React.FC = () => {
  const navigate = useNavigate();
  const { search } = useLocation();
  const hasFetched = useRef(false); // 렌더링 체크용 Ref

  useEffect(() => {
    if (hasFetched.current) return; // 이미 호출되었으면 아무 작업도 하지 않음
    hasFetched.current = true; // 첫 호출 시 True로 설정

    const query = new URLSearchParams(search);
    const code = query.get("code");
    console.log("Authorization Code:", code);

    if (code) {
      const tokenUrl = `https://kauth.kakao.com/oauth/token`;

      console.log("Sending Request with Params:");
      console.log("client_id:", KAKAO_CLIENT_ID);
      console.log("redirect_uri:", KAKAO_REDIRECT_URI);
      console.log("code:", code);

      axios
        .post(
          tokenUrl,
          new URLSearchParams({
            grant_type: "authorization_code",
            client_id: KAKAO_CLIENT_ID,
            redirect_uri: KAKAO_REDIRECT_URI,
            code: code,
          }),
          {
            headers: {
              "Content-Type": "application/x-www-form-urlencoded",
            },
          }
        )
        .then((response) => {
          const { access_token } = response.data;
          console.log("Kakao token:", access_token);

          // 백엔드로 토큰 전송
          axios
            .post(
              { accessToken: access_token },
              {
                headers: {
                  "Content-Type": "application/json",
                },
              }
            )
            .then((response) => {
              console.log("User data:", response.data);
              if (response.status === 200) {
                sessionStorage.setItem("userName", response.data.name);
                sessionStorage.setItem(
                  "accessToken",
                  response.data.accessToken
                );
                sessionStorage.setItem(
                  "refreshToken",
                  response.data.refreshToken
                );
                navigate("/home");
              }
            })
            .catch((error) => {
              if (error.response.status === 401) {
                navigate("/login");
                sessionStorage.setItem("kakaoToken", access_token);
                sessionStorage.setItem(
                  "registerToken",
                  error.response.data.registerToken
                );
              }
              console.error(
                "백엔드에 accessToken 전달 과정에 에러가 생겼습니다:",
                error
              );
            });
        })
        .catch((error) => {
          if (error.response) {
            console.error("카카오 에러 발생:", error.response.data);
            console.error("상태 코드:", error.response.status);
          } else if (error.request) {
            console.error("카카오로부터 응답이 없습니다:", error.request);
          } else {
            console.error("카카오API 요청 도중에 에러 발생:", error.message);
          }
        });
    }
  }, [search]);

  return <div>Loading...</div>;
};

export default AuthCallback;

 

 

로컬에서는 로그인 과정이 잘됐는데, S3로 배포하니까 카카오 리디렉션 경로가 없다고 뜬다.

알아보니 S3는 정적 웹 호스팅이라 카카오 로그인과 같이 따로 리디렉션을 설정해야 하는 것은 S3 설정만으로는 불가능하다는 것이다. 곧 EC2로 배포하고 해당 글 가져와야겠다.