JS' 공부흔적

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (2) - Firebase를 사용하여 이메일 로그인 구현하기 본문

Firebase

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (2) - Firebase를 사용하여 이메일 로그인 구현하기

이준수 2023. 1. 28. 04:31
 

[Firebase] Firebase, React를 사용한 간단한 프로그램 만들기 (1) - Firebase와 React 연동하기

앞으로 4편에 걸쳐서 파이어베이스와 리액트를 사용하여 아주아주 간단한 프로그램을 만들어보는 글을 작성할 예정이다. 이번 글에서는 파이어베이스와 리액트를 연동하는 것에 대해 다루겠다

2junsu.tistory.com

 

이전 글에 이어서 이번 글에서는 이메일을 사용한 회원가입 및 로그인 기능을 구현해 보자. 공식문서 링크는 여기


기본 설정

우선 전에 만들었던 test 프로젝트를 눌러서 콘솔로 이동한 후에 Authentication을 클릭하고, 이메일/비밀번호를 클릭한다.

 

 

그리고 이메일/비밀번호 사용 설정에 체크한 후 저장을 누른다.

 

 

이제 이메일로 회원가입/로그인을 구현하기 위한 준비는 끝났다.


회원가입 구현하기

먼저 회원가입을 구현하기 위해서는 createUserWithEmailAndPassword 라는 메서드를 사용할 것이다.

 

지난번에 만든 test 프로젝트를 열어서 App.js에 아래와 같이 인풋창과 버튼을 만들고, useState로 상태값을 관리해 주는 간단한 코드를 작성한다.

// App.js

import React, { useState } from "react";
import { createUserWithEmailAndPassword, getAuth } from "firebase/auth";
import { app } from "./firebase-config";

const App = () => {
  const [form, setForm] = useState({ email: "", password: "" });
  const { email, password } = form; // 구조 분해 할당

  const onChange = (e) => {
    const changed = {
      ...form,
      [e.target.name]: e.target.value,
    };

    setForm(changed);
  };

  const doSignup = () => {
    ...
  };

  return (
    <div>
      <input name="email" placeholder="이메일" type="email" onChange={onChange} />
      <input name="password" placeholder="비밀번호" type="password" onChange={onChange} />
      <button onClick={doSignup}>회원 가입</button>
    </div>
  );
};

export default App;

doSignup 함수에서 createUserWithEmailAndPassword가 사용되는데, 이때 아래와 같이 auth, email, password 정보를 받아준다. 또한 비동기적으로 동작하기 때문에 async await도 함께 사용했다.

const doSignup = async () => {
    const auth = getAuth();
    try {
      const userCredential = await createUserWithEmailAndPassword(
        auth,
        email,
        password
      );
      console.log(userCredential);
    } catch (error) {
      console.error(error.code);
    }
  };

공식문서를 참고하여 .then과 async await 정도의 차이만 존재하는데, 이때 위처럼 코드를 작성한 후에 실행해 보면 아래와 같은 에러가 뜰 것이다.

 

728x90

이에 대해서 찾아보니 getAuth() 내에 우리가 firebase-config.js에서 설정했던 app 정보를 넣어줘야 한다는 걸 알았다. 따라서 firebase-config.js의 app을 가져다 쓸 수 있게 처리해 준다.

// firebase-config.js

...

export const app = initializeApp(firebaseConfig);
// App.js

import { app } from "./firebase-config";

...

const doSignup = async () => {
    const auth = getAuth(app);
    ...
  };

이렇게 작성해 주면 에러가 사라진다.

 

추가로 고려해야 할 부분은 회원 가입에 문제가 생겼을 경우인데, 이때 아래 3가지의 에러가 발생할 수 있다.

 

 

이렇게 에러 처리까지 하고 나서 정보를 맞게 입력했다면 회원 가입에 성공할 수 있다. 파이어베이스에서 제공하는 회원 가입 api는 가입이 완료되면 자동으로 로그인까지 해준다. 따라서 이때 로그에 찍히는 userCredential 정보는 로그인 시에 얻을 수 있는 정보들이다.

 

 

진짜로 회원가입이 되었는지 확인하고 싶다면 파이어베이스 콘솔에서 Authentication의 Users 탭을 확인하면 된다.

 

 

이렇게 잘 뜬다면 회원가입을 성공적으로 구현한 것이다!


로그인 구현하기

이제는 방금 가입한 계정으로 로그인을 시도해 보자. 로그인을 구현할 때는 signInWithEmailAndPassword 메서드를 사용한다. 이 메서드도 회원가입 구현 때 사용했던 createUserWithEmailAndPassword와 같이 auth, email, password 정보를 받아준다.

 

그전에 react-router-dom을 설치하여 로그인 페이지와 회원가입 페이지를 분리할 것이다.

npm i react-router-dom

 

