FireBase 맛보기 (react-redux firebase,firestore)

CCY·2020년 6월 30일
5

FireBase 써보자! 

목록 보기
1/3
post-thumbnail

원문
보고 따라한 링크:
https://blog.logrocket.com/getting-started-react-redux-firebase/

다양한 글들도 있겟지만 속성으로 아무사람이나 따라하자고 생각해서 찾은 블로그지만 나쁘지 않은거 같아서 위 블로그 보고 정리 한 글임을 알려드립니다.

시작하기

  1. 프로젝트 시작
npx create-react-app firebase-todo-app1 
  1. 필요한 modules(npm/yarn 으로 설치)
  • Redux
  • react-redux
  • Firebase
  • react-redux-firebase
  • redux-firestore
  • react-router-dom
npm install --save react-redux-firebase firebase
npm install --save redux react-redux
npm install --save redux-firestore@latest
npm install react-router-dom

FireBase 설정

이번 튜토리얼 사용할 기능들:

  • 인증/인가 (Authentication)
  • Database

홈페이지: https://firebase.google.com/

step 1: 프로젝트 만들기

  1. 홈페이지에 들어가서 시작하기 누르고 프로젝트 생성 따라한다.
  2. 프로젝트 생성 된 후 프로젝트 파일에 들어가서 DEVELOP => DATABASE에 들어간다.

step 2: Database,Authentication 설정하기

Database 만들기

Create Database 클릭

test mode 로 데이터 실행하기 클릭 그럼 모달(팝업)이 뜬다.

데이터 베이스 서버를 선택하라고 하는데.. 지금 나는 한국이니까 아시아를 하는게 맞지 않을까? 해서 찾아보았더니

홍콩이나 도쿄로 하면될거같다는 생각이든다.

Authentication설정하기

  1. Develop 에 Authentication 다시 클릭

  2. Set up Sign-in method 클릭

  3. 다양한 인증인가 가 있는데 이번 프로젝트는 구글 로그인으로 기준 잡아서 실험 한다.


toogle 을 enable 로 변경하고, 저장을 누른다..(email까지 적어야 저장이 눌러진다)

step 3: Firebase Cloud를 앱과 연동하기

앱과 Firebase Cloud 를 연동하기 위해서는 API key 등 프로젝트와 연동할 설정 세팅 정보가 필요하다.
1. Project Overview에 가서 연동할 앱을 설정하라고 나온다.
2. 프로젝트는 web 이니까 web을 선택해서 앱 이름을 설정한다.

  1. 본인은 firebase 를 처음 사용하기도 하고..firebase로 배포? 까지해서 hosting 해볼까해서 호스팅 동이하기를 눌렀고.. 진행하다가 firebase CLI 를 설치하라고 해서

npm install -g firebase-tools 까지 일단 설치를 했다
4. 배포 할거면 절차? 같은거 같은데 일단 보류하고 다음으로 넘어가기 클릭

  1. Project overview 옆에 톱니바퀴(설정)에 들어가서 General 밑에 firebase SDK snippet 창이 있는데 거기에 config 를 눌른다.
  2. 대강 이런 정보들이 생김
const firebaseConfig = {
  apiKey: "AXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  authDomain: "test-XXXXX.firebaseapp.com",
  databaseURL: "https://test-XXXXX.firebaseio.com",
  projectId: "test-XXXXXX",
  storageBucket: "test-XXXXX.appspot.com",
  messagingSenderId: "XXXXXXXXX",
  appId: "XXXXXXXXXXXXXXXXXXXXXXXXX",
  measurementId: "XXXXXXXX"
};
  1. index.js 파일에
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
const firebaseConfig = {
  apiKey: "AXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  authDomain: "test-XXXXX.firebaseapp.com",
  databaseURL: "https://test-XXXXX.firebaseio.com",
  projectId: "test-XXXXXX",
  storageBucket: "test-XXXXX.appspot.com",
  messagingSenderId: "XXXXXXXXX",
  appId: "XXXXXXXXXXXXXXXXXXXXXXXXX",
  measurementId: "XXXXXXXX"
};

firebase.initializeApp(firebaseConfig);
firebase.firestore();

내용들을 추가하여 연동시킨다.
보통은 이런것들을 env나 config로 따로 설정하고 비공개로 한다고 알고있다.. 이건 튜토리얼이니까 그래로 놔두겟다.

코딩을 해보자!!

원문 링크 스타일로 진행하겠다. 일단 해보는게 중요하니까..
이 저자가 말하기론 reducer.js에 모든 코드를 쓰겟다고 한다..

  1. reducer.js
