๐Ÿœ Firebase Auth: ๊ณ„์ • ๋งŒ๋“ค๊ณ  ๋กœ๊ทธ์ธ ํ•˜๊ธฐ 2

summereuna๐Ÿฅยท2022๋…„ 3์›” 28์ผ

๐ŸŒŸ Twinkle (React, Firebase)

๋ชฉ๋ก ๋ณด๊ธฐ
8/42

๊ทธ๋‚˜์ €๋‚˜ ๋กœ๊ทธ์ธ๋„ ํ–ˆ๋Š”๋ฐ ์•„์ง ์ด๋ฉœ/๋น„๋ฒˆ ์ž…๋ ฅ์ฐฝ์ด ๋ณด์ด๋Š” ๊ฒƒ์ด ๊ฑฐ์Šฌ๋ฆฐ๋‹ค.

์™œ ๋กœ๊ทธ์ธํ–ˆ๋Š”๋ฐ๋„ ์ด๋ฉœ/๋น„๋ฒˆ ์ž…๋ ฅ์ฐฝ์ด ๋ณด์ด๋Š” ๊ฑธ๊นŒ?


๋ฌธ์ œ

ํ˜„์žฌ currentUser ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์žˆ๋‹ค.
์ด๋•Œ ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด currentUser ๊ฐ’์€ null๋กœ ํ‘œ์‹œ๋œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ํ˜„์žฌ App์ด ๋กœ๋“œ๋  ๋•Œ, ๋„ˆ๋ฌด ๋นจ๋ฆฌ ๋กœ๊ทธ๋˜๊ธฐ ๋•Œ๋ฌธ์— firebase๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ํ–ˆ๋Š”์ง€ ์•ˆํ–ˆ๋Š”์ง€ ํ™•์ธํ•  ์‹œ๊ฐ„์ด ์—†๋‹ค. ๋”ฐ๋ผ์„œ App์ด ์‹œ์ž‘ํ•˜๋ฉด ํ•ญ์ƒ ๋กœ๊ทธ์•„์›ƒ ์ƒํƒœ๊ฐ€ ๋˜๊ณ , authService.currentUser๋Š” ํ•ญ์ƒ null, ์ฆ‰ ๋กœ๊ทธ์ธํ•œ ์œ ์ €๊ฐ€ ์—†๋Š” ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.

์ฆ‰, Auth ๊ฐ์ฒด์˜ ์ดˆ๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋˜์ง€ ์•Š์•„ currentUser๊ฐ€ null์ธ ๊ฒƒ์ด๋‹ค.
๐Ÿ‘‰ ๊ด€์ฐฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž์˜ ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ผ๋‹จ ์•„๋ž˜ ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋ฉฐ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์ ๊ฒ€ํ•ด ๋ณด์ž.


์ค‘๊ฐ„์— setInterval()์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์„ ์ฃผ๊ณ  ์ฝ˜์†”์— currentUser๋ฅผ ์ฐ์–ด๋ณด์ž.

๐Ÿ“ components/App.js

//์ ˆ๋Œ€ ๊ฒฝ๋กœ(absolute import)
import AppRouter from "components/Router";
import { useState } from "react";
//์ ˆ๋Œ€ ๊ฒฝ๋กœ(absolute import)
//fbase์—์„œ authService ๊ฐ€์ ธ์˜ค๊ธฐ(export๋กœ ๋‚ด๋ณด๋ƒˆ๊ธฐ ๋•Œ๋ฌธ์— {} ์ค‘๊ด„ํ˜ธ ์ณ์„œ ๊ฐ€์ ธ์™€์•ผ ํ•จ)
import { authService } from "fbase";

