저번 포스팅에서 이메일과 비밀번호를 사용하여 계정을 만들어보았습니다. 이번 시간에는 만든 이메일과 비밀번호를 사용하여 로그인을 해보겠습니다.
- firebase
signInWithEmailAndPassword
을 사용하여 로그인을 한다.- 로그인 정보를 가져와서 전역에서 사용할 수 있도록 한다.
import React, { ChangeEvent, useState } from "react";
import { Link, useNavigate} from "react-router-dom";
// INTERFACE
import { UserInputInterface } from "../interfaces/user.interface";
// CSS
import { UserForm } from "../styles/userForm.styled";
import { Button, TextField } from "@mui/material";
export const Login = () => {
const [inputs, setInputs] = useState<UserInputInterface>({
email: "",
password: "",
});
const { email, password } = inputs;
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.currentTarget;
setInputs({ ...inputs, [name]: value });
};
return (
<UserForm>
<div className={"doc-title"}>
<span>Login</span>
</div>
<article className={"user-form-article"}>
<div className={"user-form-wrap"}>
<div className={"user-form"}>
<form onSubmit={onSubmit}>
<TextField
onChange={onChange}
value={email}
label="email"
variant="outlined"
name={"email"}
type={"email"}
required
/>
<TextField
onChange={onChange}
value={password}
label="password"
variant="outlined"
name={"password"}
type={"password"}
required
/>
<Button
variant={"contained"}
type={"submit"}
disabled={
email.length !== 0 && password.length !== 0 ? false : true
}
>
Log In
</Button>
</form>
</div>
<div className={"cont-link"}>
<Link
to={"/signup"}
style={{ textDecoration: "none", color: "inherit" }}
>
Not a member yet?
</Link>
</div>
</div>
</article>
</UserForm>
);
};
💡
onChange
함수까지는 회원가입 절차와 동일하기 때문에 그대로 사용하겠습니다. 회원가입 때와 마찬가지로 모든 input에 값이 있을 때 버튼이 활성화 됩니다.
이제 본격적으로 로그인 폼을 submit 해보겠습니다.
폼을 제출할 때 firebase의 signInWithEmailAndPassword
을 사용하여 유저 정보를 가져오겠습니다. 유저 정보를 성공적으로 가져왔다면 '/'
경로로 이동하도록 하겠습니다.
추가 부분만 작성하겠습니다.
// FIREBASE
import { firebaseAuth } from "../initFirebase";
import { signInWithEmailAndPassword } from "firebase/auth";
export const Login = () => {
// ...기존 내용
const onSubmit = async (e: ChangeEvent<HTMLFormElement>) => {
e.preventDefault();
await signInWithEmailAndPassword(firebaseAuth, email, password)
.then((userCredential) => {
const user = userCredential.user;
console.log(user);
navigate("/");
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.warn(`${errorCode} = ${errorMessage}`);
});
};
// .. return 부분
}
📌 Firebase 공식 문서 - 이메일 주소와 비밀번호로 사용자 로그인
이제 이메일 / 비밀번호를 사용하여 로그인을 할 수 있습니다. 로그인 한 회원의 정보를 앱 전반적으로 사용하면 더 편리하게 사용할 수 있을 것 같습니다. 지금부터 앱 전반적으로 유저 정보를 사용하는 방법에 대해 알아보겠습니다.
앱이 실행할 때 Firebase의 onAuthStateChanged
을 사용하여 현재 로그인한 유저의 uid
값을 가져옵니다. 그 다음 Firestore에 저장한 user
정보를 가져와서 userInfo
변수에 넣어두겠습니다. 앞으로 이 userInfo
가 앱 전반적으로 사용하게 될 유저의 정보입니다.
import React, { useEffect, useState } from "react";
// FIREBASE
import { firebaseAuth, fireStoreJob } from "./initFirebase";
import { onAuthStateChanged } from "firebase/auth";
import { collection, query, where, getDocs } from "firebase/firestore";
// COMPONENTS
import { AppRouter } from "./routes/Router";
import "./styles/App.css";
import { UserInterface } from "./interfaces/user.interface";
const App = () => {
const [init, setInit] = useState<boolean>(false);
const [isLogin, setIsLogin] = useState<boolean>(false);
const [userInfo, setUserInfo] = useState<UserInterface | null>(null);
useEffect(() => {
onAuthStateChanged(firebaseAuth, async (user) => {
if (user) {
// 'users' collection에서 유저 정보 가져오기
const q = query(
collection(fireStoreJob, "users"),
where("uid", "==", user.uid)
);
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
const data = doc.data();
// 유저 정보 저장
setUserInfo({
uid: data.uid,
email: data.email,
displayName: data.displayName,
date_created: data.date_created,
});
});
setIsLogin(true);
} else {
setIsLogin(false);
}
setInit(true);
});
}, []);
return (
<>
{" "}
{init ? (
<AppRouter isLogin={isLogin} userInfo={userInfo} />
) : (
"Initializing..."
)}
</>
);
};
export default App;
앱이 실행될 때 로그인한 유저가 있는 지 확인한 후 AppRouter
에 isLogin
값과 userInfo
를 전달하겠습니다.
📌 Firebase 공식 문서 - 현재 로그인한 사용자 가져오기
로그인 여부에 따라 다음과 같이 설정하겠습니다.
로그인 한 경우 : 메인 페이지로 이동 (유저 정보 전달)
로그인 하지 않은 경우 : 로그인 페이지로 이동
import React from "react";
import {BrowserRouter, Routes, Route} from "react-router-dom";
// INTERFACE
import {UserInterface} from "../interfaces/user.interface";
// COMPONENTS
import {SignUp} from "../pages/signUp";
import {Login} from "../pages/login";
import {Main} from "../pages/main";
type AppRouterType = {
isLogin: boolean;
userInfo: UserInterface | null;
};
export const AppRouter = ({isLogin, userInfo}: AppRouterType) => {
return (
<BrowserRouter>
<Routes>
{isLogin ? (
<>
<Route path="/" element={<Main userInfo={userInfo}/>}></Route>
</>
) : (
<>
<Route path="/" element={<Login/>}></Route>
<Route path="/signup" element={<SignUp/>}></Route>
</>
)}
</Routes>
</BrowserRouter>
);
};
로그인 여부에 따라 각 pages에 다른 값을 전달하도록 했습니다. 이제 로그인 한 유저의 정보를 main에서도 받을 수 있습니다. main에서 어떻게 사용할 지는 다음 포스팅에서 자세히 작성하도록 하겠습니다.