본문 바로가기
내일배움캠프 TIL

2023-12-07 본캠프 46일차 / 65일차 TIL

by KMS_99 2023. 12. 14.

2023-12-07 본캠프 46일차 / 65일차 TIL

 

주요 진행사항

- 아웃소싱 프로젝트

 

아웃소싱 프로젝트 - 로그인 구현

로그인 기능을 구현하기 위해서 이전에도 사용해본 firebase authentication을 사용하였다.

 

1. 프로젝트 세팅

우선 Firebase의 Authentication 사용설정을 하고 로그인 제공업체를 등록한다.

 

로그인 - Google 계정

이메일 또는 휴대전화

accounts.google.com

이 프로젝트에서는 일반 로그인과 구글 / 깃허브 소셜로그인을 사용한다.

 

2. 로그인 관련 메서드 파일 생성

로그인과 관련된 메서드를 미리 선언한 파일을 만들었다.

 

특히 소셜로그인은 제공업체만 다를 뿐 로직은 동일하기 때문에 switch 문을 통해 하나의 메서드로 정리하였다.

이렇게 정리한 메서드는 하나의 커스텀 훅으로 정리하여 사용하였다.

 

3. 커스텀 훅 생성

import { auth } from '../firebase';
import { useMutation } from 'react-query';
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { logout, loginEmail, signUpEmail, socialLogin, setUserData, profileUpdate } from '../axios/firebaseApi';
import { setSuccessLogin, setSuccessLogout } from '../redux/modules/authSlice';
import useAlert from './useAlert';

export const useAuth = () => {
  const { alert } = useAlert();

  const dispatch = useDispatch();

  const navigate = useNavigate();

  const logoutMutate = useMutation(logout, {
    onSuccess: () => {
      alert({ title: '로그아웃', message: '성공적으로 로그아웃 되었습니다.' });
      dispatch(setSuccessLogout());
      navigate('/');
    }
  });

  const loginMutate = useMutation(loginEmail, {
    onSuccess: () => {
      dispatch(setSuccessLogin());
      alert({ title: '로그인', message: '성공적으로 로그인하였습니다.' });
      navigate('/');
    },
    onError: (error) => {
      switch (error.code) {
        case 'auth/invalid-credential':
          alert({ title: '로그인에러', message: '잘못된 로그인 정보입니다.' });
          break;
        default:
          alert({ title: '로그인에러', message: '로그인에러 입니다.' });
          break;
      }
    }
  });

  const signUpMutate = useMutation(signUpEmail, {
    onSuccess: async ({ response, nickname }) => {
      await setUserData(response.user.uid);
      await profileUpdate(nickname);
      alert({ title: '회원가입', message: '성공적으로 회원가입하였습니다.' });
      dispatch(setSuccessLogin());
      navigate('/');
    },
    onError: (error) => {
      switch (error.code) {
        case 'auth/email-already-in-use':
          alert({ title: '회원가입에러', message: '이미 사용중인 이메일입니다.' });
          break;
        default:
          alert({ title: '회원가입에러', message: '회원가입에러 입니다.' });
          break;
      }
    }
  });

  const socialLoginMutate = useMutation(socialLogin, {
    onSuccess: async (data) => {
      await setUserData(data.user.uid);
      alert({ title: '로그인', message: '성공적으로 로그인하였습니다.' });
      dispatch(setSuccessLogin());
      navigate('/');
    },
    onError: (error) => {
      alert({ title: '소셜로그인에러', message: error.code });
    }
  });

  // 현재 user 정보
  const currentUser = auth.currentUser;

  // 회원가입
  const signUpHandler = (signUpInfo) => {
    signUpMutate.mutate(signUpInfo);
  };

  // 소셜로그인
  const socialLoginHandler = (mode) => {
    socialLoginMutate.mutate(mode);
  };

  // 일반 로그인
  const loginHandler = (loginInfo) => {
    loginMutate.mutate(loginInfo);
  };

  // 로그아웃
  const logoutHandler = () => {
    logoutMutate.mutate();
  };

  // 회원정보 체크
  const checkAuth = () => {
    const currentDate = new Date().getTime();
    auth.onAuthStateChanged((user) => {
      if (!user) {
        dispatch(setSuccessLogout());
        return;
      }
      if (currentDate > user?.stsTokenManager.expirationTime) {
        dispatch(setSuccessLogout());
      } else {
        dispatch(setSuccessLogin());
      }
    });
  };

  return { logoutHandler, checkAuth, loginHandler, signUpHandler, socialLoginHandler, currentUser };
};

 

react-query를 사용하여 더욱 편리한 비동기 처리를 할 수 있었다.