yamoo9 / likelion-FEQA

질문/답변 — 프론트엔드 스쿨, 멋사
29 stars 9 forks source link

[LAB-4] useWriteBatchData.js 랑 친해지고 싶습니다. #289

Closed PracticeKJY closed 1 year ago

PracticeKJY commented 1 year ago

질문 작성자

김종엽

문제 상황

안녕하세요. 다름이 아니라 localData -> firebase의 db 로 리팩토링 하기위해 두뇌회로를 굴리던 도중, https://github.com/yamoo9/likelion-react/blob/10-firebase-service/firebase-db-storage/src/firebase/firestore/README.md#usedatastate 야무썜이 올려주신 useWriteBatchData.js 라는 섹시한 친구를 발견해서 적용해볼려고했는데요..

제 머리속에선

(src > components > header > header.jsx에 임의로 달아서 테스트해봤습니당....) image

불러오고 -> 핸들러로 선언한 뒤 버튼에게 onClick으로 달아주면 -> 버튼클릭한순간 행복시작 이였거든요... 내 계정 파이어베이스 데이터 가면 컬렉션에 문서들이 쫘라락 뜨겠지?? 하면서 눈누난나했는데...

하지만 항상 그렇듯,

image

이렇게 뜨더라고요..

저와 같은 과정을 고민하셨던 이슈글이있어서 참고하고, 쓰기규칙도 잘 준거같은데...

image

어디서 베베꼬였을까요,,, useWriteBatchData.js와 친해지려면 어떻게해야할까요..

저희 팀 프로젝트의 src > store > productListState.js 의 initialProductList 를 너무나도 firebase의 DB로 넣고싶어요..

프로젝트 저장소 URL

https://github.com/PracticeKJY/react-project-kally/tree/firebaseTestbranch

환경 정보

yamoo9 commented 1 year ago

문제 분석

Firestore에 업로드 할 initialProductList의 구조와 shopData의 구조가 다릅니다. shopData에는 도큐멘트 ID로 사용될 keyitems를 포함하는 객체로 구성된 데 반해, initialProductList는 그렇지 않기 때문에 오류가 발생한 것입니다. 🤔

initialProductList

export const initialProductList = [
  {
    id: 'product-rksk',
    name: '[대구 반할만떡] 유부호만두',
    description: '유부로 속을 든든히 채운 군만두',
    price: 6900,
    saleRatio: 0.24,
    salePrice: 5244,
    image: {
      thumbnail: '/assets/product/ubuho/thumbnail.jpg',
      view: '/assets/product/ubuho/detail-view.jpg',
      banner: '/assets/product/ubuho/detail-banner.jpg',
      info: '/assets/product/ubuho/detail-info.jpg',
      alt: '유부호 만두',
    },
    stock: 3,
    category: '샐러드ㆍ간편식',
    kalryOnly: false,
    brand: '대구 반할만떡',
    storageType: 'frozen',
    explanation: "떡볶이 마니아라면 한 번쯤은 '반할만떡'이라는 단어를 들어보셨을 거예요. 대구 반야월 초등학교 앞 골목길에서 1973년부터 떡볶이와 만두를 팔아 온 가게, '반야월 할매 만두와 떡볶이'의 줄임말인데요. 이번에는 유부와 당면으로 속을 채워 부드러움이 돋보이는 유부호만두를 준비했답니다. 속재료에 간이 골고루 배어있어서 다른 양념을 더하지 않아도 맛있게 먹을 수 있고요. 찹쌀가루를 더한 만두피 덕분에 겉은 바삭, 속은 쫀득한 식감이 일품이지요. 에어프라이어나 프라이팬에 구워 바삭바삭한 군만두로 즐겨보세요. ",
  },
  // ...
];

shopData

export const shopData = [
  {
    key: 'Hats',
    items: [
      {
        id: 1,
        name: '브라운 브림',
        imageUrl: 'https://i.ibb.co/ZYW3VTp/brown-brim.png',
        price: 25000,
      },
      // ...
  },
  // ...
];

문제 해결

수업 시간에 다룬 useWriteBatchData 훅을 사용할 수도 있겠지만, Firestore에 데이터를 올릴 기능만 가지므로 writeBatchData 함수를 작성합니다.

writeBatchData.js

import { collection, doc, writeBatch } from 'firebase/firestore';
import { db } from './app';

/**
 * Firestore 데이터 일괄 쓰기 유틸리티 함수
 * @param {unknown[]} dataList 데이터 리스트
 * @param {string} collectionKey 콜렉션 ID
 * @param {string} documentKey 도큐멘트 ID
 */
export const writeBatchData = async (
  dataList,
  collectionKey,
  documentKey = 'documentId'
) => {
  const collectionRef = collection(db, collectionKey);
  const batch = writeBatch(db);

  dataList.forEach((data) => {
    const docRef = doc(collectionRef, data[documentKey].toLowerCase());
    batch.set(docRef, data);
  });

  try {
    await batch.commit();
    console.log('콜렉션 생성 및 도큐멘트 생성 일괄 처리가 완료되었습니다.');
  } catch (error) {
    console.log(error.message);
  }
};

그리고 테스트 코드를 아래와 같이 작성한 후, "일괄 데이터 쓰기" 버튼을 클릭하면 Firestore에 데이터를 일괄적으로 쓸 수 있습니다.

import { writeBatchData } from '@/firebase/writeBatchData';
import { initialProductList } from '@/store/productListState';

function TestWriteBatchData() {
  const handleWriteBatchData = () => {
    writeBatchData(initialProductList, 'productlist', 'id');
  };

  return (
    <>
      <button type="button" onClick={handleWriteBatchData}>
        일괄 데이터 쓰기
      </button>
      {/* ... */}
    </>
  );
}

일괄 데이터 쓰기 영상

Firestore에 일괄 쓰기 하는 시연 영상을 확인하세요. 😃

https://user-images.githubusercontent.com/1850554/230749870-81a79f69-b035-4166-a585-1d813451c04f.mp4