React 로 만드는 음악 커뮤니티 사이트 #3 (Firebase로 회원가입 구현)

시도·2023년 5월 2일
0

React

목록 보기
5/7
post-thumbnail

Firebase 셋업을 완료하고 이번에 Firebase 회원가입 기능을 구현 해 보려한다.

이메일로 회원가입 하는 기능을 만들기 전에 회원가입 페이지를 간단하게 구현 하였다.

구현 내용

  1. 사용자가 form에 이름 , 이메일 ,비밀번호를 입력한다.
  2. 비밀번호가 일치한지 확인한다. (일치하지 않는다면 오류메세지 출력)
  3. 회원가입 버튼을 누르면 firebasecreateUserWithEmailAndPassword 로 이름 , 이메일 ,비밀번호 값을 전달한다.
  4. createUserWithEmailAndPassword 에서 값을 받아서 fireabase/auth 에서 유효성 검사를 실행한 후 , 오류가 있다면 그에 맞는 오류메세지를 출력하고 정상적으로 완료 된다면 회원가입 진행후 displayName 에 이름 값을 추가 한 뒤 완료 메세지를 출력한다.

회원가입 폼 만들기

src/pages/Signup.tsx


import React, { useState } from "react";
import Button from "../components/Button/Button";
import { signup } from "../api/firebase";
import { toast } from "react-hot-toast";

const SignIn = () => {
  const [name, setName] = useState<string>("");
  const [email, setEmail] = useState<string>("");
  const [password, setPassword] = useState<string>("");
  const [rePassword, setRePassword] = useState<string>("");

  return (
    <form className=" w-72 mx-auto flex flex-col justify-center">
      <h2 className=" text-center my-12 text-2xl font-bold text-gray-800 pb-2 border border-t-0 border-x-0  border-b-gray-600">회원가입</h2>
      <div className="relative">
        <label htmlFor="name" className={`text-md absolute font-gray-600 transition ease-in-out left-3 top-4 ${isFocusName ? "-translate-x-2" : ""} ${isFocusName ? "-translate-y-3" : ""} ${isFocusName ? "scale-75" : ""}`}>
          이름
        </label>
        <input
          onChange={(e) => {
            setName(e.target.value);
          }}
          onBlur={handleNameBlur}
          onFocus={handleNameFocus}
          value={name}
          type="text"
          id="name"
          name="name"
          className={`border border-gray-600 w-full rounded-[4px] h-14 pt-4 pl-3 mb-2`}
        />
      </div>
      <div className="relative">
        <label htmlFor="email" className={`text-md absolute font-gray-600 transition ease-in-out left-3 top-4 ${isFocus ? "-translate-x-2" : ""} ${isFocus ? "-translate-y-3" : ""} ${isFocus ? "scale-75" : ""}`}>
          이메일
        </label>
        <input
          onChange={(e) => {
            setEmail(e.target.value);
          }}
          onBlur={handleEmailBlur}
          onFocus={handleEmailFocus}
          value={email}
          type="text"
          id="email"
          name="email"
          className={`border border-gray-600 w-full rounded-[4px] h-14 pt-4 pl-3 mb-1`}
        />
      </div>
      <div className="relative">
        <label htmlFor="pw" className={`text-md absolute font-gray-600 transition ease-in-out left-3 top-4 ${isFocusPw ? "-translate-x-2" : ""} ${isFocusPw ? "-translate-y-3" : ""} ${isFocusPw ? "scale-75" : ""}`}>
          비밀번호
        </label>
        <input
          onChange={(e) => {
            setPassword(e.target.value);
          }}
          onBlur={handlePwBlur}
          onFocus={handlePwFocus}
          value={password}
          type="password"
          id="pw"
          name="pw"
          className={`border border-gray-600 w-full rounded-[4px] h-14 pt-4 pl-3 mb-2`}
        />
      </div>
      <div className="relative">
        <label htmlFor="re_pw" className={`text-md absolute font-gray-600 transition ease-in-out left-3 top-4 ${isFocusRePw ? "-translate-x-2" : ""} ${isFocusRePw ? "-translate-y-3" : ""} ${isFocusRePw ? "scale-75" : ""}`}>
          비밀번호 확인
        </label>
        <input
          onChange={(e) => {
            setRePassword(e.target.value);
          }}
          onBlur={handleRePwBlur}
          onFocus={handleRePwFocus}
          value={rePassword}
          type="password"
          id="re_pw"
          name="re_pw"
          className={`border border-gray-600 w-full rounded-[4px] h-14 pt-4 pl-3 mb-2`}
        />
      </div>
      <Button
        onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
          if (password !== rePassword) {
            e.preventDefault();
            toast.error("입력하신 비밀번호가 다릅니다.");
          } else {
            e.preventDefault();
            signup(name, email, password);
            setName("");
            setEmail("");
            setPassword("");
            setRePassword("");
          }
        }}
        label="회원가입"
        textStyle="text-white"
        bgStyle="bg-blue-600"
      />
    </form>
  );
};

