Creating a Video # 01

0_CyberLover_0·2022년 4월 10일
0

Node.JS # 03

목록 보기
9/19

전 파트에서 배웠듯이 schema는 비디오의 형태를 정의 해준다.

video.js에서 살펴보면

import mongoose from "mongoose";

const videoSchema = new mongoose.Schema({
  title: String,
  description: String,
  createdAt: Date,
  hashtags: [{ type: String }],
  meta: {
    views: Number,
    rating: Number,
  },
});

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

보이다시피 영상의 각 구성요소와 데이터 형태를 보여주고 있다.

이걸 이해했다면 사용자가 비디오를 업로드 할때 해당 schema의 데이터들을 보내줄 수 있다.

물론 생성일이나 meta데이터는 사용자에게 자동으로 제공해 준다.

비디오를 업로드하는 사람은 title, description, hashtags 만 올려주면 된다.

upload를 위한 view를 바꿔 준다.

upload.pug에서

extends base.pug

block content 
    form(method="POST", action="/videos/upload")
        input(name="title", placeholder="Title", requried, type="text")
        input(name="Description", placeholder="Description", requried, type="text")
        input(name="Hashtags", placeholder="Hashtags, separated by comma.", requried, type="text")
        input(type="submit", value="Upload Video")

참고로 모든 input에는 name을 부여해야 한다.

이걸로 필요한 구성 요소들은 완성이 되었다. 한번 더 강조 하지만 각기 다른 name을 꼭 부여해야 한다.

browser를 새로고침 해주면 필요 요소들이 추가 된걸 알수 있다.

이제 controllerform을 다룰 수 있게 만들어 준다.

여기서 꼭 기억해야 하는 것은 form에는 URL이란 action이 있다.

    form(method="POST", action="/videos/upload")

그리고 만약 이 부분을 삭제 한다면 HTML은 이 URL 또는 form이 부여해주는 주소로 간다.

이전과 같으니까 코드를 정리해 주도록 한다.

    form(method="POST")

그리고 이 시점에서 router를 어떻게 구성 했는지 되돌아 본다.

videoRouter.js로 가서 보면

import express from "express";
import { get } from "express/lib/response";
import {
  watch,
  getEdit,
  postEdit,
  getUpload,
  postUpload,
} from "../controllers/videoController";

const videoRouter = express.Router();

videoRouter.route("/:id(\\d+)").get(watch);
videoRouter.route("/:id(\\d+)/edit").get(getEdit).post(postEdit);
videoRouter.route("/upload").get(getUpload).post(postUpload);

export default videoRouter;

upload가 있고, templaterender하는 getUpload가 있다.

그리고 지금 다루게 될 postUpload가 있다.

다시 videoController.js로 가서 보면

postUpload는 현재 title만 다루고 있다. 왜냐하면 이전에 그렇게 구성했기 때문이다.

하지만 이제 descriptionhashtags가 추가 되었다.

그러니 controller function에 위 두개를 추가해 준다.

export const postUpload = (req, res) => {
  const { title, Description, Hashtags } = req.body;
  return res.redirect("/");
};

이걸로 descriptionhashtags도 추가 되었다.

export const postUpload = (req, res) => {
  const { title, Description, Hashtags } = req.body;
  console.log(title, Description, Hashtags);
  return res.redirect("/");
};
  console.log(title, Description, Hashtags);

추가 해줬다. 지금하고 있는 것은 전에 배운 내용에 대한 짧은 복습이다.

form이 데이터베이스에게 데이터를 전송 해주는걸 볼거다.

해당 정보를 upload화면을 통해 전송해본다. 새로고침을 한다음 빈 공백에 문자를 넣어주고

upload를 누르면 redirect이 된다.

이 동작은 정상적인게 해당 코드가 home으로 보내지도록 만들었다.

console에 이 세가지가 출력 되어야 한다.

터미널을 통해 확인해 보면

