본문 바로가기
✍️ 기록/Firebase

[Firebase Authentication] React - 회원가입, 로그인, 로그아웃, 구글 계정 로그인

by 김물사 2025. 6. 25.

📌 Firebase Authentication이란?

- Firebase에서 제공하는 사용자 인증 서비스

- 이메일/비밀번호, Google, Facebook, GitHub, Apple 등 다양한 로그인 제공

 

 

- 인증된 사용자에게 UID 제공 → 보안 기반 서비스 구현 가능

 

📍Authentication 시작하기

🔗 firebase console

 

✅ 빌드 > Authentication > 시작하

 

✅ 이메일/비밀번호로 로그인 방법을 추가!

이후에 추가 제공 업체에서 google 또는 github 등 추가로 로그인을 진행할 수 있도록 추가

✅ 사용 설정 완료 후 프로젝트 내 firebas.ts 수정

 

📍firebase.ts getAuth 추가

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

const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
};

// 앱 초기화
const firebaseApp = initializeApp(firebaseConfig);
// 데이터베이스
const firebaseDB = getFirestore(firebaseApp);
const firebaseAuth = getAuth(firebaseApp); // 👈 추가
export { firebaseApp, firebaseDB, firebaseAuth };

 

📍 테스트 - 회원가입 auth, email, password

createUserWithEmailAndPassword(auth, email, password);

import { firebaseAuth } from "../../firebase";
import { ChangeEvent, FormEvent, useState } from "react";
import { createUserWithEmailAndPassword } from "firebase/auth";

export const SignUp = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const onChange = (e: ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    if (name === 'email') {
      setEmail(value);
    } else if (name === 'password') {
      setPassword(value);
    }
  };

  const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    try {
      const result = await createUserWithEmailAndPassword(firebaseAuth, email, password);
      console.log("성공"+ result);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <div>
      <h2>회원가입</h2>
      <form onSubmit={onSubmit}>
        <input
          name="email"
          type="email"
          placeholder="email"
          value={email}
          onChange={onChange}
        />
        <input
          name="password"
          type="password"
          placeholder="password"
          value={password}
          onChange={onChange}
        />
        <button type="submit">
          회원가입
        </button>
      </form>
    </div>
  )
}

✅ 이메일 형식으로 만들고 비밀번호 2개 입력

FirebaseError : Password should be at least 6 characters (auth/weak-password). at async onSubmit

오류를 확인할 수 있는데 이 오류는 비밀번호가 6자 이상이 아니라서 나오는 오류!

auth/weak-password: 6자 이상의 비밀번호 필요

 

✅ 비밀번호 6자리 이상 입력 후 다시 시도

✅ Authentication에 입력한 이메일도 정상적으로 확인하였고 회원가입을 완료된 것을 확인할 수 있어요!

* 민감한 정보는 제외하고 추가로 DB에 특정 값을 사용하여 회원정보를 저장하여 유저 데이터 활용.

 

📍 로그인

signInWithEmailAndPassword(auth, email, password);

- 이메일과 비밀번호로 기존 사용자를 로그인시키는 메소드

- Promise를 반환하므로 async/await나 .then()으로 처리

- 성공하면 사용자 정보 포함된 객체를 반환

- 실패 시 에러 - 비밀번호, 계정이 없는 경우

 

import { firebaseAuth } from "../../firebase";
import { signInWithEmailAndPassword } from "firebase/auth";
import { ChangeEvent, FormEvent, useState } from "react";

export const LogIn = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  
  const onChange = (e: ChangeEvent<HTMLInputElement>) => {
    const {target: {name, value}} = e;
    if(name === "email") {
      setEmail(value)
    } else if (name === "password") {
      setPassword(value)
    }
  }
  const onSubmitLogin = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    try {
      const userLogin = await signInWithEmailAndPassword(firebaseAuth, email, password);
      console.log(userLogin)  
    } catch (error) {
      console.log(error)
    }
  }

  return( 
    <div>
      <h2>로그인</h2>
      <form onSubmit={onSubmitLogin}>
        <input 
            name="email"
            type="text"
            placeholder="email"
            value={email} 
            onChange={onChange} />
          <input 
            name="password"
            type="password"
            placeholder="password"
            value={password} 
            onChange={onChange} />
          <button type="submit">로그인</button>
      </form>
    </div>
  )
}

 

✅ 이메일과 비밀번호를 정상적으로 입력 시 로그인 성공!

로그인 정보를 확인할 수 있어요 (email, accessToken 등)

📍 로그아웃

signOut(auth)

- 현재 세션을 종료하고 사용자 인증 상태를 해제

- 로컬에 저장된 인증 토큰들을 제거

- Promise를 반환하지만 대부분 빠르게 완료

- 로그아웃 후 onAuthStateChanged에서 user가 null로 변경됨을 감지 가능

signOut(auth);

 

📍 로그인 상태 체크