import {combineReducers} from "redux";
import {firebaseReducer} from "react-redux-firebase";
import {firestoreReducer} from "redux-firestore";
export const rootReducer = combineReducers({
    firebase: firebaseReducer,
    firestore: firestoreReducer
});

Firebase 에서 제공하는 리액트 리덕스 리듀서들도 불러온다.

  1. index.js
    react-redux-firebase(RRF) 설정을 하여 데이타 베이스에 접근 할 수 있게 설정을 한다.
const rrfConfig = {
  userProfile: "users",
  useFirestoreForProfile: true,
};

우리 데이터 저장공간이름을 우리가 설정할 수 있는데 여기선 "users" 라고 지었고, 파이어 스토어 프로파일에 접근해야 하기때문에 true 로 설

  1. 리덕스 + firebase react-redux 설정하기
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import { createStore, compose } from "redux";
import { Provider } from "react-redux";
import { ReactReduxFirebaseProvider } from "react-redux-firebase";
import { createFirestoreInstance } from "redux-firestore";
import { rootReducer } from "./ducks/reducers";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
import * as serviceWorker from "./serviceWorker";

const firebaseConfig = {
  apiKey: "AIzaSyBJTFQkg95Aj-s_NsA77mco8ZVG2siLv4U",
  authDomain: "react-redux-firebase-article.firebaseapp.com",
  databaseURL: "https://react-redux-firebase-article.firebaseio.com",
  projectId: "react-redux-firebase-article",
  storageBucket: "react-redux-firebase-article.appspot.com",
  messagingSenderId: "781345165856",
  appId: "1:781345165856:web:45fd42a60e5bb365172245",
  measurementId: "G-XFR3YXLCGW",
};

const rrfConfig = {
  userProfile: "users",
  useFirestoreForProfile: true,
};

firebase.initializeApp(firebaseConfig);
firebase.firestore();

const initialState = {};
const store = createStore(rootReducer, initialState);

const rrfProps = {
  firebase,
  config: rrfConfig,
  dispatch: store.dispatch,
  createFirestoreInstance,
};
ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <ReactReduxFirebaseProvider {...rrfProps}>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </ReactReduxFirebaseProvider>
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);

위 사람 코드는 index.js에 모두 다 넣었지만 원래 분리하는게 맞고. 숨길것들은 숨기는게 맞다.

이사람 프로젝트에는 아래 component 와 기능들이 구현되있다.

AddTodo: todos 추가
PrivateRoute: 인증되지 않은 사용자들이 생성하는 component들은 접근권한 없게 함.
TodoItem: todos 기능들 및 UI 구현 파일들
SignIn: Google 로그인
Todos: 인증된 TODOS 리스트 나열

로그인 (SignIn) Route

HOOKS:
Firebase Hook:

  • useFirebase Hooks 사용하여 database에 데이타를 전달,로그인 기능들 구현

React-router-hooks:

  • useHistory 사용하여 todos route로 연결
import React from "react";
import { useFirebase } from "react-redux-firebase";
import { useHistory } from "react-router-dom";
const SignIn = () => {
  const firebase = useFirebase();
  const history = useHistory();

  const signInWithGoogle = () => {
    firebase
      .login({
        provider: "google",
        type: "popup",
      })
      .then(() => {
        history.push("/todos");
      });
  };
  return (
    <div>
      <h1>Sign In</h1>
      <button
        onClick={(event) => {
          event.preventDefault();
          signInWithGoogle();
        }}
      >
        Sign In with Google
      </button>
    </div>
  );
};
export default SignIn;

Private Route

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { isLoaded, isEmpty } from "react-redux-firebase";
import { useSelector } from "react-redux";
const PrivateRoute = ({ children, ...remainingProps }) => {
  const auth = useSelector(state => state.firebase.auth);
  return (
    <Route
      {...remainingProps}
      render={({ location }) =>
        isLoaded(auth) && !isEmpty(auth) ? (
          children
        ) : (
          <Redirect
            to={{
              pathname: "/",
              state: { from: location },
            }}
          />
        )
      }
    />
  );
};
export default PrivateRoute;

AddTodo

  • users collection 안에서 todos collection을 만들어서 진행.
  • useFirestore Hooks 를 사용하여 firestore에 있는 object을 받음

모든 Todo item 안에는:
isDone – 완료 여부
title – 제목
todoID – 고유 ID
위 내용들이 들어가 있음