function App() {
  //์ธ์ฆ์„œ๋น„์Šค์˜ ํ˜„์žฌ ์œ ์ €๊ฐ€ ์ฐธ์ธ์ง€ ๊ฑฐ์ง“์ธ์ง€์— ๋”ฐ๋ผ (๋กœ๊ทธ์ธํ–ˆ๋Š”์ง€ ์•ˆํ–ˆ๋Š”์ง€์— ๋”ฐ๋ผ)state ๋‹ฌ๋ผ์ง
  const [isLoggedIn, setIsLoggedIn] = useState(authService.currentUser);
  //๐Ÿ”ฅ ์ฒ˜์Œ์— currentUser์— ๋ญ๋œจ๋Š”์ง€ ๋ณด์ž
  console.log(authService.currentUser);
  //๐Ÿ”ฅ 2์ดˆ ๋งˆ๋‹ค currentUser๋ฅผ ์ฝ˜์†”์— ์ฐ์–ด ๋ณด์ž
  setInterval(() => {
    console.log(authService.currentUser);
  }, 2000);
  //Router ๋ Œ๋”ํ•˜๊ธฐ
  //AppRouter์— prop ์ „๋‹ฌํ•˜๊ธฐ
  return (
    <>
      <AppRouter isLoggedIn={isLoggedIn} />
      <footer>&copy; twinkle {new Date().getFullYear()}</footer>
    </>
  );
}

export default App;
  • ๋ณด๋‹ค์‹œํ”ผ ์ฒ˜์Œ์—” null์ด ๋œจ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. 2์ดˆ ํ›„์—๋Š” currentUser์— ๊ฐ’์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ์‹œ์ž‘ํ•  ๋•Œ๋Š” ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ์ด ๋˜์ง€ ์•Š์€ ์ƒํƒœ์ด๊ณ  2์ดˆ๊ฐ€ ์ง€๋‚˜์„œ์•ผ ๋กœ๊ทธ์ธ๋œ ์ƒํƒœ์ด๋‹ค.

ํ•ด๊ฒฐ: Auth ๊ฐ์ฒด์— ๊ด€์ฐฐ์ž ์„ค์ •ํ•˜๊ธฐ

๊ด€์ฐฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž์˜ ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

โœ… onAuthStateChanged ๊ด€์ฐฐ์ž

์‚ฌ์šฉ์ž์˜ ๋กœ๊ทธ์ธ ์ƒํƒœ์˜ ๋ณ€ํ™”๋ฅผ ๊ด€์ฐฐํ•˜๋Š” ๊ด€์ฐฐ์ž์ด๋‹ค.

  • ์ด๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ event listener๋กœ, ์œ ์ € ์ƒํƒœ์— ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ ๋ณ€ํ™”๋ฅผ ์•Œ์•„์ฐจ๋ฆฐ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์œ ์ €๊ฐ€ ๋กœ๊ทธ์ธ ํ–ˆ์„ ๋•Œ, ๋กœ๊ทธ์•„์›ƒ ํ–ˆ์„ ๋•Œ, ๊ณ„์ •์„ ์ƒ์„ฑํ•  ๋•Œ, firebase๊ฐ€ ์ดˆ๊ธฐํ™”๋  ๋•Œ ํŠธ๋ฆฌ๊ฑฐ ๋œ๋‹ค.

v.9์€ ์ด ๋ฌธ์„œ ์ฐธ๊ณ 
ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Auth ๊ฐ์ฒด์— ๊ด€์ฐฐ์ž๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

import { getAuth, onAuthStateChanged } from "firebase/auth";
//
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
  if (user) {
    // User is signed in, see docs for a list of available properties
    // https://firebase.google.com/docs/reference/js/firebase.User
    const uid = user.uid;
    // ...
  } else {
    // User is signed out
    // ...
  }
});
  • ๊ด€์ฐฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ˜„์žฌ ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ Auth ๊ฐ์ฒด๊ฐ€ ์ค‘๊ฐ„ ๋‹จ๊ณ„(์ดˆ๊ธฐํ™” ๋“ฑ)์— ์žˆ์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค. signInWithRedirect๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด onAuthStateChanged ๊ด€์ฐฐ์ž๋Š” getRedirectResult๊ฐ€ ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ ํ›„์— ํŠธ๋ฆฌ๊ฑฐ๋œ๋‹ค.

useEffect()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ onAuthStateChanged ๊ด€์ฐฐ์ž๋ฅผ ์ž‘์„ฑํ•˜์ž.

