본문 바로가기
Firebase

[Firebase] React에 파이어베이스 데이터베이스 사용하기

by 붕어사랑 티스토리 2022. 9. 22.
반응형

https://firebase.google.com/docs/firestore/quickstart#web-version-9

 

Cloud Firestore 시작하기  |  Firebase

2022년 10월 18일에 오프라인과 온라인으로 진행될 Firebase Summit에 참여하세요. Firebase로 앱을 빠르게 개발하고 안심하고 앱을 출시하며 손쉽게 확장하는 방법을 알아보세요. 지금 등록하기 의견 보

firebase.google.com

 

 

0. 사용하기 앞서

파이어베이스는 두가지 서비스가 있다.

 

  • Firestore
  • realtime database

이게 한글로 설명된건 참으로 애매하게 설명해 놨는데 간단히 정리하자면 둘다 똑같이 데이터베이스인데 Firestore가 더 최신버전이고 성능도 좋다 라고 영어문서에 적혀있음.

 

고로 Firestore를 선택하자

 

 

 

 

 

1. 설치하기

아래 커맨드로 심플하게 설치하자

npm install firebase --save

 

 

 

 

 

2. 코드상에서 적용하기

아래 코드로 파이어베이스의 db를 가져온다

import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";

// TODO: Replace the following with your app's Firebase project configuration
// See: https://firebase.google.com/docs/web/learn-more#config-object
const firebaseConfig = {
    // ...
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);


// Initialize Cloud Firestore and get a reference to the service
const db = getFirestore(app);

 

 

 

 

3. 데이터 추가하기

파이어스토어의 db는 두가지 개념이 있다

 

  • collection : 데이터베이스 테이블이라 고 생각하면 된다
  • document : 테이블에 저장되는 데이터 정보이다

 

특이한것은 파이어스토의 스키마가 지멋대로라는 것 이다. 즉 document에 들어가는 스키마는 데이터를 넣을 때 그 즉시 지마음대로 정할 수 있다.

 

 

import { collection, addDoc } from "firebase/firestore";

try {
  const docRef = await addDoc(collection(db, "users"), {
    first: "Ada",
    last: "Lovelace",
    born: 1815
  });
  console.log("Document written with ID: ", docRef.id);
} catch (e) {
  console.error("Error adding document: ", e);
}

 

위 코드에서 두가지 함수만 기억하자

 

  • collection(db, "users")

위 함수는 db에서 컬렉션(테이블이라 생각)을 읽어오겠다는 의미이다. 만약 db안에 지정한 컬렉션이 없으면 그냥 만들어버린다(create table해버림)

 

  • addDoc()

컬렉션 안에 document를 넣는다. 한가지 기억해야할 건 스키마가 딱히 정해지지 않았다는 점이다. 데이터를 어떻게 넣는 지마음대로 넣어도 된다는 것

 

 

위 코드를 적용하면 아래처럼 파이어베이스 콘솔에 나온다

 

 

 

스키마가 딱히 정해지지 않았으므로 만약 아래처럼 데이터필드를 임의로 하나 더 추가하면 아래처럼 된다.

