티스토리 뷰

Technology/React

React 로 Firestore 다루기

캡틴테크 2023. 1. 4. 13:53
반응형

Firebase v9 를 이용해서 React 프로젝트 로그인/가입/로그아웃에 대해서 아래 글에서 살펴봤었는데요. 혹시 안보신분은 빠르게 봐주시고, 오늘은 Firestore의 컬렉션과 문서를 다루는 몇가지 주요 케이스에 대해서 다뤄보도록 하겠습니다.

https://hero-space.tistory.com/104

 

React 와 Firebase 인증서버 연동하기

웹을 제작하면서 가장 기본적으로 로그인 기능을 구현하기 위해서 사용하는 것은 구글에서 제공하는 firebase 입니다. 일정 사용량 까지 무료기도 하고 sdk도 여러가지 언어로 제공되고 있어서 쉽

hero-space.tistory.com

React에서 Firestore를 다루려면?

워낙 많은 분들이 Firebase를 사용하고 있고, Firebase에서 SDK도 잘 제공하고 있기 때문에  큰 어려움 없이 가입/로그인/로그아웃 서비스를 만들 수 있고, 추가적으로 Firebase의 저장장소인 Firestore를 이용할 수 있도록도 SDK로 제공하고 있습니다. 다만 이 역시 v8와 v9 사용법에 대한 설명이 블로그마다 혼재 되어 있으니, 자신이 만든 프로젝트에 어떤 버전이 설치되어 있는지 확인하시고 시작하시면 됩니다. 저는 최신버전을 계속 사용중이라 v9 이고 구체적으로 9.15.0 버전이네요. SDK 문서는 아래의 위치에서 확인하실 수 있습니다.

https://firebase.google.com/docs/firestore

 

Firestore  |  Firebase

유연하고 확장 가능한 NoSQL 클라우드 데이터베이스를 사용하여 클라이언트 및 서버 측 개발을 위해 데이터를 저장하고 동기화하십시오.

firebase.google.com


Firestore는 컬렉션->문서->컬렉션->문서 이렇게 반복적인 구성으로 만들어지는데요. 어디까지나 Firestore만의 간소화된 방식이니 실제 구현하다보면 불필요하게 뎁스가 길어진다던지 문제가 있습니다. 하지만 SDK로 잘 지원하기도 하고 빠르게 레퍼런스도 많다보니 자주 사용하는데요. 많은 데이터를 클라우드에 저장하는 케이스가 아니라면 더할나위 없이 사용하기 좋습니다. 

문서 생성 하기

Firestore의 특정 위치에 문서를 생성하는 것을 해보도록 하겠습니다. 패스는 Group > GroupId > GroupId > {그룹이름}으로 만들예정이고 필드 값으로 createdAt, doctorId, updatedAt 이라는 3가지의 값을 넣어서 생성하도록 할 것인데요. 그룹 이름에 해당 하는 문서 이름이 고유한 값으로 해서 생성할때 값은 그룹이 있는지 검색해보고 없다면 생성되도록 하는 방법으로 진행하도록 하겠습니다.

import { getFirestore, collection, getDocs, query, where, doc, updateDoc, setDoc, addDoc } from 'firebase/firestore';

const createGroup = async (groupName: string, doctorId: string) => {
  // create document, createdAt, doctorId, updatedAt

  // #1 check same group
  const groupCollectionRef = collection(firestoreDB, 'Group/GroupId/GroupId');
  const groups = await getDocs(groupCollectionRef);
  let isValid: boolean = true;

  groups.forEach((group) => {
    if (group.id === groupName) {
      isValid = false;
    }
  });

  if (isValid !== true) {
    console.log('grouname is duplicated');
    return false;
  }

  // #2 Get Current Time
  const date = new Date();
  const curr = date.getTime();
  const timeValue = Math.floor(curr / 1000);

  // #3 Create New Document
  try {
    await setDoc(doc(groupCollectionRef, groupName), {
      createdAt: timeValue,
      doctorId,
      updatedAt: timeValue,
    });
  } catch (error) {
    console.log(error);
    isValid = false;
  }

  return isValid;
};

export {
  firebaseAuth,
  logInWithEmailAndPassword,
  sendPasswordReset,
  logout,
  getIdToken,
  firestoreDB,
  getUIDFromEmail,
  updateUserData,
  createGroup,
  createAdmin,
};

코드를 보면 createGroup이라는 함수의 인풋 인자로 groupName과 doctorId를 받고 있습니다. 문서를 생성한 뒤 필드값에 넣을 변수로 보면 되겠구요. 먼저 같은 그룹이 있는지 검색하는 방법은 그룹을 모두 가져와서 그룹 id가 같다면 바로 리턴하는 방식으로 구현을 하였습니다. 만약 같은 id 값이 없다면 생성해도 된다고 보고 secDoc, doc 이라는 firestore sdk에서 제공하는 인터페이스를 통해서 문서를 생성하게 되는데요, 문서의 포맷팅은 doc이라는 녀석이 잡아주고, 그 안에 필드값은 인풋인자로 받은 값과, 현재 시간 기준의 timestamp를 입력하도록 createdAt와 updatedAt을 넣어 주었습니다. 물론 중복이 아닌 어떤 이유로 생성 실패가 될 수 있기에 생성 실패시에 이를 false 리턴하도록 구현해놓았습니다. setDoc 자체는 비동기적 인터페이스이기 때문에 createDoc을 부르는 데서는 await를 쓰는 것을 잊으시면 안되겠죠?

문서 업데이트 하기

문서 업데이트 하기는 문서 생성하기와 거의 유사합니다. setDoc 대신에 updateDoc이라는 인터페이스를 쓰면 되는데요. 비동기적 함수는 동일하기 때문에 아래와 같이 예시를 보시면 이해하실 수 있습니다. 이번에는 Info/Users/User 라는 하위의 uid로 유니크하게 문서이름이 잡혀있는 구조에서 doctorId와 group,  updatedAt 값을 수정해보도록 하겠습니다.

const updateUserData = async (uid: string, doctorId: string, group: string) => {
  // doctorId, group, updateAt
  const date = new Date();
  const curr = date.getTime();
  const updateAtValue = Math.floor(curr / 1000);

  const userDoc = doc(firestoreDB, 'Info/Users/User', uid);
  let isValid: boolean = true;
  try {
    await updateDoc(userDoc, { doctorId, group, updatedAt: updateAtValue });
  } catch (err) {
    console.log(err);
    isValid = false;
  }

  return isValid;
};

Firestore의 SDK는 데이터베이스의 제약으로 인해서, 한 두번 방식에 대해서 습득을 하면 빠르게 활용가능한 장점이 있습니다. 물론 데이터베이스의 제약자체가 개발의 한계점으로 다가올 수 있지만, 단순한 서비스 관점에서는 일정 사용시까지 무료로 이용할 수 있는 firestore는 훌륭한 프로토타이핑을 가능하게 하는 클라우드 서비스 이기에 리액트로 웹을 만들면서 한번쯤 빠르게 붙여보고 테스트해보시길 바랍니다.

반응형
댓글