node.js / mongoDB 등 서버환경의 복잡한 코드를 이용하지 않고 간단하게 서버환경(오늘은 인증시스템)을 구축할 수 있는 Firebase를 배웠다.
Firebase는 개발자들을 위한 구글의 기능이며 서버를 구축하여 로그인 및 인증, 채팅시스템 까지 기존에 만들었던 카카오톡에 구현하는 것이 다음 단계다.
오늘은 로그인하고 인증하는 것 까지 구현했다.
/* 인증 페이지 */
import React, { useState } from 'react';
import { authService } from 'fbase';
import { createUserWithEmailAndPassword, signInWithEmailAndPassword } from 'firebase/auth';
import { async } from '@firebase/util';
function Auth() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [newAccount, setNewAccount] = useState(true);
const onChange = (e) => {
// console.log(e.target.name);
const {
target: { name, value },
} = e;
/* input이 여러개 있으니까 if문으로 확인 */
if (name === 'email') {
setEmail(value);
} else if (name === 'password') {
setPassword(value);
}
};
/* 서버에서 사용자 정보 데이터를 가져올 때 까지 기다리는 비동기식 처리 async-await 사용 */
const onSubmit = async (e) => {
/* onSubmit은 기본적으로 웹을 새로고침 하기 때문에 preventDefault 사용 */
e.preventDefault();
/* 사용자의 정보(데이터)를 가져오기 성공 할 경우 try문을, 실패한 경우 catch문을 실행 */
try {
let data;
if (newAccount) {
/* create new account */
data = await createUserWithEmailAndPassword(authService, email, password);
} else {
/* log in */
data = await signInWithEmailAndPassword(authService, email, password);
}
// console.log(data);
/* 회원가입을 마친 사용자 정보 */
/* 로그인 성공하면 브라우저의 indexedDB에 데이터를 저장 함 */
} catch (error) {
console.log(error);
}
};
return (
<div>
<form onSubmit={onSubmit}>
<input type='email' placeholder='Email' name='email' value={email} required onChange={onChange} />
<input type='password' placeholder='Password' name='password' value={password} required onChange={onChange} />
<input type='submit' value={newAccount ? 'Create Account' : 'Log in'} />
</form>
<div>
<button>Continue withe Google</button>
<button>Continue withe Github</button>
</div>
</div>
);
}
export default Auth;
Auth 컴포넌트에 Input창 두개와 로그인 버튼을 만들고 입력 받은 값이 생기면 onChange함수가 실행되어 email과 password가 맞는지 확인 하고 그 값의 state를 변경한다.
Submit버튼(Login)을 누르게 되면 onSubmit함수가 실행되어 비동기처리방식 async-await를 이용하여 firebase의 신규유저생성 or 로그인 함수를 사용하여 유저의 정보를 data변수에 할당한다.
import React, { useState, useEffect } from 'react';
import AppRouter from 'Router';
import { authService } from 'fbase';
import { onAuthStateChanged } from 'firebase/auth';
function App() {
const [init, setInit] = useState(false);
const [isLoggedIn, setIsLoggedIn] = useState(false);
/* 특정한 시점에 실행되는 HOOK 함수 */
/* 2번째 state값(배열)이 비어있을 경우 DidMount시점에 함수 실행, state값(배열)이 있을 경우 값이 Update 될때마다 함수 실행 */
useEffect(() => {
onAuthStateChanged(authService, (user) => {
console.log(user);
if (user) {
// User is signed in
setIsLoggedIn(user);
const uid = user.uid;
} else {
// User is signed out
setIsLoggedIn(false);
}
setInit(true);
});
}, []);
console.log(authService.currentUser); // currentUser는 현재 로그인 한 사람 확인 함수
return (
<>
{init ? <AppRouter isLoggedIn={isLoggedIn} /> : 'initializing...'}
<footer>©{new Date().getFullYear()} Twitter</footer>
</>
);
}
export default App;
그 다음, 렌더가 끝난 상태인 ComponentDidMount시점에 useEffect함수를 사용해서 user의 데이터를 가져오는 firebase의 함수를 실행한다.
이 때 IsLoggedIn에 user데이터가 들어가게 되고 따라서 그 값은 true인 상태가 된다.리턴문에 초기값 init이 false일 경우 'initializing...'이 출력 되겠지만 데이터를 받아오고 IsLoggedIn state에 값이 할당되면 true가 되므로 AppRouter에 true 값을 보내 <Home />
컴포넌트를 출력하게 되는 것이다.
/* 구조 분기용 라우터 */
import React, { useState } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Auth from 'routes/Auth';
import Home from 'routes/Home';
function AppRouter({ isLoggedIn }) {
return (
<BrowserRouter>
<Routes>
{/* 로그인이 되었을때랑 안되었을때 화면 구분 */}
{isLoggedIn ? <Route path='/' element={<Home />} /> : <Route path='/' element={<Auth />} />}
{/* isLoggedIn이 true면 <Home /> 호출, false면 <Auth /> 호출 */}
</Routes>
</BrowserRouter>
);
}
export default AppRouter;
강사님이 목이 아프실정도로 여러번 설명해주셨다. 그만큼 중요하고 이해하기 어렵다는 것이라고 생각했다. 지금은 firebase를 사용해서 간단하게 구현했지만 분명 백엔드쪽도 공부해야 할 때가 올 것 같다.
오늘 끝, 내일 안녕