✅ Server listening on port http://localhost:4000 🚀
✅Connected to DB
GET /videos/upload 304 176.113 ms - -
dsfasf ehfdhdgn sdfhs
POST /videos/upload 302 27.095 ms - 46
GET / 304 64.110 ms - -

순서대로 잘 나오고 있다.

자 이제 비디오를 어떻게 만들어야 할까?

이걸하기 위해 document를 만들어 줘야한다. document는 데이터를 가진 비디오라 생각하면 된다.

그리고 documentdatabase에 저장해야 한다. 그럼 일단 document만드는거 부터 해본다.

export const postUpload = (req, res) => {
  const { title, description, hashtags } = req.body;
  const video = new Video({
    title,
    description,
    createdAt: Date.now(),
    hashtags: hashtags.split(",").map((word) => `#${word}`),
    meta: {
      views: 0,
      rating: 0,
    },
  });
  return res.redirect("/");
};
  const video = new Video({})

이 코드 안에 video model의 구성 요소들을 담아준다.

video.js에서 보면서

const videoSchema = new mongoose.Schema({
  title: String,
  description: String,
  createdAt: Date,
  hashtags: [{ type: String }],
  meta: {
    views: Number,
    rating: Number,
  },
});

title,description,createdAt,hashtags,meta를 추가해 주었다.

createdAt의 경우 data.now를 부여해 주는데 data.now의 값은 다음과 같다.

consoledata.now() 입력 해보면 나오는 숫자는 1970년1월1일0시0분0초부터 현재까지의 milliseconds라고 한다.

현재 schema와 같은 모양으로 document를 만들었다.

차이점이 있다면 document는 실제 데이터를 담는 다는 것이다.

 title,
    description,

이런 단축 코드로 입력 하는게 싫을수도 있는데 사실 이렇게 적는 것과 의미는 똑같다.

	title:title<,
   description:description,

왼쪽 titleschema의 것이고 오른쪽 titlerequest.body 안의 것을 뜻한다.

hashtagsstring으로 구성된 array인 점을 고려해야 하는데

console환경에서 위와 관련된 frontendbackend의 관련된 몇가지 실험을 할거다.

이에 대한 예제를 보도록 하자.

"hello,food,totally,delis" 사용자가 우리에게 이 정보를 보내줬다고 한다.

이 상황에서 split라 불리는 function을 사용해 준다.

"hello,food,totally,delis".split(",")

splitstring들을 분리 하는 기능을 가지고 있다.

spliter또는 separator가 그 분리의 기분이 되는데 쉼표를 기준으로 해준다.

이 코드는 쉼표를 볼때 마다 string을 나눠 줄거다.

(4) ["hello","food,""totally","delis"]

결과는 이런식으로 array를 가지게 된다. 이게 바로 array를 만드는 방식이다.

이걸 hashtags에 적용해 줄건데 아주 쉽고 아주 효율적이다.

이게 사용자에게 uploadhashtag를 쉼표로 나누라고 한 이유이다.

다른 방법으로 예제를 보면

"#hello,#hi,#lalala".split(",")이렇게 입력 하면

(3) ["#hello","#hi","#lalala"] 된다.

string에 #(해시태그)가 없다면 #(해시태그)가 없는 상태에서 추가하고 싶으면

두가지 function을 이어서 실행해주면 된다.

"food,movies,music".split(",") 먼저 split을 해주고

(3) ["food","movies","music"] 그럼 이 상태로 console에 입력 되어 있고

