Firebase 셋업을 완료하고 이번에 Firebase 회원가입 기능을 구현 해 보려한다.
이메일로 회원가입 하는 기능을 만들기 전에 회원가입 페이지를 간단하게 구현 하였다.
구현 내용
- 사용자가 form에 이름 , 이메일 ,비밀번호를 입력한다.
- 비밀번호가 일치한지 확인한다. (일치하지 않는다면 오류메세지 출력)
- 회원가입 버튼을 누르면
firebase
에createUserWithEmailAndPassword
로 이름 , 이메일 ,비밀번호 값을 전달한다.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
,password
를 받아오고 회원가입이 성공적으로 완료 된다면displayName
에name
값을 넣어준다. 그 후에 성공 메세지를 출력해준다.
공식문서
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에 등록된 사용자 정보를 이용하여 로그인/로그아웃 기능을 구현 해 볼 것이다!