220v
젝무의 개발새발
220v
전체 방문자
오늘
어제
  • 분류 전체보기 (255)
    • AI (35)
      • ML, DL 학습 (30)
      • 논문 리뷰 (4)
      • 실습 및 프로젝트 (1)
    • Algorithm (145)
      • LeetCode (13)
      • 프로그래머스 (35)
      • 백준 (96)
      • 알고리즘, 문법 정리 (1)
    • Mobile, Application (17)
      • Flutter (10)
      • iOS, MacOS (7)
    • BackEnd (7)
      • Flask (1)
      • Node.js (5)
      • Spring, JSP..etc (1)
    • Web - FrontEnd (18)
      • JavaScript, JQuery, HTML, C.. (12)
      • React (6)
    • DataBase (1)
      • MySQL (1)
      • Firebase Firestore (0)
      • Supabase (0)
    • Git (1)
    • 기타 툴 및 오류 해결 (3)
    • 강의 (5)
      • Database (3)
      • 암호학 (2)
      • 알고리즘 (0)
    • 후기와 회고 (2)
    • 블로그 꾸미기 (1)
    • 일상과 이것저것 (20)
      • 맛집 (12)
      • 세상사는일 (4)
      • 도서리뷰 (1)
      • 이런저런 생각들 (잡글) (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Priority Queue
  • 다익스트라
  • Dynamic Programming
  • REACT
  • simulation
  • top-down
  • dfs
  • two pointer
  • brute-Force
  • Minimum Spanning Tree
  • topological sort
  • BFS
  • implementation
  • Greedy
  • Lis
  • 티스토리챌린지
  • 프로그래머스
  • Mathematics
  • 오블완
  • binary search
  • disjoint set
  • bitmasking
  • union-find
  • 백준
  • 위상 정렬
  • IMPLEMENT
  • dp
  • Prefix Sum
  • 구현
  • Backtracking

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
220v

젝무의 개발새발

BackEnd/Node.js

[Node.js - Express] Node.js Express로 Firebase Firestore DB와 연동하기 + CRUD

2022. 5. 6. 04:31

Node.js 프로젝트 생성

$ npm init -y

 

패키지 설치

$ npm install express firebase dotenv cors                                                    

Express 프레임워크, Firebase 패키지, dotenv 라이브러리, cors 설치.

 

$ npm install nodemon --save-dev

PM2와 비슷하게 파일 변동 시 Node.js 서버를 자동으로 재시작해주는 nodemon 설치.

--save-dev 옵션은 설치 후 devDependencies에 추가하는 옵션.

 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon index.js"
  },

설치 후 package.json 파일의 "scripts" 부분에 "start": "nodemon index.js" 를 추가해 주자.

나중에 npm start 명령어만으로 nodemon을 실행시킬 수 있도록 하기 위함.

아니면 그냥 pm2 써도 된다.

 

$ npm install body-parser

post 방식의 request 데이터에서 body에 담긴 파라미터들을 쉽게 추출할 수 있도록 해주는 패키지.

 


 

** 주의 **

firebase 패키지를 사용하면 서버가 안 켜지는 경우가 있다. (나는 그랬다.)

그러므로.. firebase-admin 패키지를 이용하도록 하겠음..

$ npm install firebase-admin

 

파일 구조 생성

프로젝트 파일 아래에

.env

config.js

db.js

index.js

파일 생성.

 

controllers

models

routes

폴더 생성.

물론 이름은 달라도 상관없으나 아래 코드는 알아서 수정하면서 따라오시면 됩니다 :D

 

환경 변수(SDK), Firebase DB 생성

  • Firebase 프로젝트 생성.
  • Web-app 추가(등록).
  • Web-app Register 과정에서 Add Firebase SDK 부분을 확인.

놓치고 지나갔다면

프로젝트 설정 - 일반 - 내 앱 에서 다시 확인할 수 있다.

 

  • .env 파일에 입력.
#express server config

PORT=8080
HOST=localhost
HOST_URL=http://localhost:8080


#firebase database config
/* 여기에 Add Firebase SDK 부분에 있는 것들을 복사하여 입력 */
API_KEY=
AUTH_DOMAIN=
DATABASE_URL=
PROJECT_ID=
STORAGE_BUCKET=
MESSAGING_SENDER_ID=
APP_ID=

apiKey: "AIzaenf6asdf3fJSDF734rsoJasdjkfhYY", 같이 되어 있으면

API_KEY=AIzaenf6asdf3fJSDF734rsoJasdjkfhYY 처럼 입력해주면 됨. 쉼표 없어도 됩니다~

 

  • config.js 파일에 입력.
"use strict";
const dotenv = require("dotenv");
const assert = require("assert");

dotenv.config();

const {
  PORT,
  HOST,
  HOST_URL,
  API_KEY,
  AUTH_DOMAIN,
  DATABASE_URL,
  PROJECT_ID,
  STORAGE_BUCKET,
  MESSAGING_SENDER_ID,
  APP_ID,
} = process.env;

