알린홈마의 코드친구들
article thumbnail

firebase로 로그인을 하기 위해서는 파이어베이스 Authentication항목에서 기능을 활성화 해주어야 한다.

사용자 인증을 도와주는 다양한 업체가 있고, 그중에 제일 기본적인 이메일/비밀번호를 선택하고 추가적으로 구글을 선택했다

import { initializeApp } from "firebase/app";
import {
  getAuth,
  signInWithPopup,
  GoogleAuthProvider,
  signOut,
} from "firebase/auth";
import { getFirestore } from "firebase/firestore";

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,
  measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,
};

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

저번 포스팅에서 언급했듯, 파이어베이스 기본설정을 할 부분을 src > api > firebase.js 를 생성해서 해주었다.
 
CreateUserPage.jsx

import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import {
  createUserWithEmailAndPassword,
  getAuth,
  updateProfile,
} from "firebase/auth";
import { createPost, createUser } from "../api/firestore";
export default function CreateUser() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [userName, setUserName] = useState("");

  const navigate = useNavigate();
  const auth = getAuth();

  // 파이어베이스에 이메일 회원가입
  const joinEmail = async (email, password) => {
    const { user } = await createUserWithEmailAndPassword(
      auth,
      email,
      password
    );
    await updateProfile(auth.currentUser, { displayName: userName });
    return user;
  };

  // 회원가입 버튼 클릭
  const handleSignUp = async (e) => {
    // 기본 이벤트 막기
    e.preventDefault();
    // 파이어베이스에 회원가입 요청 보내기 (성공하면 로그인 페이지로 이동) (실패하면 에러 출력)
    try {
      await joinEmail(email, password);
      navigate("/login");
    } catch (error) {
      console.log(error);
    }
  };
  return (
    <div className="flex items-center justify-center h-screen">
      <form onSubmit={handleSignUp}>
        <div className="flex flex-col gap-4">
          <input
            type="email"
            placeholder="email"
            onChange={(e) => setEmail(e.target.value)}
            required
          />
          <input
            type="password"
            placeholder="password"
            onChange={(e) => setPassword(e.target.value)}
            required
          />
          <input
            type="text"
            name="userName"
            id="userName"
            placeholder="userName"
            onChange={(e) => setUserName(e.target.value)}
            required
          />
          <button
            type="submit"
            className={`btn_default ${
              !email || !password || !userName ? "disabled" : ""
            }`}
          >
            회원가입
          </button>
        </div>
      </form>
    </div>
  );
}

회원가입 페이지 컴포넌트에서 회원가입을 하는 기능을 따로 분리하지 않고 넣었다.
회원가입 기능 함수는 회원가입 페이지에서만 사용할 코드임으로 따로 분리할 필요가 없다고 판단했다.
 

 const joinEmail = async (email, password) => {
    const { user } = await createUserWithEmailAndPassword(
      auth,
      email,
      password
    );
    await updateProfile(auth.currentUser, { displayName: userName });
    return user;
  };

로그인 기능을 위해서 구글 파이어베이스에서 제공하는 "createUserWithEmailAndPassword" 함수를 이용해서 계정을 생성해준다
emaill과 password 값 및 auth 값을을 인자로 넣어줘야 한다고 한다.
 
이메일과 패스워드로 계정을 생성하게 되면 구글로 로그인한것과 달리, displayName, photoURL 등 몇몇 정보가 null값으로 받아진다.
당장은 닉네임을 표현해주고 싶어  "createUserWithEmailAndPassword"에서 유저 정보를 받아오고 async await를 이용해 
"updateProfile" 함수를 실행했다 인자로는 getAuth() 받아온 auth의 currentUser 값을 넣고 displayName에 사용하자 입력한 userName 값을 넣어준다
 
최종적으로 user를 반환하여 user 정보 displayName에 사용자가 입력한 닉네임이 포함 될 수 있도록 해주었다.
 
후에, 사용자 프로필 사진을 변경할때 해당 함수를 사용해야 할거 같다.
 
LoginPage.jsx

import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { getAuth, signInWithEmailAndPassword } from "firebase/auth";

export default function LoginPage() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState(null);
  const navigate = useNavigate();

  const auth = getAuth();
  const loginEmail = async (email, password) => {
    await signInWithEmailAndPassword(auth, email, password);
  };
  const handelLogin = async (e) => {
    e.preventDefault();
    try {
      await loginEmail(email, password);
      navigate("/");
    } catch (error) {
      if (!email) {
        setError("이메일을 입력해주세요");
      } else if (!password) {
        setError("비밀번호를 입력해주세요");
      } else {
        setError("이메일 또는 비밀번호가 일치하지 않습니다");
      }
      setTimeout(() => {
        setError(null);
      }, 3000);
    }
  };
  return (
    <div className="flex items-center justify-center h-screen flex-col gap-4">
      <form onSubmit={handelLogin}>
        <div className="flex flex-col gap-4">
          <input
            type="email"
            placeholder="email"
            onChange={(e) => setEmail(e.target.value)}
          />
          <input
            type="password"
            placeholder="password"
            onChange={(e) => setPassword(e.target.value)}
          />
          <button type="submit" className="btn_default">
            로그인
          </button>
        </div>
      </form>
      <Link to="/join">회원가입</Link>
      <div>구글로 로그인</div>
      {error && <span>{error}</span>}
    </div>
  );
}

로그인 기능은 "signInWithEmailAndPassword"  함수에 auth정보와 ,이메일 암호를 넣으면 로그인이 된다!

 

export async function logout() {
  await signOut(auth);
  return null;
}

export function onUserStateChanged(callback) {
  auth.onAuthStateChanged((user) => {
    callback(user);
  });
}

로그아웃 코드는 signOut함수에 auth 값을 전달하면 끝!

 

로그인한 유저정보를 받아오기 위해 onAuthStateChanged 함수에 유저정보를 넣어 callback 함수를 실행한다

 

App.js

import { Outlet } from "react-router-dom";
import NavBar from "./components/NavBar";
import { useEffect } from "react";
import { onUserStateChanged } from "./api/firebase";
import { useNavigate } from "react-router-dom";
import { getUserDate } from "./api/firestore";
function App() {
  const navigate = useNavigate();

  useEffect(() => {
    onUserStateChanged((user) => {
      if (!user) {
        navigate("/login");
      }
    });
  }, []);
  return (
    <div className="App h-full">
      <div id="container" className="flex h-full">
        <NavBar />
        <Outlet />
      </div>
    </div>
  );
}

export default App;

App.js가 기본 라우터값이 "/"로 설정했기 때문에 로그인을 하지 않은 사용자가 접근을 안다면 바로 로그인 페이지로 이동하도록 하는 코드를 위의 onUserStateChaged 에서 user 값을 받아와 !user 면 "/login" 으로 이동하도록 해두었다

profile

알린홈마의 코드친구들

@알린팬클럽홈마

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...