Video Detail

0_CyberLover_0·2022년 4월 12일
0

Node.JS # 03

목록 보기
13/19

전 파트에서 문제가 되었던건 영상을 클릭하면 영상의 id의 주소로 보내지는데 랜덤하게 나타난다.

물론 이건 mixin에서 설정한 대로 실행중이다.

그러나 문제는 video router가 주소를 어떻게 다뤄야 하는지 모른다.

videoRouter.js에서

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);
.route("/:id(\\d+)")

그 이유는 router에 추가할 수 있는 Regular Expression(정규표현식)

이라는 것 때문에 생기는 거다.

이건 숫자만으로 구성된 id를 다룰 때는 좋지만 mongoDB가 만들어낸 id 포맷과는 맞지 않는다.

그래서 이 에러 메세지가 뜨는 거다.

Cannot GET /videos/6252a57c867de2bae69b9f31

idedit, upload도 다 digit(숫자)가 아니기 때문이다.

하나의 방법은 이 코드를 제거해 주는 건데

videoRouter.route("/:id").get(watch);

이렇게 되면 watch controller가 실행 된다. 이 작업으로 template에서 에러가 생겼지만 괜찮다.

이제 중요한건 watch controller가 실행 된다.

근데 문제는 upload video에 들어가도 watch controller가 실행 된다.

videoRouter.route("/upload").get(getUpload).post(postUpload);
("/upload")

이 현상은 전에도 한 번 봤던 거지만 express에서 이건 id를 뜻할 뿐이다.

이를 해결하는 방법은 upload를 맨위로 올려주는 거다.

const videoRouter = express.Router();

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

이런 식으로 말이다.

그러고 나면 upload는 정상적으로 작동 하고 있다.

하지만 home에서 video를 들어가면 여전히 에러가 나고 있다.

이런식으로 해결하는 방법도 괜찮다. upload를 맨 위에 두는 것만 기억해주면 된다.

맨 위에 upload를 안 올리면 expressuploadid로 착각할 것이다.

또 다른 방법은 documentation에 있는데 이 방법을 사용 할거다.

documentation에서 mongoDB id에 대해 조사해서 이걸로 regular expression을 만들어 본다.

일단 documentation에 들어가면

https://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html

id (string) – Can be a 24 byte hex string, 

id는 24byte hexadecimal string(24바이트 16진수)라 정의 되어 있다.

이게 핵심이다. 24자의 string hexadecimal string(16진수)의 뜻을 모른다면

https://www.google.com/search?q=hexadecimal&oq=hexadecimal&aqs=chrome..69i57.318j0j1&sourceid=chrome&ie=UTF-8

구글에 검색해 보면 0에서 9까지의 숫자와 여섯개 기호로 이루어진 string이다.

0에서 9 그 다음 A에서 F까지 다행히 이 값을 쉽게 regular expression으로 만들수 있다.

먼저 regular exprssion을 실험해 본다.

https://www.regexpal.com/

일단 video 의 랜덤한id 값을 복사해서 해당 사이트에 붙여 준다.

test string칸에 이렇게 작성해 준다.

/videos/6252a57c867de2bae69b9f31
/videos/1
/videos/upload

Rugular Expression 칸에는 이렇게 작성해준다.

[0-9a-f]{24}

이제 24자가 0부터 9 그리고 a부터 f와 맞는지 확인 할거다.

이걸로 원하는 regular expression을 만들었다.

regular expression은 개발자들에게 매우 유용하니까 더 공부해 보자.

하지만 현재는 이걸로 끝이다. 모든 hexadecimal값을 찾아서 24자와 매치 시킬거다.

0부터 9 그리고 a부터 f까지의 24자 string을 찾아내는 거다. 이게 패턴이다.

다시 복습해보면 두가지 해결책이 있다.

하나는 upload를 맨 위로 올리는 것이고 나머진 hexadecimal값을 배워서 적용하는 거다.

videoRouter.js에서

const videoRouter = express.Router();

videoRouter.get("/:id([0-9a-f]{24})", watch);
videoRouter.route("/:id([0-9a-f]{24})/edit").get(getEdit).post(postEdit);
videoRouter.route("/upload").get(getUpload).post(postUpload);

이렇게 작성해 준다. 보다시피 이제 videosupload 모두 정상 작동한다.

하지만 여전히 watch controller가 실행 상태이다.

지금 해결해 보도록 한다.

regular expression을 알게 되었으니 이젠 너무(?) 쉬울거다.

이제 watch에서 뭐가 문제 인지 보도록 한다.

videoController.js에서 확인해 보면

export const watch = (req, res) => {
  const { id } = req.params;
  return res.render("watch", { pageTitle: `Watching` });
};

watch templaterender 되고 있다.

그리고 watch.pug에서 보면

extends base.pug

block content
   h3 #{video.views} #{video.videws === 1 ? "view" : "views"}
   a(href=`${video.id}/edit`) Edit Video →

h3 #{video.views}를 확인할수 있는데 하지만 video에는 현재 views가 없는 상태이다.

Cannot read properties of undefined (reading 'views')

그리고 undefinedviewsproperty를 부르지 못하고 있다.