assert(PORT, "PORT is required");
assert(HOST, "HOST is required");

module.exports = {
  port: PORT,
  host: HOST,
  url: HOST_URL,
  firebaseConfig: {
    apiKey: API_KEY,
    authDomain: AUTH_DOMAIN,
    databaseURL: DATABASE_URL,
    projectId: PROJECT_ID,
    storageBucket: STORAGE_BUCKET,
    messagingSenderId: MESSAGING_SENDER_ID,
    appId: APP_ID,
  },
};

dotenv 로 .env 파일에 입력한 환경변수를 관리해주는 것이다.

assert 는 Node.js 테스트용 모듈로, 정상적으로 작동하는지 확인해 주는 역할.

 

  • Firestore 데이터베이스를 미리 생성해 줍시다.

 

Express.js 서버 생성

index.js 파일에 입력.

"use strict";
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const config = require("./config");

const app = express();

app.use(express.json());
app.use(cors());
app.use(bodyParser.json());

app.listen(config.port, () =>
  console.log("App is Listening on url http://localhost:" + config.port)
);

 

Firebase Firestore DB와 연결

db.js 파일에 입력.

const firebase = require("firebase-admin");
const config = require("./config");

const db = firebase.initializeApp(config.firebaseConfig);

module.exports = db;

line 1 에서 firebase-admin을 사용했다.

const firebase = require("firebase"); 처럼 firebase 패키지를 이용해도 되지만,

에러가 날 시에는 firebase-admin으로 시도해 보길.

 

CRUD

Create

  • models 폴더에 user.js 생성 후 입력.
class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

user 객체 생성 틀.

 

  • controllers 폴더에 userController.js 생성 후 입력.
"use strict";

const firebase = require("../db");
const User = require("../models/user");
const firestore = firebase.firestore();

const addUser = async (req, res, next) => {
  try {
    const data = req.body;
    const user = await firestore.collection("CRUD_TEST").doc().set(data);
    res.send("Record saved successfully");
  } catch (error) {
    res.status(400).send(error.message);
  }
};

module.exports = {
  addUser,
};

 

  • routes 폴더에 user-routes.js 생성 후 입력
const express = require("express");
const { addUser } = require("../controllers/userController");

const router = express.Router();

router.post("/user", addUser);

module.exports = {
  routes: route
};

 

  • index.js 에 추가 입력. (line 6, line 14)
"use strict";
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const config = require("./config");
const userRoutes = require("./routes/user-routes");

const app = express();

app.use(express.json());
app.use(cors());
app.use(bodyParser.json());

app.use("/api", userRoutes.routes);

app.listen(config.port, () =>
  console.log("App is Listening on url http://localhost:" + config.port)
);

 

  • nodemon 또는 pm2로 서버를 켜준다.

nodemon이라면 아까 설정한 대로

$ npm start

pm2라면

$ pm2 start index.js --watch

 

  • postman으로 post 데이터 날려보기.

Postman 사용법은 알아서 찾아서 해보세용.

Post 형식으로 해서 URL에 http://localhost:8080/api/user 입력 후

Body - raw 로 설정하고 JSON 형식으로 설정한 후에

{
    "name": "Kim",
    "age": "50"
}

대충 이런 데이터 한 번 보내봅시다. 물론 형식은 models 의 user.js 에서 정한대로..^^


여기서 오류가 난다면

데이터를 전송했는데 Record saved successfully가 안 뜨고 오류가 난다면 다음을 시도해 보자. 필자는 이렇게 성공함.

  • firebase-service-key를 가져와서 파일에 JSON 형태로 저장.
  • db.js 수정 ( line 4 추가, firebase.initializeApp() 수정. )
const firebase = require("firebase-admin");
const config = require("./config");

const serviceAccount = require("./firebase_service_key.json");

const db = firebase.initializeApp({
  credential: firebase.credential.cert(serviceAccount),
  databaseURL: "https://(이름 알아서 찾아서 넣어보삼)-default-rtdb.firebaseio.com",
});

module.exports = db;

  • postman으로 post데이터 날렸을 때 밑에 Record saved successfully 가 뜨고, Firestore DB 에서 추가된 것을 확인하면 성공!!

 

Read

  • userController.js 에 Read하는 함수 추가(getAllUser), 그 함수 exports로 내보내기

( line 17~34, line 38 )

"use strict";

const firebase = require("../db");
const User = require("../models/user");
const firestore = firebase.firestore();

const addUser = async (req, res, next) => {
  try {
    const data = req.body;
    await firestore.collection("CRUD_TEST").doc().set(data);
    res.send("Record saved successfully");
  } catch (error) {
    res.status(400).send(error.message);
  }
};

const getAllUser = async (req, res, next) => {
  try {
    const snapshot = await firestore.collection("CRUD_TEST").get();
    const data = snapshot;
    const usersArray = [];
    if (data.empty) {
      res.status(404).send("No User Record found");
    } else {
      snapshot.forEach((doc) => {
        const user_data = new User(doc.data().name, doc.data().age);
        usersArray.push(user_data);
      });
    }
    res.send(usersArray);
  } catch (error) {
    res.status(400).send(error.message);
  }
};

