[날씨어때] 소셜로그인 이슈 해결

piper ·2023년 12월 14일
0

Project

목록 보기
3/15

목표:
구글을 통한 소셜 로그인 방법은 간단하지만 내 코드에 어떻게 녹여낼지 화면에 표현될 흐름 등을 생각해서 다시 만들어보아야 했다.

과정:

초기에 만든 코드:
1. firebase 초기설정, 팝업창 로그인 함수

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth";

// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "AIzaSyA_6Jaj9NVcAaxueyoCEvYGnWUxsoPf2tI",
  authDomain: "easylogin-98763.firebaseapp.com",
  projectId: "easylogin-98763",
  storageBucket: "easylogin-98763.appspot.com",
  messagingSenderId: "783928541301",
  appId: "1:783928541301:web:0d0cb9645b1fc3965a783c",
  measurementId: "G-RS5ES26W0B"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);

const provider = new GoogleAuthProvider();
const auth = getAuth();

//팝업창 로그인 함수 

const signInWithGoogle = () =>{
  return signInWithPopup(auth, provider)
  .then((result) => {
    // This gives you a Google Access Token. You can use it to access the Google API.
    const credential = GoogleAuthProvider.credentialFromResult(result);
    const token = credential.accessToken;
    // The signed-in user info.
    const user = result.user;
    console.log(result);
    
**이 부분에 토큰을 로컬 스토리지에 저장하고
로그인에 성공하였다는 창을 띄워준다. **

    localStorage.setItem("access_token", token)
    window.alert("회원가입에 성공하였습니다.");
    
    // IdP data available using getAdditionalUserInfo(result)
    // ...
  }).catch((error) => {
    // Handle Errors here.
    const errorCode = error.code;
    const errorMessage = error.message;
    // The email of the user's account used.
    const email = error.customData.email;
    // The AuthCredential type that was used.
    const credential = GoogleAuthProvider.credentialFromError(error);
    // ...
    console.log(error);
    window.alert("소셜로그인에 실패. 일반로그인을 해주세요")
  });
}; 

export { signInWithGoogle}
  1. 팝업창 로그인 함수 호출()
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import styled from "styled-components";
import login from "../../assets/img/login/login.png";
import devicon_google from "../../assets/img/login/devicon_google.png";
import kakao from "../../assets/img/login/kakao.png";
import { useDispatch } from "react-redux";
import { authActionCreator } from "../../redux/thunks/authThunk";
import { signInWithGoogle } from "../../api/socialAuthApi";

const Login = () => {
  const [userId, setUserId] = useState("");
  const [password, setPassword] = useState("");
  const navigate = useNavigate();
  const dispatch = useDispatch();

  const handleInputChange = (e) => {
    if (e.target.name === "email") {
      setUserId(e.target.value);
    } else if (e.target.name === "password") {
      setPassword(e.target.value);
    }
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    dispatch(authActionCreator(userId, password));
    navigate("/")
  };

    
  **
  const googleLogin = () =>{
    console.log('구글 버튼이 눌렸다.')
    signInWithGoogle();
      console.log('구글 로그인 팝업창 실행');
      navigate('/');
   **
   이 부분이 문제가 되었다.
   따라서 다음과 같이 실행해보았다.
   
**
const accessToken = localStorage.getItem
("access_token", token);

if(accessToken){
navigate("/")
};
**

이 역시 1)버튼이 눌리고 2)signInWithGoogle();
가 실행됨에 따라 모두 동시에 !!!!!! 실행되었다. 
};

  return (
    <Container>
      <div className="cover-img">
        <img src={login} alt="login" height="100%" width="720px" />
      </div>

      <div className="loginPage">
        <div className="loginPage-content">
          <h1>로그인</h1>
          <p>오늘도 좋은 날이에요</p>
          <div className="form-container">
            <div className="textfield-container">
              <input
                type="text"
                value={userId}
                name="email"
                id=""
                placeholder="이메일"
                onChange={handleInputChange}
              />
              <input
                type="password"
                value={password}
                name="password"
                placeholder="비밀번호"
                onChange={handleInputChange}
              />
            </div>
            <div className="button-container">
              <div className="checkbox">
                <input type="checkbox" id="checkbox" />
                로그인 정보 기억하기
              </div>
              <div className="button">
                <button onClick={handleSubmit}>로그인</button>
              </div>
            </div>
          </div>
          <div className="password-container">
            <p>비밀번호를 잊으셨나요?</p>
          </div>
          <div className="line">
            <hr className="line" />
            <p>Or</p>
            <hr className="line" />
          </div>
          <div className="social-login">
            <img src={devicon_google} alt="google" onClick={googleLogin} />
            <img src={kakao} alt="kakao" />
          </div>
          <div className="signup-container">
            <h3>
              아이디가 없으신가요?{" "}
              <h6>
                <Link to="/signup">회원가입하기</Link>
              </h6>
            </h3>
          </div>
        </div>
      </div>
    </Container>
  );
};

export default Login;

이슈:
구글 함수가 실행되기도 전에 화면이 초기메인으로
돌아가버린다. 팝업창으로 구글 로그인이 뜨고 메인화면은 로그인이 완료되기 전에 naviagate('/')가 실행되어버렸다. 이는 버튼이 눌리면서 모든 함수가 동시에 호출되기 때문이었다.

해결방법:
첫번째 방법) 버튼이 눌리면서 동시에가 아닌 순서를 보장받으면 실행되게 하는 비동기코드를 만들 수 있다.
두번째 방법) 구글에서 코드를 가져오면 자바스크립트 함수를 선언하게 된다. 함수 호출 부분이 아닌 구글이 제공한 함수를 선언하는 부분을 리액트형 컴포넌트로 바꾸어 마지막에 navigate('/')를 사용한다.

첫번째 방법으로 수정되어 완성 된 부분:
두번째 방법으로 함수 선언에 마지막에 navigate('/')를 써줄 시에 다른 컴포넌트에서 재사용하지 못할 가능성을 염두해 호출 부분의 코드를 바꾸기로 하였다.

 const googleLogin = async() =>{
    console.log('구글 버튼이 눌렸다.')

    try{
      await signInWithGoogle();
      console.log('구글 로그인 팝업창실행')
      navigate('/')
    }catch(e){
      console.log(e)
    }

promise와 .then().catch()를 사용한 부분

  const googleLogin = () =>{
    signInWithGoogle()
    .then((result)=>{
      console.log('콜백함수가 실행되었다.', result); 
      navigate('/'); 
    })
    .catch((e)=>console.e('로그인실패',e)); 
  
    console.log('버튼이 눌렸당!!')

  }
profile
연습일지

0개의 댓글