MongoDB로 DB적용하기

Suji Park·2022년 9월 14일
0
post-thumbnail

MongoDB를 Callback 방식으로 사용하기

  • Board.js 에 MDB 모듈 불러오기

  • 접속 주소 uri 설정

  • URI vs URL

  • URL(Uniform Resource Location) : 집 주소 까지만 알려줌

  • URI (Uniform Resource Identifier) : 집 주소 + 그 집에 사는 누구 까지 표시

  • DB 에 접속이 된 이후, DB 데이터를 처리 할 수 있으므로, MDB 모듈 MongoClient 의 connect 함수의 콜백으로 기능을 구현!

  • 접속이 완료 되면 2nd 매개 변수로 커서를 받고 해당 커서를 통해 DB, Collection 에 접속

게시글 불러오기

  • DB를 받아서 게시판의 전체 글 띄우기
    • GET /board 요청을 받으면 전체 게시글을 뷰에 띄우기
    • 해당 요청이 들어오면 DB에 접속 후, DB 전체의 데이터를 받기 위해 find({}) 메소드를 이용하여 Cursor 값을 받아오기
    • Cursor 는 데이터로 변환하는 toArray() 메소드를 적용해야만 데이터를 받아 올 수 있으므로 Callback 으로 데이터 받기
// @ts-check
const express = require('express');
// express에서 제공하는 Router를 변수에 담기

const router = express.Router();

const { MongoClient, ServerApiVersion } = require('mongodb');
const { resolveTypeReferenceDirective } = require('typescript');

const uri =
  'mongodb+srv://suji:mtn191371wl@cluster0.s7lxybo.mongodb.net/?retryWrites=true&w=majority';

/* 글 전체 목록 보여주기 */
router.get('/', (req, res) => {
  // 데이터 통신이 성공하면 db로 실패하면 err 메세지

  // db는 mongodb에서 생성한 모든 데이터를 의미한다.
  MongoClient.connect(uri, (err, db) => {
    const data = db.db('kdt1').collection('board');

    // db에서 데이터를 다 받아온 다음에 article이라는 변수에 넣어준다.
    data.find({}).toArray((err, result) => {
      const ARTICLE = result;

      const articleLen = ARTICLE.length; // ARticle 배열의 길이 전달
      // 특정 뷰(ejs 확장자 생략) 파일을 그려라 명령
      // obj의 키 값이 ejs의 파일과 동일한지 확인해야 함.

      // render는 경로 이동으로 '/' 없어도 되지만, redirect는 /있어야 한다.
      res.render('tetz_board', { ARTICLE, articleCounts: articleLen });
    });
  });
});

/* 글 쓰기 모드로 이동 */
router.get('/write', (req, res) => {
  res.render('tetz_board_write');
});

/* 글 추가 기능 수행 */
router.post('/write', (req, res) => {
  if (req.body.title && req.body.content) {
    // 실질적으로 실행할 코드: 배열 마지막에 글이 추가되는 구조 push

    // 키 값으로 title과 content를 가진 객체 = ejs의 name을 따라간다.
    const newArticle = {
      title: req.body.title,
      content: req.body.content,
    };

    // 통신이 성공하거나 실패하던 이 콜백을 실행해라~
    MongoClient.connect(uri, (err, db) => {
      const data = db.db('kdt1').collection('board');

      // data insertOne추가한다~(배열, 콜백함수)
      data.insertOne(newArticle, (err, result) => {
        res.redirect('/tetz_board');
      });
    });
  } else {
    // 예외 처리: 프론트에서 required로 예외처리해서 실은 안해도 된다.
    const err = new Error('데이터가 없습니다');
    // @ts-ignore
    err.statusCode = 404;
    throw err;
  }
});

/* 글 수정모드로 이동 */
router.get('/modify/title/:title', (req, res) => {
  // db 접속
  MongoClient.connect(uri, (err, db) => {
    const data = db.db('kdt1').collection('board');

    // title이 동일한 게있으면 result에 obj형태로 담아주세요~
    data.findOne({ title: req.params.title }, (err, result) => {
      if (err) {
        throw err;
      } else {
        // err가 아니라면 selectedArticle에 result를 담아서 하세요!
        const selectedArticle = result;
        res.render('tetz_board_modify', { selectedArticle });
      }
    });
  });
});

/* 글 수정 기능 수행: 수정하기 눌렀을 때  */
router.post('/modify/title/:title', (req, res) => {
  if (req.body.title && req.body.content) {
    MongoClient.connect(uri, (err, db) => {
      const data = db.db('kdt1').collection('board');

      // 수정은 updateOne 메소드 사용: 조건을 주고, 조건을 찾아와서 $set변경해준다.
      data.updateOne(
        { title: req.params.title },
        {
          $set: {
            title: req.body.title,
            content: req.body.content,
          },
        },
        (err, result) => {
          if (err) {
            throw err;
          } else {
            res.redirect('/tetz_board');
          }
        }
      );
    });
  } else {
    const err = new Error('요청 값이 없습니다.');
    err.statusCode = 404;
    throw err;
  }
});

