[React] Firebase를 통해 회원가입, 로그인, 로그아웃 기능 구현

·2023년 10월 16일
1

React

목록 보기
6/7
post-thumbnail

🔥Firebase

Firebase에 대해 간단한 개념을 우선 정리해보자.

Firebase : 실시간 DB, 인증, 스토리지, 분석 등 다양한 기능을 제공하는 모바일/웹앱 개발 플랫폼
1) Authentication: 간편한 다중 플랫폼 로그인
- 이메일 인증, 소셜미디어 계정 인증, 전화번호 인증방식 제공
- 보안강화, 사용자 인증 과정 안전하게 처리
2) FireStore: NoSQL DB
- Firebase에서 제공하는 NoSQL형식의 클라우드 DB
- 실시간 데이터 동기화 지원 (ex. 실시간 채팅)
3) Storage: 사진 및 동영상 저장
- 사용자 파일 저장 및 공유, 강력한 보안
4) Hosting: 웹앱 호스팅
- 정적 및 동적 콘텐츠 모두 호스팅 가능, 웹앱 간단 배포

장점

  • 백엔드 서버 없이 개발 가능
  • 실시간 데이터베이스
  • Google 플랫폼 통합

단점

  • 쿼리 제한
  • 비용
  • migration 어려움

코드 살펴보기

👀Firebase 연동

  • firebaseConfig
    - Firebase 연동에 필요한 값들은 모두 .env에 따로 저장해두었다.
    - Firebase앱의 구성 정보를 포함하는 JS 객체
    - Firebase를 사용하여 웹 애플리케이션을 초기화하고 firebase 앱 인스턴스를 설정하는 typescript 코드
    • Firebase 프로젝트 구성정보 포함
    • 환경변수를 통해 동적으로 코드
import { initializeApp, FirebaseApp, getApp } from "firebase/app";
import "firebase/auth";

export let app: FirebaseApp;

const firebaseConfig = {
  apiKey: process.env.REACT_APP_API_KEY,
  authDomain: process.env.REACT_APP_AUTH_DOMAIN,
  projectId: process.env.REACT_APP_PROJECT_ID,
  storageBucket: process.env.REACT_APP_STORE_BUCKET,
  messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_ID,
};

try {
  app = getApp("app");
} catch (e) {
  app = initializeApp(firebaseConfig, "app");
}

const firebase = initializeApp(firebaseConfig);

export default firebase;

  • Firebase 앱 인스턴스를 초기화 시도
    - app이라는 이름의 Firebase 앱이 존재하지 않는 경우, initializeApp을 통해 Firebase 앱 초기화
try {
  app = getApp("app");
} catch (e) {
  app = initializeApp(firebaseConfig, "app");
}

👀login 상태 확인

  • 사용자가 login인 상태: 로그인 상태임을 콘솔에 띄움
  • 사용자가 logout인 상태: 로그아웃 상태임을 콘솔에 띄움
import {getAuth, onAuthStateChanged} from "firebase/auth"

//mount시 useEffect를 통해 초기 사용자 로그인 상태 확인
useEffect(()=>{
  onAuthStateChanged(auth, (user)=>{
    if(user) {
      console.log("로그인 상태")
    }else {
      console.log("로그아웃 상태")
    }
    setInit(true)
  })
}, [auth]);
  • onAuthStateChanged: Firebase Authentication 서비스에서 제공하는 메서드, 인증 상태가 변경될때마다 호출되는 리스너 설정
    - 사용자 객체를 인자로 받는 콜백 함수 등록
    • 사용자의 로그인 상태 확인 후 적절한 작업 수행
    • 로그인 상태일 때는 사용자의 정보를, 아니라면 null return

