Joon's Space
[React] React + Firebase 연동 (setup, login, profile) (1) 본문
※ nomadcoder twitter clone coding 강의 참고
React + Firebase setup
- React 프로젝트 생성
npx create-react-app 프로젝트명
- firebase 모듈 설치
npm install firebase
- Firebase 프로젝트 생성
src/firebase.js을 생성하여 홈페이지에서 생성된 firebaseConfig를 저장하고 initiallizeApp으로 실행
// src/firebase.js
import * as firebase from "firebase/app";
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
authDomain: process.env.REACT_APP_AUTH_DOMAIN,
projectId: process.env.REACT_APP_PROJECT_ID,
storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGIN_ID,
appId: process.env.REACT_APP_APP_ID
};
export default firebase.initializeApp(firebaseConfig); // index.js에서 사용을 위함
root에 .env 파일을 생성하여 key값을 저장 (git에 업로드되어서 공개되지 않기 위함)
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import firebase from "./firebase";
console.log(firebase);
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
위와 같이 작성 후, App을 실행하면 브라우저 콘솔창에 firebase 정보가 표시되니, 연동이 잘 되었음을 확인.
// components/Router.js
import React, { useState } from "react";
import { HashRouter as Router, Route, Routes } from "react-router-dom";
import Auth from "../routes/Auth";
import Home from "../routes/Home";
const AppRouter = () => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
return (
<Router>
<Routes>
{isLoggedIn ? (
<>
<Route path="/" element={<Home/>}/>
</>
) : (
<Route path="/" element={<Auth/>}/>
)}
</Routes>
</Router>
);
};
export default AppRouter;
react v6 버전으로 넘어 오면서 Route의 부모 요소인 Switch 가 -> Routers로 이름이 변경,
그리고 Route의 exact 옵션이 사라지고 path만 남게됨, component로 사용하지 않고 element 방식으로 사용되어 <Home />, <Auth />처럼 뾰족 괄호도 넣어 줘야 한다.
Authentication
firebase에서는 authentication 기능도 제공하는데 firebase/auth 에서 getAuth() 함수를 import 한다.
// fbase.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
authDomain: process.env.REACT_APP_AUTH_DOMAIN,
projectId: process.env.REACT_APP_PROJECT_ID,
storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGIN_ID,
appId: process.env.REACT_APP_APP_ID
};
initializeApp(firebaseConfig); // index.js에서 사용을 위함
export const authService = getAuth();
fbase.js 를 다음과 같이 수정해 준다. 앞으로 getAuth 기능을 자주 사용할 것이기 때문에, authService로 선언하여 사용한다.(export)
console.log(authService.currentUser)
App.js 에서 getAuth()함수의 currentUser를 보면 반환하면 아직 아무 유저도 인증되지 않았기 때문에 null값을 반환한다. 이 값을 isLoggedIn state값 변수로 사용할 수 있다.
Google, Github 로그인 생성
firebase 콘솔에서 authentication에 가면 다음과 같이 로그인에 사용할 플랫폼을 추가할 수 있다.
계정 생성, 로그인
firebase auth의 createUserWithEmailAndPassword, signInWithEmailAndPassword 함수를 사용
- createUserWithEmailAndPassword( getAuth(), email:string, password:string) : Promise <UserCredential>
- signInWithEmailAndPassword( getAuth(), email: string, password: string) : Promise <UserCrediential>
// Auth.js
const onSubmit = async(event) => {
event.preventDefault();
try {
let data;
const auth = getAuth();
if(newAccount) {
// create account
const data = await createUserWithEmailAndPassword(auth, email, password);
} else {
// log in
const data = await signInWithEmailAndPassword(auth, email, password);
}
console.log(data);
} catch (error) {
console.log(error);
}
}
로그인 상태 확인
firebase/auth 의 onAuthStateChanged() 함수를 통해서 user가 존재하면 isLoggedIn 값을 true, 존재하지 않은 경우 isLoggedIn 값을 false로 변경한다.
이때 useEffect() 함수를 사용하고, 컴포넌트가 처음 로딩될 때만 확인하면 되기 때문에, 두 번째 deps 파라미터는 비워준다.
(두 번째 deps 파라미터에 값을 넣으면 입력한 값이 변경될 때마다, useEffect에서 첫 번째 파라미터인 함수가 실행된다. )
// App.js
const [isLoggedIn, setIsLoggedIn] = useState(false);
// 컴포넌트가 처음시작될 때 확인만 하는 작업이니 2번째 파라미터는 비워준다.
useEffect(() => {
onAuthStateChanged(authService, (user) => {
if(user) {
// logged in
setIsLoggedIn(true);
} else {
// logged out
setIsLoggedIn(false);
}
setInit(true);
});
}, [])
그리고 로그인, 계정생성을 모두 하기 위해서 toggle버튼을 생성한다.
// Auth.js
const [newAccount, setNewAccount] = useState(true);
const toggleAccount = () => setNewAccount((prev) => !prev);
return (
<span onClick={toggleAccount}>{newAccount ? "Log in " : "Create Account"}</span>
)
로그인을 하기 위해선 newAccount 값을 false, 계정 생성을 하기 위해선 newAccount 값을 true로 변경.
Social Login
firebase/auth의 signInWIthPopup 함수를 사용한다. 이때 필요한 파라미터는 auth값과, provider가 필요한데, platform마다 다른 provider를 사용하기 때문에, 각각 provider객체를 새로 생성해 준다.
// Auth.js
const onSocialClick = async(event) => {
const {
target:{name},
} = event;
let provider;
const auth = getAuth();
if(name === 'google') {
provider = new GoogleAuthProvider();
} else if(name === 'github') {
provider = new GithubAuthProvider();
}
await signInWithPopup(auth, provider);
}
return(
<button onClick={onSocialClick} name="google">Continue with Google</button>
<button onClick={onSocialClick} name="github">Continue with Github</button>
)
Logout
profile 화면을 추가하고, Navigation 컴포넌트를 추가한다.
const Navigation = () => <nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/profile">My Profile</Link>
</li>
</ul>
</nav>
Link 컴포넌트를 사용하여 해당 url로 이동시켜주는 링크를 보여준다.
Profile
(<Route path="/profile" element={<Profile />}/>)
Router에 profile을 렌더링하는 Route도 추가한다.
const Profile = () => {
const auth = getAuth();
const navigate = useNavigate();
const onLogOutClick = () => {
signOut(auth);
navigate('/');
}
return <>
<button onClick={onLogOutClick}>Log Out</button>
</>
}
로그아웃 버튼을 프로파일 컴포넌트에 추가하며, useNavigate를 사용하여 Log Out 버튼을 클릭했을 때 onClick함수로 signOut() 함수가 실행되고, "/" 홈 화면으로 다시 redirect가 되게 한다.
'Web > React' 카테고리의 다른 글
[React] React + Firebase 연동 (query, update) (3) (0) | 2022.03.01 |
---|---|
[React] React + Firebase 연동 (Cloud Firestore) (2) (0) | 2022.02.22 |
[React] authentication front-end (tailwindcss로 페이지 구현) (2) (0) | 2021.08.01 |
[React] authentication front-end (log-in 페이지 ) (1) (0) | 2021.08.01 |
[React] authentication front-end (log-in, create account, etc) (0) | 2021.07.28 |