export default SignIn;

Button 에 onClick 이벤트를 추가해준다.

  • 비밀번호가 일치하지 않는다면 error 메세지를 출력한다.
  • 비밀번호가 일치한다면 ../api/firebase 에 있는 signup 함수를 실행하고 value 값을 초기화 시켜준다.

회원가입 구현

../api/firebase

import { initializeApp } from "firebase/app";
import { getAuth, signInWithPopup, GoogleAuthProvider, createUserWithEmailAndPassword, updateProfile } from "firebase/auth";
import { toast } from "react-hot-toast";

const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.REACT_APP_FIREBASE_DB_URL,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth();
const provider = new GoogleAuthProvider();

***
생략
***
  
  
//Email 회원가입
export const signup = async (name: string, email: string, password: string) => {
  await createUserWithEmailAndPassword(auth, email, password)
    .then((userCredential) => {
      const user = userCredential.user;
      updateProfile(user, { displayName: name }); // 가입한 유저 정보에 이름을 저장한다.
      // console.log(user);
      toast.success("회원가입이 완료 되었습니다.");
    })
    .catch((error) => {
      const errorCode = error.code;

      switch (errorCode) {
        case "auth/weak-password":
          toast.error("비밀번호는 6자리 이상이어야 합니다.");
          break;
        case "auth/invalid-email":
          toast.error("잘못된 이메일 형식입니다.");
          break;
        case "auth/email-already-in-use":
          toast.error("이미 사용중인 이메일 입니다.");
          break;
      }
    });
};

위에 보이듯이 props 값으로 name , email, password 를 받아오고 회원가입이 성공적으로 완료 된다면 displayNamename 값을 넣어준다. 그 후에 성공 메세지를 출력해준다.

공식문서
https://firebase.google.com/docs/auth/web/password-auth?hl=ko
사용자 프로필 업데이트
https://firebase.google.com/docs/auth/web/manage-users?hl=ko

만약 오류가 발생한다면,

밑에 보이는 사진 처럼 오류 메세지를 전송해주고,

회원가입이 성공적으로 완료된다면,

회원가입이 완료 되었다는 메세지가 출력된다.

Fireabase 에 사용자 정보가 잘 등록 된 모습을 볼 수 있다.


🔥 오류 사항

입력 폼 CSS 에 문제가 있다는 것을 발견했다!!
원래는 Focus 값에 대해서만 생각해서 Css값을 줬는데 ,
Input에 값이 있어도 Focus가 아웃되면 blur 함수가 실행되면서 value 값을 가려버린다. input 에 대한 css 로직을 다시 구상해야 할 것 같다.


🚀 다음 구현 내용

이제 이메일 회원가입과 Google계정으로 로그인 하는 것을 완료 했으니 firebase에 등록된 사용자 정보를 이용하여 로그인/로그아웃 기능을 구현 해 볼 것이다!

profile
나의 성장일지 💫

0개의 댓글