//์ ˆ๋Œ€ ๊ฒฝ๋กœ(absolute import)
import AppRouter from "components/Router";
import { useEffect, useState } from "react";
//์ ˆ๋Œ€ ๊ฒฝ๋กœ(absolute import)
//fbase์—์„œ authService ๊ฐ€์ ธ์˜ค๊ธฐ(export๋กœ ๋‚ด๋ณด๋ƒˆ๊ธฐ ๋•Œ๋ฌธ์— {} ์ค‘๊ด„ํ˜ธ ์ณ์„œ ๊ฐ€์ ธ์™€์•ผ ํ•จ)
import { authService } from "fbase";
import { getAuth, onAuthStateChanged } from "firebase/auth";

function App() {
  //๐Ÿ”ฅ firebase๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์„ ์ดˆ๊ธฐํ™”ํ•˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ๋‚˜์„œ isLoggedIn์ด ๋ฐ”๋€Œ๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค.
  const [init, setInit] = useState(false);
  //์ธ์ฆ์„œ๋น„์Šค์˜ ํ˜„์žฌ ์œ ์ €๊ฐ€ ์ฐธ์ธ์ง€ ๊ฑฐ์ง“์ธ์ง€์— ๋”ฐ๋ผ (๋กœ๊ทธ์ธํ–ˆ๋Š”์ง€ ์•ˆํ–ˆ๋Š”์ง€์— ๋”ฐ๋ผ)state ๋‹ฌ๋ผ์ง
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  //๐Ÿ”ฅ ์–ด๋–ป๊ฒŒ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ์„๊นŒ? useEffect()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค ใ…‡ใ…‡!
  useEffect(() => {
    const auth = getAuth();
    //๐Ÿ”ฅ๐Ÿ”ฅ ์œ ์ € ๋ณ€ํ™”๊ฐ€ ์žˆ๋Š”์ง€ listenํ•˜๊ธฐ: onAuthStateChanged๊ด€์ฐฐ์ž ์‚ฌ์šฉ
    //๐Ÿ”ฅ onAuthStateChanged์€ ์ฝœ๋ฐฑ์ด ํ•„์š”ํ•œ๋ฐ, ์ฝœ๋ฐฑ์€ user์ด๋‹ค.
    onAuthStateChanged(auth, (user) => {
      //console.log(user);
      //๐Ÿ”ฅ user๊ฐ€ ์žˆ๋‹ค๋ฉด ๋กœ๊ทธ์ธ ์ฐธ์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ , ์•„๋‹ˆ๋ผ๋ฉด ๋กœ๊ทธ์ธ ๊ฑฐ์ง“์œผ๋กœ
      if (user) {
        setIsLoggedIn(true);
        const uid = user.uid;
      } else {
        setIsLoggedIn(false);
      }
      //๐Ÿ”ฅ ๊ทธ๋Ÿฌ๊ณ  ๋‚˜์„œ ์ดˆ๊ธฐํ™” ์‹œ์ผœ๋ผ
      setInit(true);
    });
  }, []);
  //Router ๋ Œ๋”ํ•˜๊ธฐ & AppRouter์— prop ์ „๋‹ฌํ•˜๊ธฐ
  return (
    <>
      {/*๐Ÿ”ฅ init์ด ๊ฑฐ์ง“์ด๋ฉด ๋ผ์šฐํ„ฐ ์ˆจ๊ธฐ๊ณ  ์ดˆ๊ธฐํ™” ์ค‘์ด๋ผ๊ณ  ๋„์šฐ๊ธฐ*/}
      {init ? <AppRouter isLoggedIn={isLoggedIn} /> : "์ดˆ๊ธฐํ™”์ค‘..."}
      <footer>&copy; twinkle {new Date().getFullYear()}</footer>
    </>
  );
}

export default App;

์˜ค์ผ€์ด
์ดˆ๊ธฐํ™”์ค‘...๋œฌ๋‹ค์Œ์— ๋กœ๊ทธ์ธ ๋˜์—ˆ์œผ๋ฉด HOME์ด ๋œฌ๋‹ค.

