본문 바로가기
✍️ 기록/Firebase

[Firebase] React - 조회, 추가, 수정, 삭제

by 김물사 2025. 6. 18.

📌 Friebase

 

📍프로젝트 생성 - 참고

 

[Firebase] 파이어베이스 프로젝트 생성 및 연동

📌 Firebase란?파이어베이스(Firebase)는 2011년 파이어베이스(Firebase, Inc)사가 개발하고 2014년 구글에 인수된 웹/모바일 앱 개발의 여러 측면을 간소화해주는 Google의 플랫폼 🔗 Firebase Firebase | Google's

th91.tistory.com

※ Firebase Console 접속 ➡️ 새 프로젝트 생성 ➡️ 웹 앱 등록 후 아래와 같이 진행.

📍 React - firebase 설치

npm install firebase

 

📍 firebase.ts  / .env 생성

✅ firebase.ts - 개인 Firebase SDK 설정 정보 

 

앱 등록 시 SDK 정보 놓친 분들 프로젝트 ➡️ 프로젝트 설정 ➡️ 일반 ➡️ 내 앱에서 확인할 수 있어요!

// src/firebase.ts
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';

const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
};

// 앱 초기화
const firebaseApp = initializeApp(firebaseConfig);
// 데이터베이스
const firebaseDB = getFirestore(firebaseApp);
export { firebaseApp, firebaseDB };

 

✅ .env - 환경변수 사용

- 보안과 유지보수를 위해 .env로 분리해서 관리

- REACT_APP_ 또는 VITE_ 접두사 사용

- root에 .env 파일 생성

# firebase - Tistory
REACT_APP_FIREBASE_API_KEY= "apiKey"
REACT_APP_FIREBASE_AUTH_DOMAIN= "authDomain"
REACT_APP_FIREBASE_PROJECT_ID= "projectId"
REACT_APP_FIREBASE_STORAGE_BUCKET= "storageBucket"
REACT_APP_FIREBASE_MESSAGING_SENDER_ID= "messagingSenderId"
REACT_APP_FIREBASE_APP_ID= "appId"

 

✅ 프로젝트 SDK 정보 입력

※ .gitignore 파일에 .env 추가

.env 추가하여 git에 민감 정보가 배포되지 않도록 합니다.

.env 파일 수정 후 재시작해야 수정된 값이 적용!

 

📍 Firestore Database 조회

 

✅ 테스트 확인하기 위해 임시로 컬렉션/문서/필드 정보 추가

import { useEffect } from 'react';
import { collection, getDocs } from 'firebase/firestore';
import { firebaseDB } from '../firebase';

export const Tistory = () => {
   useEffect(() => {
    const fetchUsers = async () => {
      try {
        const querySnapshot = await getDocs(collection(firebaseDB, 'tistory'));
        console.log(querySnapshot);
        // 문서가 없는 경우 예외 처리
        if (querySnapshot.empty) {
          console.log("문서가 없습니다.");
          return;
        }
         // 각 문서 ID와 데이터 조회
        querySnapshot.forEach((doc) => {
          const data = doc.data();
          console.log(data);
          console.log('문서 ID : ', doc.id);
          Object.keys(data).forEach((key) => {
            console.log(`${key} : `, data[key]);
          });
        });
      } catch (error) {
        console.error('데이터 불러오기 실패:', error);
      }
    };
    fetchUsers();
  }, []);

  return ( 
    <div className="Tistory">
      TEST
    </div>
  )
}

firebase.ts 에서 등록한 firebaseDB import

- getDocs(collection(firebaseDB, '컬렉션명'));

- 컬렉션에 있는 문서를 조회하여 문서의 ID와 data 정보를 받아올 수 있습니다.

✅ 정상적으로 불러와서 확인 완료!

 

📍 요청 횟수

📗getDocs : 컬렉션의 모든 문서 가져오기

- 요청 횟수 : 문서 수만큼 읽기 요청 발생

- 비용 : 문서 100개 ➡️ 100회 읽기 비용 발생

// 전체 문서 불러오기
const fetchAllDoc = async () => {
  const snapshot = await getDocs(collection(db, '컬렉션명'));

  if (snapshot.empty) {
    console.log('❌ 문서 없음');
    return;
  }

  snapshot.forEach((doc) => {
    console.log('문서 ID:', doc.id);
    console.log('정보', doc.data());
  });
};

 

 

📗 getDoc : 단일 문서 가져오기, 문서 ID를 알고 있는 경우

- 요청 횟수 : 1

- 비용: 문서 1개 = 1회 읽기 비용

const fetchDoc = async () => {
  const ref = doc(db, '컬렉션명', '문서id');
  const snapshot = await getDoc(ref);

  if (snapshot.exists()) {
    console.log('정보', snapshot.data());
  } else {
    console.log('❌ 문서 없음');
  }
};

 

✅ 상황에 맞게 요청비용 절감하여 사용!

 

📍 추가 - 컬렉션, 문서, 필드

📗 문서 추가 - 문서 ID 지정

// ✅ ID 지정 문서 추가 
const handleDocAdd = async () => {
  // collection(DB, '컬렉션명','문서 ID'),
  await setDoc(doc(firebaseDB, 'tistory', 'doc-add'), {
    title: '직접 지정한 문서 ID로 추가',
  });
}

