외부활동/유데미X스나이퍼팩토리

[유데미x스나이퍼팩토리] 10주 완성 프로젝트 캠프 31일차 - firebase로 데이터 저장하고 내보내기, firestore, storage

주디_JUDI 2023. 7. 6. 20:35

과제 내용

  • 카페 좌석 확인 구독 시스템
  • 리액트 및 파이어베이스를 활용한 서비스 개발
  • 파이어베이스 docs를 바탕으로 서버 구축

과제 과정

파이어베이스 docs 살펴보기

  • 파이어베이스 docs를 살펴보면 cloud FireStore가 있다.

 

  • docs의 cloud firestore - '데이터 읽기' - '데이터 한 번 가져오기' - 'Cloud Firestore 초기화' 부분을 읽어보면 초기 설정에 관한 설명이 적혀있다.

  • 이 코드를 복사한 후 프로젝트 폴더에 config.js를 생성하여 그 안에 붙여넣었다.

 

  • 그리고 그 다음으로 필요한 것은 데이터를 가져오는 것이므로 '데이터 한 번 가져오기' -  '컬렉션의 모든 문서 가져오기'를 참고하여 문서를 불러오기에 필요한 method들인 collection, getDocs, .data()를 활용하였다.


데이터베이스 구글 스프레드시트 생성하기

  • 팀끼리 데이터를 함께 만들기로 하였기 때문에 우선적으롤 구글 스프레드 시트에 데이터 시트를 만들어서 한 곳에 데이터를 모두 입력하기로 하였다.

개인정보가 포함된 부분은 모자이크 처리를 했습니다.

  • 피그마에 의해 추측하여 아래와 같은 데이터 속성이 필요하다고 생각되어 표를 생성하였다.
(cafe) id  
(cafe) name  
location  
tags  
image  
open_time  
close_time  
phone_number  
menu product_id
  product
  price
totalSeat  
leftSeat  

 


Storage에 이미지 저장하기

  • 파이어베이스 보안 규칙으로 데이터 액세스를 테스트 모드로 생성하였다. 모든 사용자가 엑세스 가능하도록 하기 위함이다.
  • image 파일은 로컬파일로 전달하기보다 firebase의 storage를 생성하여 이미지를 저장하고, 해당 url을 저장하였다.

 


Firestore에 데이터 저장하기

  • firestore에서 데이터를 저장하기 위해서는 먼저 컬렉션을 생성해야한다. 컬렉션 하나는 '카페 리스트'와 같은 큰 하나의 object를 생성한다.
  • 그리고 두번째로 문서를 추가한다. 문서 하나에는 cafe 하나의 정보를 포함하는 object를 생성한다.

 

  • 데이터 리스트에 입력한대로 데이터를 하나씩 입력해준다. 
  • 필드의 id, product_id 같은 경우에는 문서 추가를 할때 '자동 ID' 생성을 활용하여 하나씩 만들어서 데이터를 입력했다.
  • 사실 이러한 방식은 좋지 않고, 프론트엔드에서 uuidv4나 new Date()를 생성하여 id를 넣어주거나 백엔드에서 id를 생성해주는 것이 맞지만 이번 프로젝트의 경우에는 프론트엔드가 id를 생성하지 않도록 하기 위하여 데이터를 입력하였다. (이 방식은 절대로 권유하지 않는다.)


파이어스토어에서 데이터 불러오기

  • 스토어에서 데이터를 불러오려면 우선 firebaseConfig라는 정보를 받아와야한다. 해당 내용에 대해서는 29일차에 정리했으므로 생략한다.
  • firebaseConfig를 가져온 후 해당 프로젝트에서 npm install firebase를 하여 패키지를 설치한다.
  • 가져온 config 정보를 config.js 와 같은 파일명으로 저장한다.
import { firebaseConfig } from "./firebase";

const config = {
  apiKey: firebaseConfig.apiKey,
  authDomain: firebaseConfig.authDomain,
  projectId: firebaseConfig.projectId,
  storageBucket: firebaseConfig.storageBucket,
  messagingSenderId: firebaseConfig.messagingSenderId,
  appId: firebaseConfig.appId,
};
  • 정보를 git에 보내지 않기 위하여 gitignore가 된 파일에 config 정보를 저장하고 불러왔다.

 

  • 앞서 말한 초기화를 하기 위하여 initializeApp을 firebase/app에서 불러와서 적용한다.
import { initializeApp } from "firebase/app";

...

const app = initializeApp(config);

 

 

  • app에서 firestore에 저장된 데이터를 가져오기 위하여 'getFirestore'를 적용한다.
import { getFirestore } from "firebase/firestore";

...

const app = initializeApp(config);
export const db = getFirestore(app);

 

 

  • 그 외 또 필요한 method들을 config 내에서 불러온 다음에 export한다.
import { getFirestore, collection, getDocs } from "firebase/firestore";

...

export { collection, getDocs };

 


컴포넌트에서 데이터 불러오기

  • 파이어베이스 데이터는 Promise 객체이기 때문에 promise 데이터를 반환하기 위하여 await, async를 사용하였다.
  • collection으로 'cafe-list'라는 collection을 cafe_list 변수에 할당하여 그 데이터에서 getDocs를 사용해야 컬렉션 안의 문서 데이터를 가져올 수 있다.
const fetchCafes = async () => {
	const cafe_list = collection(db, "cafe-list");
    const result = await getDocs(cafe_list);
}

 

  • getDocs라는 데이터를 가져오기 위해서는 공식문서에서 적혀있는대로 forEach문을 사용하여 데이터를 하나씩 가져올 수 있고, 또 다른 방법으로는 'docs'라는 array를 따로 가져와서 리스트를 변수에 저장할 수도 있다.
// 1안: 데이터를 하나씩 가져오기
result.forEach((el) => setData(el.data());

// 2안: 데이터를 리스트로 가져오기
const cafeData = result.docs.map((el) => el.data());
setData(cafeData)
  • getDocs로 가져온 문서 안에는 docs라는 array가 존재한다.

  • 여기서 주의할 점은 result.forEach로 가져올 경우에는 데이터가 하나씩 잘 나타나지만, result.map으로 가져올 경우에는 에러가 발생하므로 result 안에 있는 docs라는 배열을 활용해서 map을 써야한다!

(forEach와 map 모두 배열의 메소드인데 map은 에러가 발생하고 forEach는 발생하지 않는데, 그 이유에 대해서는 나중에 다시 블로그로 정리해보려고 한다.)

 

  • useEffect로 데이터가 무한 렌더링되지 않기 위하여 의존성 배열을 만들어서 제어하였다.
  • 마지막으로 void로 fetchCafes라는 fetch 함수를 실행하였다.
  useEffect(() => {
    const fetchCafes = async () => {
      const cafe_list = collection(db, "cafe-list");
      const result = await getDocs(cafe_list);
      const cafeData = result.docs.map((el) => el.data());
      console.log(cafeData);
    };
    void fetchCafes();
  }, []);

과제 결과

콘솔로 찍은 데이터