๊ณ„์ •

์ด์ œ ๋กœ๊ทธ์•„์›ƒํ•˜์ž. indexedDB์— ์žˆ๋Š” data ์ง€์šฐ๋ฉด ๋จ.
๊ณ„์ • ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ์šด ๊ณ„์ • ๋งŒ๋“ค์ž.

๊ทธ๋Ÿฌ๊ณ  ๋‚˜์„œ ๋˜ ๋˜‘๊ฐ™์€ ๊ณ„์ •์„ ๋งŒ๋“œ๋ ค๊ณ  ํ•˜๋ฉด ์ฝ˜์†”์— ์˜ค๋ฅ˜๊ฐ€ ๋œฌ๋‹ค.

email์ด ์ด๋ฏธ ์‚ฌ์šฉ ์ค‘์ด์–ด์„œ ๋œจ๋Š” ์˜ค๋ฅ˜์ธ๋ฐ, ์ด ๋ถ€๋ถ„์€ ์—ฌ๊ธฐ์— ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜์ด๋‹ค.
๐Ÿ“ Auth.js

//๐Ÿ”ฅ ์ด๋ฉ”์ผ, ๋น„๋ฒˆ์œผ๋กœ ์ƒˆ๋กœ์šด ๊ณ„์ • ์ƒ์„ฑ ๋ฐ ๋กœ๊ทธ์ธ ํ•˜๊ธฐ์œ„ํ•ด ์•„๋ž˜ ๋ฉ”์„œ๋“œ ์ž„ํฌํŠธํ•˜๊ธฐ
//๐Ÿ”ฅ getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword
import {
  getAuth,
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
} from "firebase/auth";

import { useState } from "react";

const Auth = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [newAccount, setNewAccount] = useState(true);
  const auth = getAuth();
  //email, password์— ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฒคํŠธ
  const onChange = (event) => {
    const {
      target: { name, value },
    } = event;
    if (name === "email") {
      setEmail(value);
    } else if (name === "password") {
      setPassword(value);
    }
  };
  //form์— ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฒคํŠธ
  const onSubmit = async (event) => {
    event.preventDefault();
    //form submitํ•˜๋ฉด newAccount ์Šคํ…Œ์ดํŠธ๋กœ ํ™•์ธํ•˜์ž!
    //newAccount๊ฐ€ ์ฐธ์ด๋ฉด ๊ณ„์ • ์ƒˆ๋กœ ๋งŒ๋“ค๊ณ , ๊ฑฐ์ง“์ด๋ฉด ๋กœ๊ทธ์ธํ•˜๊ธฐ
    try {
      let data;
      if (newAccount) {
        data = await createUserWithEmailAndPassword(auth, email, password);
        setNewAccount(false);
      } else {
        data = await signInWithEmailAndPassword(auth, email, password);
      }
      console.log(data);
    } catch (error) {
      //โ—๏ธโ—๏ธโ—๏ธโ—๏ธโ—๏ธโ—๏ธ์—ฌ๊ธฐ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ!โ—๏ธโ—๏ธโ—๏ธโ—๏ธโ—๏ธ
      console.log(error);
    }
  };

  return (
    <div>
      <h1>๋กœ๊ทธ์ธ ํŽ˜์ด์ง€</h1>
      <p>๋กœ๊ณ  ๋„ฃ๊ธฐ</p>
      <form onSubmit={onSubmit}>
        <input
          type="email"
          placeholder="Email"
          required
          value={email}
          name="email"
          onChange={onChange}
        ></input>
        <input
          type="password"
          placeholder="Password"
          required
          value={password}
          name="password"
          onChange={onChange}
        ></input>
        <input type="submit" value={newAccount ? "Create Account" : "Login"} />
      </form>
      <div>
        <button>Continue with Google</button>
        <button>Continue with GitHub</button>
      </div>
    </div>
  );
};

export default Auth;

๋”ฐ๋ผ์„œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋„์šฐ์ž.