✅ doc-add 지정한 문서 id로 추가 완료 확인!

 

📗 문서 ID 미지정 - 자동 ID 생성

// ✅ ID 지정 문서 추가 
const handleDocAdd = async () => {
  await addDoc(collection(firebaseDB, 'tistory'), {
    title: '랜덤 ID로 문서 추가',
  });
}

✅ ID를 지정하지 않을경우 랜덤으로 문서 ID가 만들어져 문서가 생성!

 

📖 addDoc() vs setDoc() 차이

  addDoc() setDoc()
문서 ID 자동 생성됨 (랜덤) 직접 지정
사용 대상 collection() doc()
기존 문서 덮어쓰기 항상 새 문서 같은 ID 존재 시 덮어씀
주요 사용처 단순 추가, 고유 ID 불필요할 때 문서 ID가 명확해야 할 때

 

 

📗 하위 컬렉션 생성

// ✅ 하위 컬렉션 생성 및 문서 추가
const handleAddSubCollection = async () => {
  const parentDocRef = doc(firebaseDB, 'tistory', 'test');
  // 하위 컬렉션 이름 지정 및 참조
  const subColRef = collection(parentDocRef, 'subCol');

  // 하위 컬렉션 문서 추가 (랜덤 ID)
  await addDoc(subColRef, {
    title: 'sub 컬렉션 문서 추가 완료',
  });
}

 

 

✅ subCol > 랜덤ID 문서 추가를 확인할 수 있습니다!

 

📗 필드 정보 추가

 

 // ✅ 필드 정보 추가
  const handleAdd = async () => {
    const testRef = doc(firebaseDB, 'tistory', 'test');
    const testDoc = await getDoc(testRef);
    if (testDoc.exists()) {
      await updateDoc(testRef, { date: new Date() });
      console.log('date 추가 완료.')
    } else {
      console.log('❌ 문서가 없는 경우');
    }
  }

✅ date 추가 확인 완료!

📍 수정 - 필드

const handleUpdate = async () => {
  const parentDocRef = doc(firebaseDB, 'tistory', 'test');
  try {
    await updateDoc(parentDocRef, {
      array: arrayUnion({ title: '추가된 타이틀' }), // arrayUnion: 배열에 새 객체 추가
      test: '업데이트 test', // test 필드 값 변경
    });
  } catch (error) {
    console.error('❌ 오류 ', error);
  }
};

 

업데이트 전 업데이트 후

 

지정된 컬렉션, 문서 내 필드 값 업데이트 성공

 

※ arrayUnion : 배열 추가만 가능 - 중복 없이 추가배열 내 값을 수정하기 위해서는 아래와 같이 기존 배열 정보를 가져온 후 수정 후 새로운 배열로 덮어쓰기.

...
// 기존 배열 값 가져온 후 특정 값 변경 후 배열 전체 업데이트
const updatedArray = data.array.map(item =>
  item.id === '특정 조건' ? { ...item, title: '수정된 타이틀' } : item
);

// 전체 배열과 test 필드 함께 업데이트
await updateDoc(parentDocRef, {
  array: updatedArray,
  test: '업데이트 test',
});

📍 삭제 - 문서, 필드

📗 문서 삭제

// ✅ 문서 삭제 
const handleRemove = async () => {
  const targetRef = doc(firebaseDB, 'tistory', 'a2mBacKDV0paxacKhWBY');
  try {
    await deleteDoc(targetRef);
    console.log('문서 삭제 완료');
  } catch (error) {
    console.error('❌ 문서 삭제 실패:', error);
  }
}

✅ 테스트를 위해 생성한 불필요한 문서(a2mBacKDV0paxacKhWBY) 삭제 

 

📗 필드 삭제

// ✅ 필드 삭제 
const handleRemove = async () => {
  const testRef = doc(firebaseDB, 'tistory', 'test');
  const testDoc = await getDoc(testRef);
  if (testDoc.exists()) {
    await updateDoc(testRef, {
      date: deleteField(), // 👈 date 필드 삭제
    });
    console.log('date 필드 삭제 완료')
  }else{
    console.log('❌ 문서가 없는 경우');
  }
}

 

추가 된date 필드 값을 이번엔 삭제 진행하여 정상적으로 삭제 확인! 

 

📍 사용 함수 정리

  컬렉션 참조 생성 collection(db, '컬렉션명')
조회,
data 가져오기
컬렉션 내 전체 문서 조회 getDocs(collection(db, '컬렉션명'))
하나의 문서 데이터 조회 getDoc(doc(db, '컬렉션명', '문서ID'))
추가, 덮어쓰기 랜덤 ID로 문서 추가 addDoc(collection(db, '컬렉션명'), 데이터)
문서 ID를 지정하여 추가 또는 덮어쓰기 setDoc(doc(db, '컬렉션명', '문서ID'), 데이터)
수정 기존 문서의 일부 필드만 수정 updateDoc(doc(db, '컬렉션명', '문서ID'), 새데이터)
배열 필드에 값 추가 (중복 없이) arrayUnion(값)
삭제 문서 삭제 deleteDoc(doc(db, '컬렉션명', '문서ID'))
특정 필드를 삭제 deleteField()
하위 컬렉션의 경우 하위 컬렉션 내 문서가 없다면 자동 삭제

 

 

✍️ 기록

 

감사합니다. 😁

 

반응형
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.