루트 경로에 src 폴더를 만들고 그 안에 Login.jsx와 Signup.jsx 파일을 만든 뒤, Signup.jsx에 아까 작성한 회원가입 코드를 옮긴다. 그리고 App.js는 아래와 같이 수정한다.

// App.js

import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Login from "./pages/Login";
import Signup from "./pages/Signup";

const App = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Login />} />
        <Route path="/signup" element={<Signup />} />
      </Routes>
    </BrowserRouter>
  );
};

export default App;

 

로그인 코드는 signInWithEmailAndPassword 메소드를 사용하여 아래와 같이 작성한다. 그리고 회원가입 페이지로 넘어가기 위한 버튼도 추가로 만들어준다.

// Login.jsx

import React, { useState } from "react";
import { signInWithEmailAndPassword, getAuth } from "firebase/auth";
import { app } from "../firebase-config";
import { Link } from "react-router-dom";

const Login = () => {
  const [form, setForm] = useState({ email: "", password: "" });
  const { email, password } = form; // 구조 분해 할당

  const onChange = (e) => {
    const changed = {
      ...form,
      [e.target.name]: e.target.value,
    };

    setForm(changed);
  };

  const doLogin = async () => {
    const auth = getAuth(app);
    try {
      const userCredential = await signInWithEmailAndPassword(
        auth,
        email,
        password
      );
      console.log(userCredential);
    } catch (error) {
      console.error(error.code);
      switch (error.code) {
        ...
    }
  };

  return (
    <div>
      <input
        name="email"
        placeholder="이메일"
        type="email"
        onChange={onChange}
      />
      <input
        name="password"
        placeholder="비밀번호"
        type="password"
        onChange={onChange}
      />
      <button onClick={doLogin}>로그인</button>
      <Link to="/signup">
        <button>회원가입하기</button>
      </Link>
    </div>
  );
};

export default Login;

 

회원가입 구현할 때의 코드와 거의 유사하고 메서드만 다르다. 또 다른 점은 에러 코드인데, 로그인 시에 고려해야 할 에러는 아래 3가지이다.

 

 

에러 처리까지 한 후에 아까 가입한 계정으로 로그인을 시도해 보자. 정보를 제대로 입력했다면 회원가입 시에 찍혔던 로그와 동일한 로그가 찍힐 것이다.


토큰 유무에 따른 리다이렉팅 하기

로그인을 하게 되면 찍히는 로그 중에서 accessToken을 활용해 보자. accessToken은 로그인을 성공했다는 의미로 넘겨주는 정보이다. 이를 가지고 있으면 로그인 상태임을 나타낸다. 따라서 accessToken을 가지고 있다면 메인 페이지로, 그렇지 않다면 로그인 페이지로 리다이렉팅 하는 기능을 구현해 보자.

 

우선, 연습하는 과정이므로 토큰 정보를 그냥 localStorage에 저장하겠다. 또한, 다음 글에서 다룰 Firestore에서 사용하기 위해 uid도 같이 저장하겠다. doLogin 함수와 doSignup 함수에서 로그가 찍히는 부분에 아래 코드를 추가한다.

localStorage.setItem(
        "userInfo",
        JSON.stringify({
          // getIdToken()은 promise가 넘어오므로 await을 앞에 써야한다.
          accessToken: await userCredential.user.getIdToken(),
          uid: userCredential.user.uid, // Firestore에서 쓰기 위한 uid
        })
      );
      
 window.location.reload(); // 리다이렉팅을 구현할 때 정보를 저장하고 새로고침함으로써 결과가 반영되기 위함

 

추가한 후에 로그인을 해보면 개발자 도구 - Application에서 Local Storage에 값이 잘 저장된 걸 볼 수 있다.

 

 

이제 accessToken 유무에 따라 어떤 페이지를 보여줄지 구현하면 된다.

 

pages 폴더에 Main.jsx 파일을 생성하고 App.js를 아래와 같이 수정하자.

// Main.jsx

import React from 'react';

const Main = () => {
    return (
        <div>
            Main
            <button onClick={()=>{localStorage.removeItem('userInfo')}}>remove</button>
        </div>
    );
};

export default Main;
// App.js

import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Login from "./pages/Login";
import Main from "./pages/Main";
import Signup from "./pages/Signup";

const App = () => {
  const accessToken = JSON.parse(localStorage.getItem("userInfo"))?.accessToken;
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={accessToken ? <Main /> : <Login />} />
        <Route path="/signup" element={<Signup />} />
      </Routes>
    </BrowserRouter>
  );
};

export default App;

 

이렇게 작성해 주면 아래와 같은 결과를 얻을 수 있다.

SMALL

이렇게 파이어베이스를 사용하여 이메일 회원가입과 로그인을 구현해 보았다.

 

다음 글에서는 파이어베이스에서 제공하는 2가지 데이터베이스 중에서 Firestore를 간단하게 다뤄볼 것이다.

 

 

728x90
반응형