클론코딩/유튜브

#3 - MongoDB를 이용해 데이터 다루기

최문경 블로그 2020. 5. 8. 19:49
 

Nomad Coders

% Complete

academy.nomadcoders.co

 

 

Mongoose 설치와 사용방법

이 수업에서는 데이터베이스로 MongoDB를 사용했다. 그리고 MongoDB를 Node.js에서 사용할 수 있게 도와주는 것이 Mongoose이다.

 

설치(먼저, MongoDB를 설치해야 함.)

npm i mongoose

사용

//db.js
import mongoose from "mongoose";
import dotenv from "dotenv";
dotenv.config();

mongoose.connect(process.env.MONGO_URL, {
  useNewUrlParser: true,
  useFindAndModify: false,
});

const db = mongoose.connection;

const handleOpen = () => console.log("✅ Connected to DB");
const handleError = () => console.error.bind(console, "connection error:");

db.once("open", handleOpen);
db.on("error", handleError);

 

dotenv는 우리의 중요한 정보들을 숨길 수 있게 도와주는 것이다.

npm i dotenv로 설치한 후, .env파일을 만들어서 그 안에 데이터베이스가 연결되어있는 URL(MONGO_URL)을 넣어주었다.

 

 

 

모델 만들기

models라는 폴더를 만들고 거기에 Video.js파일을 만들었다.

//Video.js
import mongoose from "mongoose";

const VideoSchema = new mongoose.Schema({
  fileUrl: {
    type: String,
    required: "File URL is required",
  },
  title: {
    type: String,
    required: "Title is required",
  },
  description: String,
  views: {
    type: Number,
    default: 0,
  },
  createAt: {
    type: Date,
    default: Date.now,
  },
  comments: [ //Comment.js와 연결
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: "Comment"
    }
  ]
});

const Video = mongoose.model("Video", VideoSchema);
export default Video;

 

마지막에서 두 번째 줄이 처음에는 잘 이해가 안 되었는데, Mongoose홈페이지의 글을 보고 이해됐다. model함수는 스키마의 복사본을 만들어준다고 한다. 그러니까 마지막에서 두 번째 줄의 의미는 VideoSchema를 사용해 "Video"라는 이름의 모델을 만들고 나서 VideoSchema의 복사본을 Video에 넣는 것이다.

 

 

각 비디오에 댓글도 있으니까 Comment.js도 추가한다. (둘을 연결하는 코드는 둘 중 하나에 쓰면 된다. 여기서는 Video.js에 씀)

import mongoose from "mongoose";

const CommentSchema = new mongoose.Schema({
  text: {
    type: String,
    required: "Text is required"
  },
  createdAt: {
    type: Date,
    default: Date.now
  }
});

const Comment = mongoose.model("Comment", CommentSchema);
export default Comment;

 

 

 

업로드하기(Create)

먼저, multer모듈을 설치해준다. multer는 파일 전송을 도와주는 모듈이다.

 

사용방법

먼저, upload 하는 form에 가서 enctype="multipart/form-data"를 꼭 추가해줘야한다.

그리고 아래처럼 미들웨어에 코드를 추가하고 router도 수정한다.

//middleware.js
import multer from "multer";

const multerVideo = multer({ dest: "uploads/videos/" });

export const uploadVideo = multerVideo.single("videoFile");

//videoRouter.js
//videoRouter.post(routes.upload, postUpload);
videoRouter.post(routes.upload, uploadVideo, postUpload);

 

마지막으로 postUpload컨트롤러를 추가해준다.

import Video from "../models/Video";

export const postUpload = async (req, res) => {
  const {
    body: { title, description },
    file: { path }
  } = req;
  const newVideo = await Video.create({
    fileUrl: path,
    title,
    description
  });
  res.redirect(routes.videoDetail(newVideo.id));
};

multer덕분에 req.file에서 사용자가 upload 할 때 보내온 정보들과 multer가 추가적으로 만든 정보들을 얻을 수 있다. 그래서 우리는 Video모델에 id를 정의하지 않았지만, multer가 id를 만들어주었기 때문에 newVideo.id를 사용할 수 있다. 그리고 자바스크립트는 기본적으로 비동기 방식으로 동작하기 때문에 Video.create가 끝나기 전에 밑의 코드가 실행될 수 있다. 그래서 await을 사용해 동기로 바꿔준다.

 

MongoDB에 데이터를 추가하는 것은 완료되었으니 이제 데이터를 가져와서 보여주면 된다.

 

home컨트롤러를 수정해주는 데, 아래와 같이 모든 데이터를 가져와서 home.pug에 넘겨주면 된다.

import Video from "../models/Video";

export const home = async (req, res) => {
  try {
    const videos = await Video.find({});
    res.render("home", { pageTitle: "Home", videos });
  } catch (error) {
    console.log(error);
    res.render("home", { pageTitle: "Home", videos: [] });
  }
};

 

 

 

수정하기(Update)

findOneAndUpdate함수를 사용하면 몽구스가 업데이트를 해준다.

export const getVideoEdit = async (req, res) => {
  const {
    params: { id },
  } = req;
  try {
    const video = await Video.findById(id);
    res.render("videoEdit", { title: `Edit ${video.title}`, video });
  } catch (error) {
    res.redirect(routes.home);
  }
};

export const postVideoEdit = async (req, res) => {
  const {
    params: { id },
    body: { title, description },
  } = req;
  try {
    await Video.findOneAndUpdate(id, { title, description });
    res.redirect(routes.videoDetail(id));
  } catch (error) {
    res.redirect(routes.home);
  }
};

 

 

 

삭제하기(Delete)

findOneAndDelete함수를 사용하면 몽구스가 삭제해준다. (단, 데이터베이스에 있는 데이터만 지워지고 uploads밑에 있는 파일들은 지워지지 않는다.)

export const videoDelete = async (req, res) => {
  const {
    body: { id },
  } = req;
  try {
    await Video.findOneAndDelete(id);
  } catch (error) {}
  res.redirect(routes.home);
};