✅ onAuthStateChanged(auth, (user) => {  . . . }

- 사용자의 인증 상태 변화를 실시간으로 감지하는 리스너

- 사용자가 로그인/로그아웃할 때마다 콜백 함수를 실행

- 사용자 객체(로그인 시) 또는 null(로그아웃 시)을 콜백에 전달

- 컴포넌트 마운트 시 설정하고, 언마운트 시 해제해야 함 (메모리 누수 방지)

- 페이지 새로고침 후에도 로그인 상태를 자동으로 복원

onAuthStateChanged(auth, (user) => {
  if (user) {
    console.log('로그인 상태', user);
  } else {
    console.log('로그아웃 상태');
  }
});

 

📍 로그인 상태 체크 / 로그아웃

import { useEffect, useState } from 'react';
import { onAuthStateChanged, signOut } from 'firebase/auth';
import { firebaseAuth } from "../../firebase";
import { LogIn } from './LogIn';

export const Tistory = () => {
  const [loginUser, setLoginUser] = useState<string | null>(null);

  useEffect(()=>{
    // 사용자의 로그인 상태 변경 감시
    const unAuth = onAuthStateChanged(firebaseAuth, (user) => {
      if (user) {
        console.log(user)
        console.log('로그인 상태')
        setLoginUser(user.email);
      } else {
        console.log('로그아웃 상태')
        setLoginUser(null);
      }
    })
    return () => unAuth();
  },[])

  // 로그아웃
  const handleSignOut = () => {
    signOut(firebaseAuth);
  }
  return (
    <div className="Tistory">
      {
        loginUser 
          ? <button onClick={handleSignOut}>{loginUser}님 로그아웃</button> 
          : <LogIn />
      }
    </div>
  );
};

✅ 회원가입한 email과 password를 다시 입력하고 로그인 진행!

 

✅ 로그인한 이메일도 확인 가능하며 로그아웃 버튼 시 로그아웃 정상적으로 확인 완료!

 

📍구글 계정으로 로그인하기 

📘 제공업체 구글 추가

✅ Authentication ➡️ 로그인 방법 ➡️ 새 제공업체 추가 

 

✅ Google 외 다른 업체도 진행할 수 있어요.

✅ 프로젝트 지원 이메일  선택 후 저장

 

✅ 로그인 제공업체에 Google 추가 완료 

 

📍 Google 인증 회원가입 & 로그인

📘 firebase.ts > new GoogleAuthProvider 추가

// firebase
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
import { getAuth, GoogleAuthProvider } from "firebase/auth"; // 👈 추가 : GoogleAuthProvider

. . .

// 앱 초기화
const firebaseApp = initializeApp(firebaseConfig, 'Tistory');
// 데이터베이스
const firebaseDB = getFirestore(firebaseApp);
const firebaseAuth = getAuth(firebaseApp); 
const fireProvider = new GoogleAuthProvider(); // 👈 추가
export { firebaseApp, firebaseDB, firebaseAuth, fireProvider};

 

📘구글계정 로그인 

 

signInWithPopup

- 팝업 창을 통해 소셜 로그인(구글, 페이스북 등)을 처리하는 메소드

- 사용자가 구글 계정으로 로그인하면 Firebase Auth와 연동

- 기존 계정이 있으면 로그인, 없으면 자동으로 새 계정 생성

- 완료되면 팝업이 닫히고 UserCredential 객체 반환

import { firebaseAuth, fireProvider } from "../../firebase";
import { signInWithPopup } from "firebase/auth";

export const LogIn = () => {
 
  const handleGoogle = async() => {
    try {
      const result = await signInWithPopup(firebaseAuth, fireProvider);
      const googleUser = result.user;
      console.log("Google 계정 회원가입 및 로그인 성공", googleUser);
    } catch (error) {
      console.error(error);
    }
  }

  return( 
    <div>
      <h2>구글 계정 연동 - 회원가입 & 로그인</h2>
      <button className="btn" onClick={handleGoogle}>
        Google 로그인하기
      </button>
    </div>
  )
}

 

✅ Google 로그인하기 버튼 클릭 시 로그인 팝업이 나와요!

⚠️ Cross-Origin-Opener-Policy policy would block the window.closed call.

 오류는 브라우저의 보안 정책(COOP: Cross-Origin-Opener-Policy) 때문에 발생하는 것

signInWithPopup 방식이 팝업 창을 열고 닫는 과정에서 콘솔 오류

 

✅ console에 오류가 나오지만 실제 기능은 정상 작동!

 

✅ 계속 진행 시 로그인 성공!

 

✅ firebase > Authentication에 google 계정 정보도 추가되어 회원가입이 되었어요.

✅ onAuthStateChanged 사용하고 있어서 구글 로그인 시에도 바로 로그인 체크를 할 수 있어요!

 

회원가입 로그인, 로그아웃, 구글 계정 연동 완료.

 

✍️ 기록

 

감사합니다. 😁

반응형
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.