DogKaeBi

[Next.js] 데이터베이스 FireStore

Database로 Firebase의 FireStore를 사용해봤지만 결국은 사용을 중단했다. 사용법은 간단했지만, 데이터 하나당 읽기 한번으로 카운팅하는 것이 부담스러웠다.

[Next.js] 데이터베이스 FireStore

서론

Database를 계속 고민했다.
첫 계획은 "빠르게 만들어보기"이었다.
SQL을 사용하면 DB설계가 오래 걸리 것 같았다.

그리고 결국 DB를 어떤 서버에 올려야 하는데...
시간, 금전, 공부 비용이 높아질 것 같았다.

NoSQL을 보다가
firebase를 사용해봤다.

(하지만 결과적으로는 firebase사용도 포기했다)

Firebase

Firebase 공식 사이트 : https://firebase.google.com/

Firebase는 google이 운영하는 app 개발자 플랫폼이다.
DB, 배포, 인가, 인증 등 여러 서비스를 제공하고 있다.

아마 google 로그인을 만들면 거의 필수로 사용되는 플랫폼이다.

이름 때문에 햇갈리수 있다.

Firebase은 플랫폼 및 앱의 이름이다.
FireStore는 Firebase의 DB 서비스이다.


Firebase 프로젝트 만들기

사용법은 언어와 서비스 마다 다르다.

나의 경우 Next.js -
즉 javascript를 사용하고 있고,
DB만 사용해볼 생각이다.

  • Firebase에서 로그인을 하고
  • 프로젝트를 만든다
  • 프로젝트 화면에서 제품을 선택해서 사용하면된다.

프로젝트에 FireStore 사용하기

DB는

  • Firestore Database 선택
  • 데이터베이스 만들기 선택
  • 위치 선택 ( 서비스 위치로 선택 )
  • 보안 규칙 설정

테스트 단계에서는
보안 규칙은 아래처럼

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

read, write를 모두 허용한다.

프로젝트를 만들면 firebaseConfig에 필요한 정보가 나온다. 별도로 우선 저장해야 한다. (apiKey, authDomain 등 ...)



Firebase, FireStore 코드 추가

프로젝트도 세팅을 해야한다.

npm으로 firebase를 설치하고

npm install firebase

앱 객체를 만든다.
컨트롤러 폴더에 만들었다.

// .\app\controller\firebase.js

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

const firebaseConfig = {
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID,
  measurementId: process.env.FIREBASE_MEASUREMENT_ID,
};

const app = initializeApp(firebaseConfig);
export const firestore = getFirestore(app);

위처럼

  • firebaseConfig 생성
    객체로 내용은 firebase 사이트에서 제공한 정보를 기입한다.
    (우선 "process.env.~"은 내용은 무시하고, firebase에서 제공한 내용을 객체의 값으로 사용한다)
  • initializeApp으로 firebaseConfig을 넘겨, 앱을 시작.
  • getFirestore으로 fireStore사용 및 export

이러면 사용할 준비는 끝났다.



FireStore 데이터

FireStore는 NoSQL 형식으로
객체 형식으로 데이터를 저장한다.

즉 key와 value로 저장된다.

collection - doc - data
형태로 저장된다.

데이터 형태를 예시 보면

collection : {
  "doc" : {
    "data1" : 1,
    "data2" : true,
  },
},
Korea : {
  "Seoul" : {
    "population" : 1000,
    "Metropolitan" : true,
  },
  "Busan" : {
    "population" : 340,
    "Metropolitan" : false,
  }
},
China : {
  "Beijing" : {
    ...
  },
}

같은 형태이다.

FireStore 데이터 추가

데이터 추가 공식 설명문

추가 방식은 set과 add이 있다.
set은 없으면 추가하고, 있으면 수정하는 방식이다.
add는 추가하는 방식이고 doc 이름을 자동 생성한다.

둘의 제일 큰 차이점은 doc 이름의 지정이라고 생각한다.

addDoc 방식

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

const data = { key1: "value1", key2: "value2" };
await addDoc(colletion(firestore, "collectName"), data);

setDoc 방식

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

const data = { key1: "value1", key2: "value2" };
await setDoc(doc(firestore, "collectName", "docName"), data);
  • 앱 객체를 import
  • 필요한 함수를 import
  • await으로 함수 addDoc/setDoc 실행

위에 보는 것 처럼
addDoc은 colletion함수로 위치를 지정해야 한다.
setDoc은 doc함수로 위치를 지정해야 한다.


FireStore 데이터 읽기

데이터 읽기 공식 설명문

import { firestore } from "@controller/firebase";
import { doc, getDoc } from "firebase/firestore";

const docSnap = await getDoc(doc(firestore, "collectName", "docName"));

쿼리를 사용할 수도 있다.
자세한 내용은 공식 사이트에서 확인...



사용 포기한 이유 및 오류

포기한 이유

결론적으로...
사용 시도했지만 포기했다.

사용을 포기한 이유는
전체 읽기와 활당량 때문이다.

다른 DB와 동일하게
Firebase는 사용량으로 비용을 받는다.
작은 프로젝트는 무료로 사용이 가능하다.

하지만 나의 경우는
한자 데이터가 많은데,
Firebase 특성상 각 데이터 당 1회 읽기로 보기 때문에..
페이지를 2~3회 열면 이미 무료 활당량을 전부 사용해버린다.

getDocFromCache 함수도 있지만
캐시를 사용해도 해결되는 문제가 아니어서 포기했다.


부주의로 자주 발생한 오류

자주 발생하는 오류 중에
initialize 오류가 발생할 때가 있다.

우선 import 실수로 발생한다.
initialize와 앱을 사용하는 import 주소가 다를 때

import { ... } from "firebase/firestore";
import { ... } from '@firebase/firestore/lite';


Next.js이어서 발생하는 문제도 있다.
Next는 SSL이어서 Client의 이벤트나 env(환경변수)가 생각되로 전달되지 않을 수 있다.

데이터 추가할 때 발생할 수 있는 오류이다.
정확히는 오류가 발생하지도 않고,
데이터가 추가되지 않는 경우가 있다.

아직 환경변수에 대해서 얘기한 적은 없지만...
.env.local 이라는 파일을 만들면
환경변수를 사용할 수 있다.

위에 firebase 세팅에서 process.env.FIREBASE_API_KEY 같은 환경 변수를 사용했다.
변수명이 FIREBASE_API_KEY 방식으로 사용하면 서버에서만 사용이 가능하다.
변수명이 NEXT_PUBLIC_FIREBASE_API_KEY이라면 client에서도 사용이 가능하다.