try {
      const docRef = await addDoc(collection(dbService, "users"), {
        first: "Ada",
        last: "Lovelace",
        born: 1815,
        test: 123123123,
      });

 

 

 

 

 

4. 데이터 수정하기

데이터의 수정방법은 두가지가 있다

  • update
  • setDoc

update

update() 메소드를 이용하면 doc의 특정필드만 업데이트 할 수 있다. 만약 특정필드의 값이 없을경우 마찬가지로 필드값을 그냥 추가해버린다

import { doc, updateDoc } from "firebase/firestore";

const washingtonRef = doc(db, "cities", "DC");

// Set the "capital" field of the city 'DC'
await updateDoc(washingtonRef, {
  capital: true
});

 

setDoc

setDoc은 주어진 데이터로 doc을 통째로 다시 set해버린다. 만약 데이터가 없을경우 그냥 데이터를 추가해버린다.

import { doc, setDoc } from "firebase/firestore";

// Add a new document in collection "cities"
await setDoc(doc(db, "cities", "LA"), {
  name: "Los Angeles",
  state: "CA",
  country: "USA"
});

 

만약 setDoc을 이용하는데 데이터가 존재하지 않은지 확실치 않다면 merge을 true로 줘보자.

merge 값이 true이면 데이터가 없다면 추가해버리고, 데이터가 있을경우 update처럼 작용한다

import { doc, setDoc } from "firebase/firestore"; 

const cityRef = doc(db, 'cities', 'BJ');
setDoc(cityRef, { capital: true }, { merge: true });

 

 

 

 

5. addDoc과 setDoc으로 데이터 추가하는것의 차이?

다큐먼트를 추가하면 아래처럼 document의 고유 아이디가 생긴다.

 

 

여기서 setDoc은 이 아이디를 내가 직접 지정해 줄 수 있고, addDoc의 경우 위에 사진처럼 아이디를 중구난방으로 랜덤하게 만든다

import { collection, addDoc } from "firebase/firestore";

// Add a new document with a generated id.
const docRef = await addDoc(collection(db, "cities"), {
  name: "Tokyo",
  country: "Japan"
});
console.log("Document written with ID: ", docRef.id);

 

혹은 자동id생으로 doc을 먼저 만든 뒤 set을 해서 데이터를 추가 할 수도 있다. 경우에 따라서 편하다는데 굳이..?

import { collection, doc, setDoc } from "firebase/firestore";

// Add a new document with a generated id
const newCityRef = doc(collection(db, "cities"));

// later...
await setDoc(newCityRef, data);

 

 

 

 

6. 데이터 읽기

아래처럼 getDocs를 이용하여 컬렉션 전체 데이터를 읽어올 수 있다

import { collection, getDocs } from "firebase/firestore";

const querySnapshot = await getDocs(collection(db, "users"));
querySnapshot.forEach((doc) => {
  console.log(`${doc.id} => ${doc.data()}`);
});

 

 

 

 

7. 데이터 삭제

deleteDoc을 이용하여 다큐먼트를 삭제 할 수 있다

import { doc, deleteDoc } from "firebase/firestore";

await deleteDoc(doc(db, "cities", "DC"));

아래처럼 또는 update()deleteField()를 이용하면 데이터의 특정필드 삭제를 할 수 있다

import { doc, updateDoc, deleteField } from "firebase/firestore";

const cityRef = doc(db, 'cities', 'BJ');

// Remove the 'capital' field from the document
await updateDoc(cityRef, {
    capital: deleteField()
});

 

 

 

8. Map형태의 데이터 추가와 수정

아래처럼 데이터를 여러개 담는 데이터를 추가하고 싶으면 자바스크립트의 경우 Object 형태로 데이터를 넣을 수도 있다.

만약 이 Object의 특정 필드만 업데이트 하고 싶으면 아래 업데이트 내용을 참고하면 된다.

import { doc, setDoc, updateDoc } from "firebase/firestore";

// Create an initial document to update.
const frankDocRef = doc(db, "users", "frank");
await setDoc(frankDocRef, {
    name: "Frank",
    favorites: { food: "Pizza", color: "Blue", subject: "recess" },
    age: 12
});

// To update age and favorite color:
await updateDoc(frankDocRef, {
    "age": 13,
    "favorites.color": "Red"
});

 

위 예시는 점(.) 을 이용하여 오브젝트의 특정필드만을 업데이트 한 것이다.

 

 

허나 아래처럼 favorites 오브젝트를 다시 정의해서 update 해버리면 필드 전체가 싹다 갈아 엎어진다. 즉 아래처럼 해 버리면 업데이트 이후에 favorites.colorfavorites.subject 필드는 더이상 존재하지 않는다.


// Create our initial doc
db.collection("users").doc("frank").set({
  name: "Frank",
  favorites: {
    food: "Pizza",
    color: "Blue",
    subject: "Recess"
  },
  age: 12
}).then(function() {
  console.log("Frank created");
});

// Update the doc without using dot notation.
// Notice the map value for favorites.
db.collection("users").doc("frank").update({
  favorites: {
    food: "Ice Cream"
  }
}).then(function() {
  console.log("Frank food updated");
});

/*
Ending State, favorite.color and favorite.subject are no longer present:
/users
    /frank
        {
            name: "Frank",
            favorites: {
                food: "Ice Cream",
            },
            age: 12
        }
 */

 

 

 

배열요소 업데이트

만약 db에 배열이 저장되어 있는 경우 arrayUnion()arrayRemove() 메소드를 통해 배열에 추가, 삭제를 할 수 있다.

import { doc, updateDoc, arrayUnion, arrayRemove } from "firebase/firestore";

const washingtonRef = doc(db, "cities", "DC");

// Atomically add a new region to the "regions" array field.
await updateDoc(washingtonRef, {
    regions: arrayUnion("greater_virginia")
});

// Atomically remove a region from the "regions" array field.
await updateDoc(washingtonRef, {
    regions: arrayRemove("east_coast")
});

 

 

 

 

 

 

 

9. 커스텀 클래스

간혹가다 Object형태가 아닌 클래스 형태로 데이터를 관리하는 경우가 있다. 이때 클래스 데이터를 db에 저장하려면Converter를 만들어서 파이어스토어에 전달해주면 된다.

 

또한 이렇게 사용하면 스키마를 구현할 수 있게 된다!

class City {
    constructor (name, state, country ) {
        this.name = name;
        this.state = state;
        this.country = country;
    }
    toString() {
        return this.name + ', ' + this.state + ', ' + this.country;
    }
}

// Firestore data converter
const cityConverter = {
    toFirestore: (city) => {
        return {
            name: city.name,
            state: city.state,
            country: city.country
            };
    },
    fromFirestore: (snapshot, options) => {
        const data = snapshot.data(options);
        return new City(data.name, data.state, data.country);
    }
};
import { doc, setDoc } from "firebase/firestore";

// Set with cityConverter
const ref = doc(db, "cities", "LA").withConverter(cityConverter);
await setDoc(ref, new City("Los Angeles", "CA", "USA"));

 

 

 

10. 서버 타임스탬프

db에 관한 업데이트 기록을 남기고 싶다면 serverTimestamp() 메소드를 이용하자. 아래는 update 함수를 이용하여 타임스탬프를 남기는 예제이다.

import { updateDoc, serverTimestamp } from "firebase/firestore";

const docRef = doc(db, 'objects', 'some-id');

// Update the timestamp field with the value from the server
const updateTimestamp = await updateDoc(docRef, {
    timestamp: serverTimestamp()
});

 

 

 

11. 숫자값 늘리기

increament를 사용하여 특정 데이터의 숫자를 증감 할 수 있습니다.

import { doc, updateDoc, increment } from "firebase/firestore";

const washingtonRef = doc(db, "cities", "DC");

// Atomically increment the population of the city by 50.
await updateDoc(washingtonRef, {
    population: increment(50)
});
반응형

댓글