module.exports = {
  addUser,
  getAllUser,
};

 

  • userController.js 에서 import해 사용할 User Class를 user.js 에서 export해주기

( line 8 )

class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

module.exports = User;

 

  • user-routes.js 에 getAllUser 함수로 Read 할 route 설정해 주기

( line 7 )

const express = require("express");
const { addUser, getAllUser } = require("../controllers/userController");

const router = express.Router();

router.post("/user", addUser);
router.get("/users", getAllUser);

module.exports = {
  routes: router,
};

 

  • postman으로 get 요청 보내보기

http://localhost:8080/api/users 주소에 get 요청을 보내면 밑에 데이터가 쫘라락 뜰 것이다.

안 뜨면 에러메시지 보고 함수 고쳐보시길.

(Firebase 공식 문서 참고)

 

Update

  • userController.js 에 Update 함수 추가(updateUser)

마찬가지로 module.export 에 updateUser 추가!

const updateUser = async (req, res, next) => {
  try {
    const newUserData = req.body;
    const userID = req.params.id;
    const userSnapshot = await firestore.collection("CRUD_TEST").doc(userID);
    const userData = await userSnapshot.get();

    if (!userData.exists) {
      res.status(404).send("User with given ID not found");
    } else {
      userSnapshot.update(newUserData);
      res.send(`Update Successfully\n
      Updated User ID : ${userID}\n
      new User Data : {
        name : ${req.body.name},
        age : ${req.body.age}
      }
      `);
    }
  } catch (error) {
    res.status(400).send(error.message);
  }
};

 

  • user-routes.js 에도 마찬가지로 route 추가. ( line 5, line 12 )
const express = require("express");
const {
  addUser,
  getAllUser,
  updateUser,
} = require("../controllers/userController");

const router = express.Router();

router.post("/user", addUser);
router.get("/users", getAllUser);
router.post("/updateUser/:id", updateUser);

module.exports = {
  routes: router,
};

 

  • postman에서 테스트! post 형식으로 데이터 보내기.

문서명은 URL에서 파라미터 형식으로 입력!

( http://localhost:8080/api/updateUser/"Document명" 처럼 )

{
    "name" : "JAEWON",
    "age" : "500"
}

같이 데이터를 입력해주고, send버튼 누르면 잘 작동하는 것을 볼 수 있다!

 

Delete

이제 남은 건 delete인데.. 하던 대로 똑같이 구현하면 어렵지 않게 구현할 수 있다.

  • userController.js 에 Delete 함수 추가(deleteUser)

마찬가지로 밑의 module.export 에 deleteUser 추가!

const deleteUser = async (req, res, next) => {
  try {
    const userID = req.params.id;
    const userSnapshot = await firestore.collection("CRUD_TEST").doc(userID);
    const userData = await userSnapshot.get();

    if (!userData.exists) {
      res.status(404).send("User with given ID not found");
    } else {
      res.send(`Delete Successfully!
      Deleted User ID : ${userID}
      Deleted User Data : {
        name : ${userData.data().name},
        age : ${userData.data().age}
      }
      `);
      userSnapshot.delete();
    }
  } catch (error) {
    res.status(400).send(error.message);
  }
};

 

  • user-routes.js 에도 마찬가지로 route 추가. ( line 6, line 14 )
const express = require("express");
const {
  addUser,
  getAllUser,
  updateUser,
  deleteUser,
} = require("../controllers/userController");

const router = express.Router();

router.post("/user", addUser);
router.get("/users", getAllUser);
router.post("/updateUser/:id", updateUser);
router.get("/deleteUser/:id", deleteUser);

module.exports = {
  routes: router,
};

 

  • postman에 get 방식으로 데이터 보내보면 정상적으로 지워질 User 데이터가 출력되고, Firestore에서 지워지는 것을 확인할 수 있음.

지울 Document명(문서명)은 파라미터로 입력.

(http://localhost:8080/api/deleteUser/"문서명")

 


 

이렇게 성공적으로 Express.js로 서버를 열어 Firebase Firestore DB와 연동하고 CRUD까지 마쳤다. ^ㅁ^

    'BackEnd/Node.js' 카테고리의 다른 글
    • [Node.js - Express] 서버가 안 켜지는 에러(Node.js express와 Firebase 연동) - (Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in ~~~)
    • [Node.js] PM2 설치 및 사용 (Node.js 중단 없이 서비스, 코드 변동 시 자동 재시작)
    • [Node.js / JavaScript] Node.js 개발환경 설정하기 (2) - TypeScript, 그리고 동적 타이핑(Dynamic Typing).
    • [Node.js] Node.js 개발환경 설정하기 (1) - Formatter(Prettier), Linter(ESLint) + Extensions (포매터, 린터 + 여러 확장 프로그램)
    220v
    220v
    DGU CSE 20 / Apple Developer Academy @ POSTECH 2nd Jr.Learner.

    티스토리툴바