import React, { useState } from "react";
import { useFirestore } from "react-redux-firebase";
import { useSelector } from "react-redux";
const AddTodo = () => {
  const [presentToDo, setPresentToDo] = useState("");
  const firestore = useFirestore();
  const { uid } = useSelector((state) => state.firebase.auth);
  const handleChange = ({ currentTarget: { name, value } }) => {
    if (name === "addTodo") {
      setPresentToDo(value);
    }
  };
  const addNewTodo = (todo) => {
    firestore
      .collection("users")
      .doc(uid)
      .collection("todos")
      .add({
        title: todo,
        isDone: false,
      })
      .then((docRef) => {
        docRef.update({
          todoID: docRef.id,
        });
      });
    setPresentToDo("");
  };
  return (
    <div>
      <form action="">
        <input
          type="text"
          name="addTodo"
          value={presentToDo}
          onChange={handleChange}
        />
        <button
          onClick={(event) => {
            event.preventDefault();
            addNewTodo(presentToDo);
          }}
        >
          Add Todo
        </button>
      </form>
    </div>
  );
};
export default AddTodo;

Todos Item

사용자가 checkbox 를 클릭하면 Cloud firestore 의 데이터를 업데이트 하여 보여줌

import React, { useState } from "react"
import { useFirestore } from "react-redux-firebase"
import { useSelector } from "react-redux"

const ToDoItem = ({ isDone, title, todoID }) => {
  const [isTodoItemDone, setTodoItemDone] = useState(isDone)
  const firestore = useFirestore()
  const { uid } = useSelector((state) => state.firebase.auth)
  console.log(isTodoItemDone)
  const handleChange = (event) => {
    if (event.currentTarget.type === "checkbox") {
      setTodoItemDone(!isTodoItemDone)
      firestore.collection("users").doc(uid).collection("todos").doc(todoID).update({
        isDone: !isTodoItemDone,
      })
    }
  }
  return (
    <div
      style={{
        textDecoration: isTodoItemDone && "line-through",
        opacity: isTodoItemDone ? 0.5 : 1,
      }}
    >
      <input type="checkbox" name="" id="" onChange={handleChange} checked={isTodoItemDone} />
      {title}
    </div>
  )
}

export default ToDoItem

Todos

  • users 가 로그인 하면 보여줄 todos.
  • useFireStore connect 를 사용하여 cloud에 있는 redux 상태를 확인
  • subCollection 이라 storeAs 로 listen 해야 한다.
import React from "react";
import { useSelector } from "react-redux";
import AddTodo from "../Components/AddTodo";
import { useFirestoreConnect } from "react-redux-firebase";
import ToDoItem from "../Components/TodoItem";
const Todos = () => {
  const { displayName, uid } = useSelector((state) => state.firebase.auth);
  useFirestoreConnect({
    collection: `users/${uid}/todos`,
    storeAs: "todos",
  });
  const todos = useSelector((state) => state.firestore.data.todos);
  console.log(todos);
  return (
    <div>
      <h3>Hello {displayName}</h3>
      <h4>Todos</h4>
      <AddTodo />
      <ul
        style={{
          listStyleType: "none",
        }}
      >
        {todos &&
          Object.values(todos).map((todo) => (
            <li>
              <ToDoItem
                title={todo.title}
                isDone={todo.isDone}
                todoID={todo.todoID}
              />
            </li>
          ))}
      </ul>
    </div>
  );
};
export default Todos;

APP.js

import React from 'react';
import PrivateRoute from "./UI/Components/PrivateRoute";
import Todos from "./UI/Routes/Todos";
import SignIn from "./UI/Routes/SignIn";
import {Switch, Route} from "react-router-dom";
function App() {
  return (
    <div style = {{
      textAlign: "center"
    }}>
      <h1>Redux Todo App</h1>
      <Switch>
        <PrivateRoute path = "/todos">
          <Todos />
        </PrivateRoute>
        <Route path = "/">
        <SignIn />
        </Route>
      </Switch>

    </div>
  );
}
export default App;

최종

마치며

  1. 일단 유튜브 30분~ 1시간 등등 동영상보단 시간은 절약 한거같아 좋았다.
  2. 코드가 직접 짠 코드들은 아니기때문에 100% 이해한다는 못하지만 추후에 프로젝트를 진행하면서 firebase react-redux를 써야 하면 부분 부분 참조하면 도움이 될것같다.
  3. 조만간 직접 구현해보자!!

앗!! 이사람은 netflify에 배포하였다..firebase 배포하기도 알아봐야겟다.

profile
✍️ 기록을 습관화 하자 ✍️ 나는 할 수 있다, 나는 개발자가 될거다 💪🙌😎

0개의 댓글