[React]FireStore

44183 단어 ReactReact

Firbase란?

FireBase 바로가기

BaaS (Backend as a Service)

백엔드를 서비스로서 빌려오는 것이다. 파이어베이스를 예로 들면, 데이터베이스, 소셜 서비스 연동(일종의 소셜 로그인), 파일시스템 등을 API 형태로 제공해준다.

FireStore

Firebase에 포함되어 있는 서비스 중 하나로 유연하고 확장 가능한 NoSQL 크라우드 데이터베이스이다.

구조 :

  • Collection: 문서(다큐먼트)의 집합
  • Document: JSON 형식으로 데이터를 저장

Firebase 연동

Firebase 패지키 설치

yarn add firebase

config 가져오기

(1) src 폴더 하위에 firebase.js 파일 생성

//firebase.js
import firebase from "firebase/app";
import "firebase/firestore";

const firebaseConfig = {
// firebase 설정과 관련된 개인 정보
};

// firebaseConfig 정보로 firebase 시작
firebase.initializeApp(firebaseConfig);

// firebase의 firestore 인스턴스를 변수에 저장
const firestore = firebase.firestore();

// 필요한 곳에서 사용할 수 있도록 내보내기
export { firestore };

(2) firebase 대시보드에서 버튼

(3) 앱 이름을 적고, 잠시 기다리면 sdk 추가 영역에 텍스트가 뜬다.
firebaseConfig 내용만 위의 firebse.js에 붙여넣기

(4) App.js 에서 firebase.js에서 내보낸 firestore가져오기

import { firestore } from "./firebase";

(5) componentDidMount에서 데이터 불러와보기

