-
[Firebase] React (Typescript) 에서 Firebase auth를 사용한 로그인 기능 구현front-end 2021. 10. 12. 21:52
React 프로젝트에서 Firebase를 사용하여 로그인 기능을 구현해 볼 것이다. 생각보다 간단하다.
로그인 기능은 민감한 기술이지만, Firebase를 이용하여 인증을 추가하는 것이 매우 간단하다.
이번 포스팅에서는
- React, React-hook
- Typescript
에 대해 알고 있다고 생각하여 자세한 내용은 생략하여 진행할 예정이니 참고바란다.
프로젝트 생성하기
프로젝트를 생성할 원하는 위치에 폴더를 생성하자. 필자는 react-typescript-login으로 진행하겠다.
폴더가 생성되었으면 프로젝트를 생성하자. 앞서 말씀드렸다 시피 react와 typescript로 프로젝트를 생성할 예정이므로 create-react-app을 활용하여 빠르게 프로젝트를 생성해보자.
더보기npx create-react-app react-typescript-login --template typescript
폴더명이 react-typescript-login이라는 폴더에 프로젝트가 생성되었다. 폴더에 들어가서 모듈들을 설치받은 후 프로젝트를 실행하자
더보기npm run start
react-typescript를 이용해서 프로젝트가 실행되는 것을 확인할수 있다.
실행되는 것을 확인했다면, 사용하지 않을 파일들은 제거하자.
- reportWebVitals.js
- logo.svg
- index.css
- setupTests.ts
- App.css
- App.test.tsx
//App.tsx import React from "react"; function App() { return <div className="App">React - typescript - login</div>; } export default App;
// index.tsx import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById("root") );
앞서 말한데로 TypeScript를 사용할 예정이므로 Typescript를 추가하자
더보기npm install --save firebase
여기까지 모든 작업이 완료되었다면. 터미널에서 프로젝트를 실행해보자.
더보기npm run start
Firebase Setup
Firebase를 이용하여 로그인을 구현하기 위해서 먼저 Firebase에서 세팅이 필요하다. (아무나 사용할 수 있는 게 아니니까) Firebase의 설정은 생각보다 쉽다. 잘 따라오기면 하면 문제 없을 될 것이다. 가장 먼저 Firebase를 사용하기 위해서는 Google 계정이 필요하다. 계정이 없는 경우 빨리 계정을 만들고 오자. 만들었다면 아래의 링크에 접속하자.
https://console.firebase.google.com/
링크에 들어가면 프로젝트 추가, 기존에 프로젝트가 하나도 없는 경우에는 프로젝트 생성 버튼이 있다.
추가 또는 생성 버튼을 클릭하자.
프로젝트 이름을 생성하고, 게속버튼을 누르고 프로젝트를 만들자. 생성이 완료되면 다음과 같은 페이지가 나온다
좌측 상단의 Authentication을 클릭 후 우측에 나오는 페이지의 시작하기 버튼을 클릭하자.
기본 제공업체의 이메일/비밀번호 버튼을 클릭하자, 추가 제공업체에서 제공하는 구글 로그인, fb로그인 등은 추후에 다뤄볼 예정이다.
비밀번호가 없는 로그인 토글은 꺼주자. 비밀번호가 없는 로그인도 지원한다는 점만 알아두자! firebase는 정말 최고다.
지금까지 fireabse 로그인 프리 셋팅을 완료했다.
이제 firebase에 내 app(web)을 추가하자.
우측 상단에 프로젝트 개요를 클릭하면, 우측 화면에 추가할 앱이 나온다. 우리는 웹으로 만들 예정이므로 </> 버튼을 클릭하여 생성하자.
위 그림과 같은 입력 창이 나온다. 앱 닉네임을 입력 후 앱을 등록해주자. Firebase 호스팅도 가능한 점 알고 넘어가자. 필자는 github page를 이용해 호스팅 할 것이므로 체크하지 않았다. 앱 등록이 완료되면 제품의 SDK, Config창을 보여준다.
여기까지 왔으면 거의 다왔다. 이제는 firebase를 우리 프로젝트에 복사해서 넣어주자.
firebase.tsx을 생성 후 위 파일을 복사한 후 넣어주자. firebase의 auth기능 만 사용할 예정이므로 약간 수정하자.
// Import the functions you need from the SDKs you need import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; // Your web app's Firebase configuration // For Firebase JS SDK v7.20.0 and later, measurementId is optional const firebaseConfig = { apiKey: "AIzaSyBRisZvaH9vvgzM63oez-iTG1RxkdYkCfU", authDomain: "react-firebase-login-284af.firebaseapp.com", projectId: "react-firebase-login-284af", storageBucket: "react-firebase-login-284af.appspot.com", messagingSenderId: "324187884252", appId: "1:324187884252:web:51a90cf764935df2158219", measurementId: "G-Y6019Z4B4M" }; // Initialize Firebase export const app = initializeApp(firebaseConfig); export const auth = getAuth(app);
getAuth() [https://firebase.google.com/docs/reference/js/auth.md?authuser=0#getauth] 를 사용해 auth 정보를 가져오고, export 해주자. 제대로 연결되었는지 확인을 위해서 index.tsx 파일에 넣어 실행해보자
import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; import { auth } from "./firebase"; console.log(auth); ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById("root") );
콘솔 창을 열어보니 특별한 문제없이 잘 연결된 것을 확인할 수 있다.
이제 우리는 firebase 세팅이 완료되었고, 프로젝트에서 사용할 수 있다.
이제 본격적으로 React에서 로그인 기능을 구현해보도록 하자
로그인, 로그아웃 상태 감지하기
firebase에서 로그인, 로그아웃 상태를 감지하는 함수(onAuthStateChanged)를 제공하고 있다. 이 함수는 함수명처럼 인증의 상태의 변화를 감지하는 함수이다. 로그인, 로그아웃 시 동작하는 함수라고 생각하면 된다. 자세한 건 공식 문서를 살펴보자. https://firebase.google.com/docs/reference/js/auth.md?authuser=0#onauthstatechanged
로그인 정보는 모든 컨포넌트에서 사용 가능하기 때문에, context api를 사용하여 언제 어디서든 사용할 수 있도록 구현해보자. 먼저 context/authContext.tsx를 생성하자.
// authContext.tsx import React from "react"; import { User } from "@firebase/auth"; export const AuthContext = React.createContext<User | null>(null);
createContext()를 사용하여 firebase에서 제공하는 User 객체를 넘겨주는 Context를 생성했다. 다음으로 Provider을 생성하자 provider/authProvider.tsx 에서 유저 정보를 내려줘야 한다. onAuthStateChanged를 실행하고 useEffect를 사용해 변경을 감지하자. 아래와 같은 코드가 된다.
//authProvider.tsx import { User } from "@firebase/auth"; import { useEffect, useState } from "react"; import { AuthContext } from "../context/authContext"; import { auth } from "../firebase"; const AuthProvider: React.FC = ({ children }) => { const [user, setUser] = useState<User | null>(null); useEffect(() => { const subscribe = auth.onAuthStateChanged(fbUser => { console.log(`구독 실행`, fbUser); setUser(fbUser); }); return subscribe; }, []); return <AuthContext.Provider value={user}>{children}</AuthContext.Provider>; }; export default AuthProvider;
이제 AuthProvider를 사용할수 있도록 index.tsx 파일에 넣어주자.
// index.tsx import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; import AuthProvider from "./provider/authProvider"; ReactDOM.render( <React.StrictMode> <AuthProvider> <App /> </AuthProvider> </React.StrictMode>, document.getElementById("root") );
useContext 훅을 사용하여 user의 값을 어디서든 불러올 수 있다.
// App.tsx import React, { useContext } from "react"; import { AuthContext } from "./context/authContext"; function App() { const userInfo = useContext(AuthContext); console.log(userInfo); // 로그인이 아닌경우 null return <div className="App">React - typescript - login</div>; } export default App;
React 로그인, 회원가입 입력 폼 만들기
회원가입 기능 구현
로그인 전에 먼저 회원가입이 가능해야 로그인이 가능한것쯤은 모두가 알고 있을 것이다. 이번에는 회원가입 기능을 간단하게 구현해보자. 유저에게 email, password를 입력받을 input tag를 생성하고, 로그인인지 회원가입인지를 구별해주는 상태 (isCreate)를 만들어 분기하자.
// App.tsx import React, { MouseEventHandler, useContext, useState } from "react"; import { AuthContext } from "./context/authContext"; function App() { const userInfo = useContext(AuthContext); const [email, setEmail] = useState(""); const [pwd, setPwd] = useState(""); const [isCreate, setIsCreate] = useState(false); const handleEmail = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setEmail(e.target.value); }; const handlePwd = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setPwd(e.target.value); }; const handleClickCreate = (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); setIsCreate(pre => !pre); }; return ( <div className="App"> <form> <input type="email" name="email" onChange={handleEmail} value={email} /> <input type="password" name="pwd" onChange={handlePwd} value={pwd} /> <button type="button"> {isCreate ? "만들기" : "로그인"}</button> <button type="button" onClick={handleClickCreate}> {isCreate ? "취소" : "회원가입"} </button> </form> </div> ); } export default App;
Firebase 회원가입
지금까지 입력 폼은 다만들었다. 이제 서버에 전달해주기만 하면 된다. firebase에서 회원가입 관련 함수를 찾으면 쉽게 발견할 수 있는 함수가 있다. createUserWithemailandpassword() 함수로 https://firebase.google.com/docs/reference/js/auth.md?authuser=0#createuserwithemailandpassword
firebase에서 제공하는 함수이다. 자세한건 위 링크를 참조해서 볼 수 있다. firebase에서 제공하는 회원가입 함수를 이용해서 구현해보자.
// App.tsx import { createUserWithEmailAndPassword } from "@firebase/auth"; import React, { MouseEventHandler, useContext, useState } from "react"; import { AuthContext } from "./context/authContext"; import { auth } from "./firebase"; function App() { const userInfo = useContext(AuthContext); const [email, setEmail] = useState(""); const [pwd, setPwd] = useState(""); const [isCreate, setIsCreate] = useState(false); const handleEmail = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setEmail(e.target.value); }; const handlePwd = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setPwd(e.target.value); }; const handleClickCreate = (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); setIsCreate(pre => !pre); }; const handleSubit = (e: React.FormEvent) => { e.preventDefault(); // 회원 가입일때 if (isCreate) { createUserWithEmailAndPassword(auth, email, pwd) .then(() => { alert("회원가입 성공"); }) .catch(e => { alert(e); }); } }; return ( <div className="App"> <form onSubmit={handleSubit}> <input type="email" name="email" onChange={handleEmail} value={email} /> <input type="password" name="pwd" onChange={handlePwd} value={pwd} /> <button type="submit"> {isCreate ? "만들기" : "로그인"}</button> <button type="button" onClick={handleClickCreate}> {isCreate ? "취소" : "회원가입"} </button> </form> </div> ); } export default App;
회원가입 완료되는 문구가 나온다. firebase 즉 서버에도 데이터가 생성되었는지 확인해보자
서버에도 계정이 생성된걸 확인할 수 있다.
로그인 기능 구현
이제 본격적으로 로그인 기능을 구현할수 있다. 로그인 기능도 firebase에서 제공한다. signinwithemailandpassword로 mail과 password를 이용해서 구현한다. 자세한 건 링크해서 확인 가능하다. 로그인에 성공하면 로그인 상태를 구독하고 있는 provider의 useEffect가 실행하여 user 값을 갱신하여 내려준다. user값이 있으면 로그인이 된 상태이며, user값이 없으면 비로그인 상태임을 알 수 있다. 이제 코드로 구현해보자.
https://firebase.google.com/docs/reference/js/auth.md?authuser=0#signinwithemailandpassword// app.tsx import { createUserWithEmailAndPassword, signInWithEmailAndPassword } from "@firebase/auth"; import React, { MouseEventHandler, useContext, useState } from "react"; import { AuthContext } from "./context/authContext"; import { auth } from "./firebase"; function App() { const userInfo = useContext(AuthContext); const [email, setEmail] = useState(""); const [pwd, setPwd] = useState(""); const [isCreate, setIsCreate] = useState(false); const handleEmail = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setEmail(e.target.value); }; const handlePwd = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setPwd(e.target.value); }; const handleClickCreate = (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); setIsCreate(pre => !pre); }; const handleSubit = (e: React.FormEvent) => { e.preventDefault(); // 회원 가입일때 if (isCreate) { createUserWithEmailAndPassword(auth, email, pwd) .then(() => { alert("회원가입 성공"); }) .catch(e => { alert(e); }); } else { signInWithEmailAndPassword(auth, email, pwd) .then(() => { alert("로그인 성공"); }) .catch(e => { alert(e); }); } }; return ( <div className="App"> {userInfo ? ( <div> 로그인 상태입니다 </div> ) : ( <form onSubmit={handleSubit}> <input type="email" name="email" onChange={handleEmail} value={email} /> <input type="password" name="pwd" onChange={handlePwd} value={pwd} /> <button type="submit"> {isCreate ? "만들기" : "로그인"}</button> <button type="button" onClick={handleClickCreate}> {isCreate ? "취소" : "회원가입"} </button> </form> )} </div> ); } export default App;
Firebase에서 제공되는 함수가 있어서 구현하기가 매우 간편하다.
마지막으로 로그아웃 기능을 구현하자.
로그아웃 기능 구현
로그아웃 기능 또한 firebase에서 제공하기 때문에 아주 간단하게 구현할수 있다. 로그아웃을 도와주는 함수는 signOut으로 공식 홈페이지에서 확인 가능하다. https://firebase.google.com/docs/reference/js/auth.md?authuser=0#signout
import { createUserWithEmailAndPassword, signInWithEmailAndPassword, signOut } from "@firebase/auth"; import React, { MouseEventHandler, useContext, useState } from "react"; import { AuthContext } from "./context/authContext"; import { auth } from "./firebase"; function App() { const userInfo = useContext(AuthContext); const [email, setEmail] = useState(""); const [pwd, setPwd] = useState(""); const [isCreate, setIsCreate] = useState(false); const handleEmail = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setEmail(e.target.value); }; const handlePwd = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setPwd(e.target.value); }; const handleClickCreate = (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); setIsCreate(pre => !pre); }; const handleSubit = (e: React.FormEvent) => { e.preventDefault(); // 회원 가입일때 if (isCreate) { createUserWithEmailAndPassword(auth, email, pwd) .then(() => { alert("회원가입 성공"); }) .catch(e => { alert(e); }); } else { signInWithEmailAndPassword(auth, email, pwd) .then(() => { alert("로그인 성공"); }) .catch(e => { alert(e); }); } }; // 로그아웃 기능 const handleLogout = () => { signOut(auth); }; return ( <div className="App"> {userInfo ? ( <div> 로그인 상태입니다 <button onClick={handleLogout}> 로그아웃 </button> </div> ) : ( <form onSubmit={handleSubit}> <input type="email" name="email" onChange={handleEmail} value={email} /> <input type="password" name="pwd" onChange={handlePwd} value={pwd} /> <button type="submit"> {isCreate ? "만들기" : "로그인"}</button> <button type="button" onClick={handleClickCreate}> {isCreate ? "취소" : "회원가입"} </button> </form> )} </div> ); } export default App;
로그아웃 버튼을 클릭하면, 다시 로그인 화면으로 돌아오는 것을 확인할수있다.
정리
이번시간에 firebase, typescript, react를 이용하여 로그인 기능을 구현해보았다. 로그인 기능이 민감하고 쉽지 않은 주제이지만, firebase에서 모든 로그인 기능을 제공하고 있기 때문에 쉽게 구현해볼 수 있었다. 다음 포스팅에서는 구글 로그인, 애플 로그인, 등 sns 로그인을 구현해보는 시간을 가져보자.
728x90'front-end' 카테고리의 다른 글
FE개발자 k8s를 알아야하는가? (0) 2024.01.29 HTML에서 JavaScript 변수 다루기: let vs var vs window (0) 2024.01.24 컴파일러? 번들러? (0) 2021.11.25 gulp? browserify? (0) 2020.02.17 [GraphQL] 개념 이해하기 (0) 2019.10.29