//์ด๋ฉ”์ผ, ๋น„๋ฒˆ์œผ๋กœ ์ƒˆ๋กœ์šด ๊ณ„์ • ์ƒ์„ฑ ๋ฐ ๋กœ๊ทธ์ธ ํ•˜๊ธฐ์œ„ํ•ด ์•„๋ž˜ ๋ฉ”์„œ๋“œ ์ž„ํฌํŠธํ•˜๊ธฐ
//getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword
import {
  getAuth,
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
} from "firebase/auth";

import { useState } from "react";

const Auth = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [newAccount, setNewAccount] = useState(true);
  //๐Ÿ”ฅ error ์Šคํ…Œ์ด๋“œ๋ฅผ ๋งŒ๋“ค์ž. ๋””ํดํŠธ ๊ฐ’์œผ๋กœ ๋น„์–ด ์žˆ๋Š” ํ…์ŠคํŠธ ์ฃผ๊ธฐ
  const [error, setError] = useState("");
  const auth = getAuth();
  //email, password์— ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฒคํŠธ
  const onChange = (event) => {
    const {
      target: { name, value },
    } = event;
    if (name === "email") {
      setEmail(value);
    } else if (name === "password") {
      setPassword(value);
    }
  };
  //form์— ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฒคํŠธ
  const onSubmit = async (event) => {
    event.preventDefault();
    //form submitํ•˜๋ฉด newAccount ์Šคํ…Œ์ดํŠธ๋กœ ํ™•์ธํ•˜์ž!
    //newAccount๊ฐ€ ์ฐธ์ด๋ฉด ๊ณ„์ • ์ƒˆ๋กœ ๋งŒ๋“ค๊ณ , ๊ฑฐ์ง“์ด๋ฉด ๋กœ๊ทธ์ธํ•˜๊ธฐ
    try {
      let data;
      if (newAccount) {
        data = await createUserWithEmailAndPassword(auth, email, password);
        setNewAccount(false);
      } else {
        data = await signInWithEmailAndPassword(auth, email, password);
      }
      console.log(data);
    } catch (error) {
      //๐Ÿ”ฅ์—๋Ÿฌ๊ฐ€ ์ƒ๊ธฐ๋ฉด error ์Šคํ…Œ์ดํŠธ์— ๋„ฃ์–ด์„œ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€ ๋„์šฐ๊ธฐ
      //console.log(error.message);
      setError(error.message);
    }
  };

  return (
    <div>
      <h1>๋กœ๊ทธ์ธ ํŽ˜์ด์ง€</h1>
      <p>๋กœ๊ณ  ๋„ฃ๊ธฐ</p>
      <form onSubmit={onSubmit}>
        <input
          type="email"
          placeholder="Email"
          required
          value={email}
          name="email"
          onChange={onChange}
        ></input>
        <input
          type="password"
          placeholder="Password"
          required
          value={password}
          name="password"
          onChange={onChange}
        ></input>
        <input type="submit" value={newAccount ? "Create Account" : "Login"} />
        {/*๐Ÿ”ฅ error ๋ณด์—ฌ์ฃผ๊ธฐ*/}
        {error}
      </form>
      <div>
        <button>Continue with Google</button>
        <button>Continue with GitHub</button>
      </div>
    </div>
  );
};

export default Auth;

๋กœ๊ทธ์ธ/๊ฐ€์ž…ํ•˜๊ธฐ ํ† ๊ธ€ ๋ฒ„ํŠผ ๋งŒ๋“ค๊ธฐ

//์ด๋ฉ”์ผ, ๋น„๋ฒˆ์œผ๋กœ ์ƒˆ๋กœ์šด ๊ณ„์ • ์ƒ์„ฑ ๋ฐ ๋กœ๊ทธ์ธ ํ•˜๊ธฐ์œ„ํ•ด ์•„๋ž˜ ๋ฉ”์„œ๋“œ ์ž„ํฌํŠธํ•˜๊ธฐ
//getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword
import {
  getAuth,
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
} from "firebase/auth";

import { useState } from "react";