이 말은 정의 되지 않은 무엇 안에서 views를 못 찾고 있음을 말한다.

맞는 말이다. 왜냐하면 video를 전송 안 하는데

templatevideo를 전송 받아야 작동하기 때문이다.

이걸 해결하기 위해 이 코드를 삭제하고

block content
   p=video.description
   small=video.createdAt 
   a(href=`${video.id}/edit`) Edit Video →

이렇게 추가해준다. 비디오는 description을 갖고 있다는 걸 기억해야 한다.

이렇게 해도 기존 에러는 계속 존재 한다.

p=video.description

이건 아직 videoundefined상태이기 때문이다.

그렇기 때문에 descriptionundefined인 거다.

그럼 이제 video를 정의해 준다.

현재 video는 없다. id는 가지고 있다.

videoController.js에서

export const watch = (req, res) => {
  const { id } = req.params;
  return res.render("watch", { pageTitle: `Watching` });
};

idconsole.log해서 존재를 확실히 해준다.

export const watch = (req, res) => {
  const { id } = req.params;
  console.log(id);
  return res.render("watch", { pageTitle: `Watching` });
};

이렇게 하고 새로고침을 하게 되면 터미널에 id가 나오게 된다.

✅ Server listening on port http://localhost:4000 🚀
✅Connected to DB
6252a57c867de2bae69b9f31

이제 이건 idvideo를 찾을수 있다는 말이다.

https://mongoosejs.com/docs/queries.html

queries 관련 문서를 확인해 보면 적용 할수 잇는 다양한 옵션들이 존재한다.

이 중에서 findByidfindOne을 사용해 줄거다.

findOne은 보내는 모든 condition을 적용시켜 준다.

await Adventure.findOne({ country: 'Croatia' }).exec();

예를 들어 조회수가 25인 영상을 찾을 수 있다.

findByidid로 영상을 찾아 낼수 있는 기능을 지원해 준다.

await Adventure.findById(id).exec();

그래서 일단 findByid를 사용해 준다.

videdController.js에서

export const watch = async (req, res) => {
  const { id } = req.params;
  const video = await Video.findById(id);
  console.log(video);
  return res.render("watch", { pageTitle: `Watching` });
};

const video = await 라고 적은 다음에 async가 없으면 await를 쓸수 없다는 것도 기억하도록 한다.

findByIdid가 필요 한데 idreq.params에서 오고 있으니 id를 그냥 적어 주면 된다.

req.paramrouter가 주는 express의 기능인 것만 알면 된다.

그리고 console.log(video)를 넣어줘서 잘 작동 하는지 확인 한다.

연결에는 이상이 없고 기록을 보면 터미널을 보면 해당 video의 정보가 존재 한다.

URL에서 id를 받고 있다. 왜냐하면 router가 여기에 있기 때문이다.

videoRouter.js에서

/:id([0-9a-f]{24})

이제 idreq.params에 전송되고 그 다음 video를 검색하는 거다.

videoawait하고 mongoose에서 지원 해주는 findById를 실행 한다.

그리고 그 id에 대한 검색이 끝나면 video가 불려 지는 거다.

이제 watch templatevideo를 전송해 주도록 한다.

왜냐하면 watch templatevideo를 정의 되지 않았기 때문이다.

export const watch = async (req, res) => {
  const { id } = req.params;
  const video = await Video.findById(id);
  console.log(video);
  return res.render("watch", { pageTitle: `Watching`, video });
};

이렇게 작성해 준다. 이제 새로고침 해준다. 이번엔 제대로 작동 한다.

그리고 이 코드를 div안에 넣어 준다.

watch.pug에서

block content
   div
      p=video.description
      small=video.createdAt 
   a(href=`${video.id}/edit`) Edit Video →

이렇게 해주면 좀더 완성에 가까워 진다. 이 작업으로 detail 화면도 접속 가능해 졌다.

이제 해야 하는것이 하나 더 남아 있다. title을 마무리 해야 한다.

watching 대신 videotitle을 전송 시켜 주는게 좋을것 같다.

vidoeController.js에서

export const watch = async (req, res) => {
  const { id } = req.params;
  const video = await Video.findById(id);
  return res.render("watch", { pageTitle: video.title, video });
};

그리고 pageTitlebase.pug에서 다루고 있다. 이렇게 하면 된다.

새로고침 해서 확인해 보면 title이 잘 나온다.database에서 보내진 모든 데이터가 보이고 있다.

이걸로 모든 video를 볼수 있게 되었다. 각 영상의 상세 페이지에도 접속 할수 있게 되었다.

다음 파트에서는 video수정에 대해 알아 보도록 한다.

idreq.params에서 오는 걸 꼭 기억했으면 한다.

const { id } = req.params;
  const video = await Video.findById(id);
/:id([0-9a-f]{24})

이 코드가 express를 시켜서 URL을 인식 하도록 만들었기 때문이다.

또 24자리 hexadecimal값의 regular expression을 만들었다.

그 값이 MongoDB id와 매칭되서 각 url이 만들어 진거다.

profile
꿈꾸는 개발자

0개의 댓글