...
const bucket = firestore.collection("buckets");
// 하나만 확인하기
bucket
  .doc("bucket_item")
  .get()
  .then((doc) => {
  // .exists를 써서 데이터가 있는 지 없는 지 확인
  if(doc.exists){
    // 데이터를 콘솔에 찍어보기
    console.log(doc.data());
  }
});
//전체 확인하기
bucket
  .get()
  .then((docs) => {
  let bucket_data = [];
  docs.forEach((doc) => {
    // 도큐먼트 객체를 확인
    console.log(doc);
    // 도큐먼트 데이터 가져오기
    console.log(doc.data());
    // 도큐먼트 id 가져오기
    console.log(doc.id);

    if (doc.exists) {
      bucket_data = [...bucket_data, { id: doc.id, ...doc.data() }];
    }
  });

  console.log(bucket_data);
  ...

FireStore 데이터 사용

공식문서 확인

app.js에서 firestore 데이터 사용

(1) 데이터 추가하기

콜렉션을 찾고 → add
대시보드에서 잘 추가되었는 지 확인

bucket.add({ text: "수영 배우기", compeleted: false });

(2) 데이터 수정하기

콜렉션을 찾고 → 도큐먼트 id로 set

bucket.doc("bucket_item").update({ text: "수영 배우기", compeleted: false });

(3) 데이터 삭제

콜렉션을 찾고 → 도큐먼트 id로 delete

bucket.doc("bucket_item").delete([도큐먼트 ID]);

리덕스와 FireBase

미들웨어(middleware)

리덕스 데이터를 수정할 때 [액션이 디스패치 되고 → 리듀서에서 처리] 하는 과정이 있다. 미들웨어는 이 과정 사이에 미리 사전 작업을 할 수 있도록 하는 중간 다리 같은 것이다. 즉! [액션이 일어나고 → 미들웨어가 할 일 하기 → 리듀서에서 처리] 이 순서로 처리하게 된다.

- firestore 데이터를 리덕스 스토어에 넣으려면?

(1) 리덕스에서 비동기 통신을 할 때 필요한 미들웨어 먼저 설치

yarn add redux-thunk
  • 미들웨어 redux-thunk 의 역할

액션 생성 함수는 객체 반환한하지만 redux-thunk는 객체 대신 함수를 생성하는 액션 생성함수를 작성할 수 있게 해준다.

  • 액션 생성 함수의 작성이 필요한 이유는?

리덕스는 기본적으로는 액션 객체를 디스패치한다. → 즉, 함수를 생성하면 특정 액션이 발생하기 전에 조건을 주거나, 어떤 행동을 사전에 처리할 수 있다.

(2) configStore.js에 미들웨어를 추가

import { createStore, combineReducers, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";	// 미들웨어
import bucket from "./modules/bucket";
import { createBrowserHistory } from "history";

export const history = createBrowserHistory();

const middlewares = [thunk];	// 미들웨어

const enhancer = applyMiddleware(...middlewares);	// 미들웨어
const rootReducer = combineReducers({ bucket });
const store = createStore(rootReducer, enhancer);

export default store;
         `

firestore 적용하기

1. load할 때 데이터를 가지고 오기

(1) 파이어베이스랑 통신하는 함수 만들기

const bucket_db = firestore.collection("bucket");

// 파이어베이스랑 통신하는 부분
export const loadBucketFB = () => {
  return function (dispatch) {
                
    bucket_db.get().then((docs) => {
      let bucket_data = [];
      docs.forEach((doc) => {
        // 도큐먼트 객체를 확인
        console.log(doc);
        // 도큐먼트 데이터 가져오기
        console.log(doc.data());
        // 도큐먼트 id 가져오기
        console.log(doc.id);

        if(doc.exists){
          bucket_data = [...bucket_data, {id: doc.id, ...doc.data()}];
        }
      });

      console.log(bucket_data);
      // 액션 생성 함수한테 우리가 가져온 데이터를 넘기기
      dispatch(loadBucket(bucket_data));
    });
  };
};

(2) 리듀서 수정

case "bucket/LOAD": {
  if(action.bucket.length >0){
    return { list: action.bucket };
  }

  return state;
}

(3) App.js 에서 사용

// App.js
...
// loadBucketFB를 import해오는 거 잊지말기
// load()를 componentDidMount에서 부르면 된다.
const mapDispatchToProps = (dispatch) => ({
  load: () => {
    dispatch(loadBucketFB());
  },
  create: (new_item) => {
    console.log(new_item);
    dispatch(createBucket(new_item));
  }
});
...

2. create에 firestore 적용

순서는 항상 똑같다.
파이어베이스랑 통신 → 필요하다면 리듀서 고치고 → 불러다 쓰기

bucket.add({ text: "수영 배우기", completed: false });

(1) 파이어베이스랑 통신하는 함수 만들기

// 파이어베이스랑 통신하는 부분
export const addBucketFB = (bucket) => {
    return function (dispatch) {
        console.log(bucket);
        // 생성할 데이터를 미리 생성
        let bucket_data = { text: bucket, completed: false };

        // add()에 데이터를 넘기기
        bucket_db
            .add(bucket_data)
            .then((docRef) => {
                // id를 추가한다
                bucket_data = { ...bucket_data, id: docRef.id };

                console.log(bucket_data);

                // 성공했을 때는? 액션 디스패치
                dispatch(createBucket(bucket_data));
            })
            .catch((err) => {
                // 여긴 에러가 났을 때 들어오는 구간
                console.log(err);
                window.alert('오류 발생! 나중에 다시 시도해주세요');
            });
    };
};

(2)리듀서 수정

case "bucket/CREATE": {
    const new_bucket_list = [
        ...state.list,
        action.bucket,
    ];
    return { list: new_bucket_list };
}

(3) App.js 에서 사용

// App.js
...
// addBucketFB를 import해오는 거 잊지말기
const mapDispatchToProps = (dispatch) => ({
    load: () => {
        dispatch(loadBucketFB());
    },
    create: (new_item) => {
        console.log(new_item);
        dispatch(addBucketFB(new_item));
    }
});
...

3. update에 firestore 적용

순서는 항상 똑같다.
파이어베이스랑 통신 → 필요하다면 리듀서 고치고 → 불러다 쓰기

bucket.doc([id]).update({ text: "수영 배우기", completed: false });

(1) 파이어베이스랑 통신하는 함수 만들기

// 파이어베이스랑 통신하는 부분
export const updateBucketFB = (bucket) => {
    return function (dispatch, getState) {
        // state에 있는 값을 가져옴
        const _bucket_data = getState().bucket.list[bucket];

        // id가 없으면? 바로 끝
        if (!_bucket_data.id) {
            return;
        }

        // 새로운 값
        let bucket_data = { ..._bucket_data, completed: true };

        bucket_db
            .doc(bucket_data.id)
            .update(bucket_data)
            .then((res) => {
                dispatch(updateBucket(bucket));
            })
            .catch((err) => {
                console.log("err");
            });
    };
};

(2) Detail.js 에서 사용

// Detail.js
...
// updateBucketFB를 import해오는 거 잊지말기
<button onClick={() => {
    dispatch(updateBucketFB(bucket_index));
    props.history.goBack();
}}>완료하기</button>

4. delete에 firestore 적용

순서는 항상 똑같다.
파이어베이스랑 통신 → 필요하다면 리듀서 고치고 → 불러다 쓰기

bucket.doc([id]).delete();

(1) 파이어베이스랑 통신하는 함수 만들기

// 파이어베이스랑 통신하는 부분
export const deleteBucketFB = (bucket) => {
    return function (dispatch, getState) {
        const _bucket_data = getState().bucket.list[bucket];
        // id가 없으면? 바로 끝
        if (!_bucket_data.id) {
            return;
        }
        // 삭제하기
        bucket_db
            .doc(_bucket_data.id)
            .delete()
            .then((res) => {
                dispatch(deleteBucket(bucket));
            })
            .catch((err) => {
                console.log("err");
            });
    };
};

(2) Detail.js 에서 사용

// Detail.js
...
<button onClick={() => {
    //   dispatch(); <- 괄호안에는 액션 생성 함수가 들어간다.
    // 예시
    dispatch(deleteBucketFB(bucket_index));
    props.history.goBack();
}}>삭제하기</button>
...

좋은 웹페이지 즐겨찾기