본문 바로가기

STUDY/Firebase

Firebase | 채팅 웹 애플리케이션 (4) 회원가입/로그인

1. firebase.js 수정

authentication과 database 함수를 export 

// src/services/firebase.js

firebase.initializeApp(firebaseConfig);

export const auth = firebase.auth;
export const database = firebase.database();

 

2. auth.js 파일 생성 및 작성

함수명만 봐도 알 수 있듯, signUp은 이메일과 비밀번호를 이용한 회원가입이고 signIn은 이메일과 비밀번호를 이용한 로그인 처리임

// src/helpers/auth.js

import { auth } from "../services/firebase";

export function signUp(email, password) {
  return auth().createUserWithEmailAndPassword(email, password);
}

export function signIn(email, password) {
  return auth().signInWithEmailAndPassword(email, password);
}

 

3. SignUp.js 컴포넌트 만들기

위에서 export해준 signUp 메서드를 import 해줌

// src/pages/SignUp.js

import React, { useState } from "react";
import { Link } from "react-router-dom";
import { signUp } from "../helpers/auth";

 

form태그로 휘리릭 작성

정식 런칭할 서비스가 아니니까 그냥 비밀번호 한 번만 입력받겠어요..

멋진 회원가입 페이지

 

✔️이메일과 비밀번호를 담을 state를 생성

✔️handleOnChange - state값을 변경해주는 메서드

✔️handleOnSubmit - 회원가입 버튼을 클릭했을 때 firebase 회원가입 처리를 실행할 메서드

function SignUp() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleOnChange = (e) => {
    const type = e.target.name;
    if (type === "email") {
      setEmail(e.target.value);
    } else if (type === "password") {
      setPassword(e.target.value);
    }
  };

  const handleOnSubmit = async (e) => {
    e.preventDefault();
    if (email !== "" && password !== "") {
      try {
        await signUp(email, password);
      } catch (error) {
        console.log(error);
      }
    }
  };

  return (
    <div className="sign-container">
      <div className="sign-up-wrap">
        <h1 className="title">회원가입</h1>
        <form className="sign-up-form" onSubmit={handleOnSubmit}>
          <div>
            <input
              type="email"
              placeholder="이메일을 입력하세요."
              name="email"
              value={email}
              onChange={handleOnChange}
            />
          </div>
          <div>
            <input
              type="password"
              placeholder="비밀번호를 입력하세요."
              name="password"
              value={password}
              onChange={handleOnChange}
            />
          </div>
          <div>
            <button type="submit">회원가입</button>
          </div>
        </form>
        <hr></hr>
        <p>
          이미 회원이신가? <Link to="/login">로그인</Link>
        </p>
      </div>
    </div>
  );
}

export default SignUp;

회원가입 테스트!!
Users목록에 해당 회원이 추가되었다!

 

4. Login.js 컴포넌트 만들기

로그인도 회원가입과 거의 동일함

회원가입 페이지와는 다른 분위기의 로그인 페이지

 

로그인 컴포넌트에서는 signIn 메서드를..

// src/pages/Login.js

import React, { useState } from "react";
import { Link } from "react-router-dom";
import { signIn } from "../helpers/auth";

 

회원가입과 다른 점은.. handleOnSubmit에서 signIn으로 바꿔주는 것 입니다..

  const handleOnSubmit = async (e) => {
    e.preventDefault();
    if (email !== "" && password !== "") {
      try {
        await signIn(email, password).then((res) => console.log(res));
      } catch (error) {
        console.log(error);
      }
    }
  };

 

Login.js 전체코드 👇

더보기
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { signIn } from "../helpers/auth";

function Login() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleOnChange = (e) => {
    const type = e.target.name;
    if (type === "email") {
      setEmail(e.target.value);
    } else if (type === "password") {
      setPassword(e.target.value);
    }
  };

  const handleOnSubmit = async (e) => {
    e.preventDefault();
    if (email !== "" && password !== "") {
      try {
        await signIn(email, password).then((res) => console.log(res));
      } catch (error) {
        console.log(error);
      }
    }
  };

  return (
    <div className="sign-container">
      <div className="sign-wrap">
        <h1 className="title">로그인</h1>
        <form className="sign-form" onSubmit={handleOnSubmit}>
          <div>
            <input
              type="email"
              placeholder="이메일을 입력하세요."
              name="email"
              value={email}
              onChange={handleOnChange}
            />
          </div>
          <div>
            <input
              type="password"
              placeholder="비밀번호를 입력하세요."
              name="password"
              value={password}
              onChange={handleOnChange}
            />
          </div>
          <div>
            <button type="submit">로그인</button>
          </div>
        </form>
        <hr></hr>
        <p>
          회원이 아니신가? <Link to="/signup">회원가입</Link>
        </p>
      </div>
    </div>
  );
}

export default Login;

 

5. App.js 수정

로그인에 성공했을 경우 /chat으로 페이지가 이동되도록!

 

import { auth } from "./services/firebase";

 

우선 user값을 받아 상태값을 변경할 리듀서를 작성

function reducer(state, action) {
  switch (action.type) {
    case "GET_USER":
      return { ...state, authenticated: action.result };
    default:
      return state;
  }
}

 

useEffect를 이용해 user값을 갱신하는 dispatch실행

useEffect(() => {
    auth().onAuthStateChanged((user) => {
      console.log("App.js useEffect user? ", user);
      if (user) {
        dispatch({
          type: "GET_USER",
          result: true,
        });
      } else {
        dispatch({
          type: "GET_USER",
          result: false,
        });
      }
    });
  }, []);

 

로그인에 성공하면 채팅 페이지로 이동한다.

App.js 전체 코드 👇

더보기
import React, { useReducer, useEffect } from "react";
import { BrowserRouter as Router, Switch } from "react-router-dom";
import { auth } from "./services/firebase";

import "./styles.css";

import Chat from "./pages/Chat";
import SignUp from "./pages/SignUp";
import Login from "./pages/Login";
import PublicRoute from "./components/PublicRoute";
import PrivateRoute from "./components/PrivateRoute";

const initialState = {
  authenticated: false,
  loading: true,
};

function reducer(state, action) {
  switch (action.type) {
    case "GET_USER":
      return { ...state, authenticated: action.result };
    default:
      return state;
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, initialState);
  const { authenticated } = state;
  
  useEffect(() => {
    auth().onAuthStateChanged((user) => {
      if (user) {
        dispatch({
          type: "GET_USER",
          result: true,
        });
      } else {
        dispatch({
          type: "GET_USER",
          result: false,
        });
      }
    });
  }, []);
  
  return (
    <Router>
      <Switch>
        <PrivateRoute
          path="/chat"
          authenticated={authenticated}
          component={Chat}
        />
        <PublicRoute
          path="/signup"
          authenticated={authenticated}
          component={SignUp}
        />
        <PublicRoute
          path={["/", "/login"]}
          authenticated={authenticated}
          component={Login}
        />
      </Switch>
    </Router>
  );
}

export default App;

6. 로그아웃

로그아웃은 더 간단하다..

// src/helpers/auth.js

export function logout() {
  return auth().signOut();
}