"food,movies,music".split(",").map(word => #${word}) 그 다음 map을 실행 시켜준다.

그리고 모든 단어들 앞에 #(해시태그)을 붙여준다.

(3) ["#food","#movies","#music"]

array를 만들어 단어별 분리를 시킨 다음 #을 붙여 줄거다.

이게 바로 hashtags코드를 구성하는 원리가 된다.

먼저 hashtags의 존재를 확실히 해줘야한다.

하지만 이 부분에서 이미 required된 상태라 크게 걱정 할 필요는 없을 듯하다.

form을 믿어 보도록 한다.

    hashtags: hashtags.split(",").map((word) => `#${word}`),

그래서 이렇게 입력 하게 되었다. 그리고 보다시피 video object하나가 완성 되었다.

  const video = new Video({
    title,
    description,
    createdAt: Date.now(),
    hashtags: hashtags.split(",").map((word) => `#${word}`),
    meta: {
      views: 0,
      rating: 0,
    },

이 부분은 실재 하는 데이터와 관련되어 있다. form에서 전송되는 데이터 말이다.

이걸로 hashtags가 완성 되었다.

그럼 이제 video를 한번 console.log해본다.

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

export const home = async (req, res) => {
  const videos = await Video.find({});
  return res.render("home", { pageTitle: "Home", videos });
};
export const watch = (req, res) => {
  const { id } = req.params;
  return res.render("watch", { pageTitle: `Watching` });
};

export const getEdit = (req, res) => {
  const { id } = req.params;
  return res.render("Edit", { pageTitle: `Editing` });
};
export const postEdit = (req, res) => {
  const { id } = req.params;
  const { title } = req.body;
  return res.redirect(`/videos/${id}`);
};

export const getUpload = (req, res) => {
  return res.render("upload", { pageTitle: "Upload Video" });
};

export const postUpload = (req, res) => {
  const { title, description, hashtags } = req.body;
  const video = new Video({
    title,
    description,
    createdAt: Date.now(),
    hashtags: hashtags.split(",").map((word) => `#${word}`),
    meta: {
      views: 0,
      rating: 0,
    },
  });
  console.log(video);
  return res.redirect("/");
};
console.log(video);
  return res.redirect("/");

new video를 실행 시키게 되는데 이걸 console.log하고 home 화면으로 넘어간다.

여기서 한가지 의문점이 든다. 방금의 작업이 database상에 저장이 될까..?

확인해 보도록 한다. 새로고침 해주고 빈칸을 채워 주고 upload한다.

결과로 보자면 아직 database상에 아무것도 존재하지 않는다.

하지만 console에서 보여주는 결과 값은 상당히 잘 나와 있다.

GET /videos/upload 200 16.410 ms - 754
{
  title: 'Video 1',
  description: 'Best JS',
  createdAt: 2022-04-10T08:36:39.589Z,
  hashtags: [ '#hi', '#how', '#are', '#you' ],
  meta: { views: 0, rating: 0 },
  _id: new ObjectId("625297179ddafe0e40ee48d7")
}
POST /videos/upload 302 12.340 ms - 46
GET / 304 23.606 ms - -

이 형식은 설계한 video랑 똑같다. hashtahsstring으로 된 array이고

title있고 description있고 date도 있고 meta도 있어 그리고 마지막으로

생성된 고유 id도 있다. mongooseid를 부여 해준거다.

왜냐하면 objectdocument처럼 ID가 있어야 하기 때문이다.

고유식별번호가 꼭 필요한데 그걸 다 일일이 다 지정해 줘야 할 필요가 없다.

시스템이 알아서 랜덤한 id를 부여한다.

잠시 mongo console로 돌아가서 (터미널에서 mongo를 친다음 show dbs를 쳐준다.)

(wetube database폴더가 존재하고 있는데 왜 존재하는지는 모르겠다.

강의에서는 아직 존재 하지 않는 걸로 나오고 있는데 일단 넘어가도록 한다.)

home에서 새로고침을 하면 아직 아무 영상도 없다.

video에 대한 정보가 database에 존재하지 않는다. 이게 무슨 일이냐면

video를 만든 것은 맞다. 그리고 objectjavascript 세계에서는 존재한다.

하지만 아직 저장이 안 된 상태 이다.

profile
꿈꾸는 개발자

0개의 댓글