/* 글 삭제 기능 수행 */
router.delete('/delete/title/:title', (req, res) => {
  MongoClient.connect(uri, (err, db) => {
    const data = db.db('kdt1').collection('board');

    // 지우는 것 deletOne 메소드: 찾아준 후 바로 지워준다.
    data.deleteOne({ title: req.params.title }, (err, result) => {
      if (err) {
        throw err;
      } else {
        // 여기에 redirect 걸면 delete 메소드로 튀어나가기 때문에 notfound가뜬다. => 프론트를 믿고.. send로 처리
        res.send('삭제 완료');
      }
    });
  });
});

module.exports = router;

Async / Await를 적용하여 모듈화

  • DB 관련 코드를 모듈화
  1. Mongo.js코드에서 client를 모듈화
  2. Board.js에서 client를 가져오기

Callbakc을 Async, Await으로 변경하기

  • Await를 사용하려면 함수 부분에 async를 추가해야 한다.
  • 전체 db를 불러오거나 전체 데이터를 받는 경우에는 cursor(DB에 대한 정보와 위치를 알려주는 데이터) 형태로 받아오기 때문에 await 처리 필요 X

  • 단, cursor 를 데이터화 할 때는 통신이 필요하므로 await 처리

  • 기존 callback 에서 처리하던 부분을 await 뒤에 두어서 자연스럽게 나중에 처리하도록 수정

// @ts-check
const express = require('express');
// express에서 제공하는 Router를 변수에 담기

const router = express.Router();

const mongoClient = require('./mongo');

const { MongoClient, ServerApiVersion } = require('mongodb');
const { resolveTypeReferenceDirective } = require('typescript');

const uri =
  'mongodb+srv://suji:mtn191371wl@cluster0.s7lxybo.mongodb.net/?retryWrites=true&w=majority';

/* 글 전체 목록 보여주기 */
router.get('/', async (req, res) => {
  // await 붙은 순간은 이전에 다 callback으로 처리한 순간들이다.
  const client = await mongoClient.connect();
  // 데이터를 변화할 때 콜백을 걸어주면 되는 거니까 위치만 알려주는 정보만 넣어준다.(await 필요없음)
  const cursor = client.db('kdt1').collection('board');
  // 데이터가 받아지면 ARTICLE로 들어간다.
  const ARTICLE = await cursor.find({}).toArray();
  const articleLen = ARTICLE.length;
  res.render('tetz_board', { ARTICLE, articleCounts: articleLen });
});

/* 글 쓰기 모드로 이동 */
router.get('/write', (req, res) => {
  res.render('tetz_board_write');
});

/* 글 추가 기능 수행 */
router.post('/write', async (req, res) => {
  if (req.body.title && req.body.content) {
    const newArticle = {
      title: req.body.title,
      content: req.body.content,
    };

    // client에 접속에 관련된 정보를 가져온다.
    const client = await mongoClient.connect();
    // 접속을 바탕으로 db와 collection
    const cursor = client.db('kdt1').collection('board');
    // 데이터받는 시간이 걸리니까 await 걸어서 insertOne 추가
    await cursor.insertOne(newArticle);
    res.redirect('/tetz_board');
  }
});

/* 글 수정모드로 이동 */
router.get('/modify/title/:title', async (req, res) => {
  const client = await mongoClient.connect();
  const cursor = client.db('kdt1').collection('board');
  // title과 params의 타이틀이 동일하다면, 해당 데이터가 selectedArticle이 들어간다.
  const selectedArticle = await cursor.findOne({ title: req.params.title });
  res.render('tetz_board_modify', { selectedArticle });
});

/* 글 수정 기능 수행: 수정하기 눌렀을 때  */
router.post('/modify/title/:title', async (req, res) => {
  if (req.body.title && req.body.content) {
    const client = await mongoClient.connect();
    const cursor = client.db('kdt1').collection('board');
    // title이 params의 title과 같다면,
    await cursor.updateOne(
      { title: req.params.title },
      // req.body와 동일하게 바꿈
      {
        $set: {
          title: req.body.title,
          content: req.body.content,
        },
      }
    );
    res.redirect('/tetz_board');
  } else {
    const err = new Error('요청 값이 없습니다.');
    err.statusCode = 404;
    throw err;
  }
});

/* 글 삭제 기능 수행 */
router.delete('/delete/title/:title', async (req, res) => {
  const client = await mongoClient.connect();
  const cursor = client.db('kdt1').collection('board');
  await cursor.deleteOne({ title: req.params.title });
  res.send('삭제 완료');
});

module.exports = router;
profile
천방지축😛 얼레벌레🙄 빙글빙글🙃 돌아가는 수지의 코드~🎵

0개의 댓글