const Auth = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [newAccount, setNewAccount] = useState(true);
  //error ์Šคํ…Œ์ด๋“œ๋ฅผ ๋งŒ๋“ค์ž. ๋””ํดํŠธ ๊ฐ’์œผ๋กœ ๋น„์–ด ์žˆ๋Š” ํ…์ŠคํŠธ ์ฃผ๊ธฐ
  const [error, setError] = useState("");
  const auth = getAuth();
  //email, password์— ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฒคํŠธ
  const onChange = (event) => {
    const {
      target: { name, value },
    } = event;
    if (name === "email") {
      setEmail(value);
    } else if (name === "password") {
      setPassword(value);
    }
  };
  //form์— ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฒคํŠธ
  const onSubmit = async (event) => {
    event.preventDefault();
    //form submitํ•˜๋ฉด newAccount ์Šคํ…Œ์ดํŠธ๋กœ ํ™•์ธํ•˜์ž!
    //newAccount๊ฐ€ ์ฐธ์ด๋ฉด ๊ณ„์ • ์ƒˆ๋กœ ๋งŒ๋“ค๊ณ , ๊ฑฐ์ง“์ด๋ฉด ๋กœ๊ทธ์ธํ•˜๊ธฐ
    try {
      let data;
      if (newAccount) {
        data = await createUserWithEmailAndPassword(auth, email, password);
        setNewAccount(false);
      } else {
        data = await signInWithEmailAndPassword(auth, email, password);
      }
      console.log(data);
    } catch (error) {
      //์—๋Ÿฌ๊ฐ€ ์ƒ๊ธฐ๋ฉด error ์Šคํ…Œ์ดํŠธ์— ๋„ฃ์–ด์„œ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€ ๋„์šฐ๊ธฐ
      //console.log(error.message);
      setError(error.message);
    }
  };
  //๐Ÿ”ฅ ๊ฐ€์ž…ํ•ด์•ผํ•˜๋Š”์ง€ ๋กœ๊ทธ์ธํ•ด์•ผ ํ•˜๋Š”์ง€ ํ† ๊ธ€ํ•˜๋Š” ํ•จ์ˆ˜: newAccount์˜ ์ด์ „ ๊ฐ’๊ณผ ๋ฐ˜๋Œ€๋˜๋Š” ๊ฐ’ ๋ฆฌํ„ดํ•˜๊ธฐ
  const toggleAccount = () => setNewAccount((prev) => !prev);
  return (
    <div>
      <h1>๋กœ๊ทธ์ธ ํŽ˜์ด์ง€</h1>
      <p>๋กœ๊ณ  ๋„ฃ๊ธฐ</p>
      <form onSubmit={onSubmit}>
        <input
          type="email"
          placeholder="Email"
          required
          value={email}
          name="email"
          onChange={onChange}
        ></input>
        <input
          type="password"
          placeholder="Password"
          required
          value={password}
          name="password"
          onChange={onChange}
        ></input>
        <input type="submit" value={newAccount ? "๊ฐ€์ž…ํ•˜๊ธฐ" : "๋กœ๊ทธ์ธ"} />
        {/*error ๋ณด์—ฌ์ฃผ๊ธฐ*/}
        {error}
      </form>
      {/*๐Ÿ”ฅ newAccount(์ƒˆ๋กœ์šด ๊ณ„์ •)๊ฐ€ ์ฐธ์ด๋ฉด ๋กœ๊ทธ์ธ, ๊ฑฐ์ง“์ด๋ฉด ๊ฐ€์ž…ํ•˜๊ธฐ๊ฐ€ ๋˜๋Š” ํ† ๊ธ€ ๋งŒ๋“ค๊ธฐ */}
      <button onClick={toggleAccount}>
        {newAccount ? "๋กœ๊ทธ์ธ" : "๊ฐ€์ž…ํ•˜๊ธฐ"}
      </button>
      <div>
        <button>Continue with Google</button>
        <button>Continue with GitHub</button>
      </div>
    </div>
  );
};

export default Auth;
profile
Always have hope๐Ÿ€ & constant passion๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€