👀signUp 구현

  • email: 정규식을 이용하여 입력값 형식 제한
  • password: 8자리 이상의 입력값으로 제한
  • passwordConfirm: password값과 일치해야함
  //회원가입 입력값 관리
  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const {
      target: { name, value },
    } = e;

    if (name === "email") {
      setEmail(value);
      console.log(value);
      //email 정규식
      const emailRegex = /^[a-zA-Z0-9-_]+@[a-zA-Z.]+$/;

      if (!value?.match(emailRegex)) {
        setError(
          "이메일 형식이 올바르지 않습니다. 영문 대소문자, 숫자와 특수기호(_),(-),(@)만 사용 가능합니다."
        );
      } else {
        setError("");
      }
    }
    if (name === "password") {
      setPassword(value);

      if (value?.length < 8) {
        setError("비밀번호는 8자리 이상으로 입력해주세요.");
      } else if (passwordConfirm?.length > 0 && value !== passwordConfirm) {
        setError("비밀번호와 비밀번호 확인 값이 다릅니다.");
      } else {
        setError("");
      }
    }
    // 비밀번호 확인 (passwordConfirm)도 위와 비슷한 형태
    
  //'회원가입하기' 버튼 클릭 시  
  const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    try {
      const auth = getAuth(app);
      await createUserWithEmailAndPassword(auth, email, password);
      toast.success("회원가입에 성공하였습니다.");
      navigate("/");
    } catch (error: any) {
      toast.error(error?.code);
      console.log(error);
    }
  };

✔️회원가입 input값 관리

  • 이벤트 객체 타입 지정 부분
e: React.ChangeEvent<HTMLInputElement>

  • 비구조화 할당
    - e로부터 taget속성 추출
    - input의 name과 input의 value(현재 입력값)
const {
	target: { name, value },
} = e;

비구조화 할당
: JS나 TypeScript와 같은 프로그래밍언어에서 변수를 객체나 배열에서 추출하여 사용하는 문법
-> 객체나 배열의 내부 속성이나 요소를 간편하게 변수에 할당. 할당하려는 변수의 이름과 일치하는 속성이나 요소를 추출하여 할당

const person = {name: "John", age: 30}
const {name, age} = person;
console.log(name) //John
console.log(age) //30
  • email input값
    - nameemail인 경우
    • 입력된 값으로 email값을 설정 setEmail
    • 만약 입력된 값이 emailRegex(이메일 정규식)에 벗어날 경우 error
if (name === "email") {
	setEmail(value);
	const emailRegex = /^[a-zA-Z0-9-_]+@[a-zA-Z.]+$/;

	if (!value?.match(emailRegex)) {
		setError(
			"이메일 형식이 올바르지 않습니다. 영문 대소문자, 숫자와 특수기호(_),(-),(@)만 사용 가능합니다."
		);
	} else {
		setError("");
	}
}

✔️'회원가입하기' 버튼 클릭 시 (onSubmit)

  • React에서 사용자가 form을 제출할 때 실행될 이벤트 핸들러
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {}
  • e.preventDefault()
    기본 제출 동작을 중단, form이 실제로 서버 제출되는 것을 중단하고 JS 함수가 대신 실행되도록 함
  • createUserWithEmailAndPassword
    입력된 email, password를 해당 메서드에 전달하여 회원가입에 성공할 경우 toast.success를 띄우고, useNavigate를 통해 홈화면으로 가도록 구현
await createUserWithEmailAndPassword(auth, email, password);
toast.success("회원가입에 성공하였습니다.");
navigate("/");

👀login 구현

  • login input값의 onChange는 회원가입과 매우 비슷한 형태로 구현됨
  • '로그인하기'버튼을 클릭했을 때 동작하는 onSubmit
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    try {
      const auth = getAuth(app);
      await signInWithEmailAndPassword(auth, email, password);
      toast.success("로그인에 성공하였습니다.");
    } catch (error: any) {
      toast.error(error?.code);
      console.log(error);
    }
  };
  • signWithEmailAndPassword
    입력한 email과 password값을 해당 메서드로 전달

👀logout 구현

  • logout 버튼 클릭 시
const onSignOut = async () => {
  try {
    const auth = getAuth(app);
    await signOut(auth);
    toast.success("로그아웃 되었습니다.");
  } catch (error: any) {
    console.log(error);
    toast.error(error?.code);
  }
};

0개의 댓글