전 파트에서 문제가 되었던건 영상을 클릭하면 영상의
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
이 id
나 edit
, 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
를 안 올리면 express
는 upload
를 id
로 착각할 것이다.
또 다른 방법은
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진수)
의 뜻을 모른다면
구글에 검색해 보면 0에서 9까지의 숫자와 여섯개 기호로 이루어진 string
이다.
0에서 9 그 다음 A
에서 F
까지 다행히 이 값을 쉽게 regular expression
으로 만들수 있다.
먼저
regular exprssion
을 실험해 본다.
일단 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);
이렇게 작성해 준다. 보다시피 이제 videos
와 upload
모두 정상 작동한다.
하지만 여전히 watch controller
가 실행 상태이다.
지금 해결해 보도록 한다.
regular expression
을 알게 되었으니 이젠 너무(?) 쉬울거다.
이제 watch
에서 뭐가 문제 인지 보도록 한다.
videoController.js
에서 확인해 보면
export const watch = (req, res) => {
const { id } = req.params;
return res.render("watch", { pageTitle: `Watching` });
};
watch template
가 render
되고 있다.
그리고 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')
그리고 undefined
된 views
의 property
를 부르지 못하고 있다.
이 말은 정의 되지 않은 무엇 안에서 views
를 못 찾고 있음을 말한다.
맞는 말이다. 왜냐하면 video
를 전송 안 하는데
template
은 video
를 전송 받아야 작동하기 때문이다.
이걸 해결하기 위해 이 코드를 삭제하고
block content
p=video.description
small=video.createdAt
a(href=`${video.id}/edit`) Edit Video →
이렇게 추가해준다. 비디오는 description
을 갖고 있다는 걸 기억해야 한다.
이렇게 해도 기존 에러는 계속 존재 한다.
p=video.description
이건 아직 video
가 undefined
상태이기 때문이다.
그렇기 때문에 description
도 undefined
인 거다.
그럼 이제
video
를 정의해 준다.
현재 video
는 없다. id
는 가지고 있다.
videoController.js
에서
export const watch = (req, res) => {
const { id } = req.params;
return res.render("watch", { pageTitle: `Watching` });
};
id
를 console.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
이제 이건 id
로 video
를 찾을수 있다는 말이다.
https://mongoosejs.com/docs/queries.html
queries
관련 문서를 확인해 보면 적용 할수 잇는 다양한 옵션들이 존재한다.
이 중에서 findByid
와 findOne
을 사용해 줄거다.
findOne
은 보내는 모든 condition
을 적용시켜 준다.
await Adventure.findOne({ country: 'Croatia' }).exec();
예를 들어 조회수가 25인 영상을 찾을 수 있다.
findByid
은 id
로 영상을 찾아 낼수 있는 기능을 지원해 준다.
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
를 쓸수 없다는 것도 기억하도록 한다.
findById
는 id
가 필요 한데 id
는 req.params
에서 오고 있으니 id
를 그냥 적어 주면 된다.
req.param
은 router
가 주는 express
의 기능인 것만 알면 된다.
그리고 console.log(video)
를 넣어줘서 잘 작동 하는지 확인 한다.
연결에는 이상이 없고 기록을 보면 터미널을 보면 해당 video
의 정보가 존재 한다.
URL
에서 id
를 받고 있다. 왜냐하면 router
가 여기에 있기 때문이다.
videoRouter.js
에서
/:id([0-9a-f]{24})
이제 id
는 req.params
에 전송되고 그 다음 video
를 검색하는 거다.
video
를 await
하고 mongoose
에서 지원 해주는 findById
를 실행 한다.
그리고 그 id
에 대한 검색이 끝나면 video
가 불려 지는 거다.
이제
watch template
에video
를 전송해 주도록 한다.
왜냐하면 watch template
가 video
를 정의 되지 않았기 때문이다.
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
대신 video
의 title
을 전송 시켜 주는게 좋을것 같다.
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 });
};
그리고 pageTitle
은 base.pug
에서 다루고 있다. 이렇게 하면 된다.
새로고침 해서 확인해 보면 title
이 잘 나온다.database
에서 보내진 모든 데이터가 보이고 있다.
이걸로 모든 video
를 볼수 있게 되었다. 각 영상의 상세 페이지에도 접속 할수 있게 되었다.
다음 파트에서는 video
수정에 대해 알아 보도록 한다.
id
가 req.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
이 만들어 진거다.