
Video를 user와 연결하는 작업을 해본다.
현재는 video와 user가 서로 연결되어 있지 않다.
mongoose나 mongodb를 활용해 연결하려면 id를 사용해야 한다.
왜냐하면 id는 하나밖에 없고 랜덤 숫자이기 때문이다.
그러면 현재 가지고 있는 id를 가지고 연결해 보도록 하겠다.
user에는 해당 user가 업로드한 모든 영상의 id를 저장 해준다.
그리고 video에는 해당 영상을 올린 user의 id를 저장한다.
현재는 이해하지 못해도 코드를 보면 알게 될거다.
먼저 videoSchema에 owner를 추가해준다.
video.js에서
const videoSchema = new mongoose.Schema({
title: { type: String, required: true, trim: true, maxLength: 80 },
fileUrl: { type: String, reqired: true },
description: { type: String, required: true, trim: true, maxLength: 20 },
createdAt: { type: Date, required: true, default: Date.now },
hashtags: [{ type: String, trim: true }],
meta: {
views: { type: Number, default: 0, required: true },
rating: { type: Number, default: 0, required: true },
},
ower: { type: mongoose.Schema.Types.ObjectId, reqired: true, ref: "User" },
});
owner의 type은 number,string,date가 아니고 objectId이다.
그러나 objectId문자 그대로 쓰면 코드가 노란색이 아니다.
위에 코드들을 보면 노랑색으로 활성화된 코드들은 JavaScript에서 제공하는 코드이다.
그런데 object는 mongoose코드에서만 사용 할수 있다.
그래서 이런식으로 작성할수가 있다.
ower: { type: mongoose.Schema.Types.ObjectId, reqired: true, ref: "User" },
그리고 required: true를 추가해준다. reference도 추가해줄 필요가 있는데
그 이유는 mongoose에게 owner에 id를 저장하겠다고 알려줘야 하기 때문이다.
그런데 아직 어떤 model과 연결할지 알려주지도 않은 상태이다.
수많은 model이 있으면 어떤 것과 연결할 것인지 알려줘야 한다.
그래서 mongoose에게 이 owner가 어떤 model의 object라고 알려준다.
여기서는 User model이 된다. 그래서 "User"이라고 넣어 주었다.
이제 video에 owner 항목이 추가 되었다.
owner은 object ID이다. object ID는 여기 보이는 긴 string이다.
ObjectId("626a5e7f2a8175076f7a1e45"
이게 바로 object ID이다.
여기에서 중요한건 Mongoose에게 이 object ID가 model user에서 온다고 알려주는거다.
이렇게 해야 Mongoose가 도와 줄수 있다.
이제 github로그인을 통해 계정을 생성해 준다.
그리고 영상을 하나 업로드 해주기 전에 controller에 수정해줄 부분이 있다.
이제 영상을 업로드 할때 업로드 하는 사용자의 id를 전송해야 하기 때문이다.
videoController.js에서
postUpload controller에 user관련 코드를 추가 한다.
export const postUpload = async (req, res) => {
const {
user: { _id },
} = req.session;
const { path: fileUrl } = req.file;
const { title, description, hashtags } = req.body;
try {
await Video.create({
title,
description,
fileUrl,
owner: _id,
hashtags: Video.formatHashtags(hashtags),
});
user는 req.session에서 가져오면 된다. 그리고 user에서 _id를 가져온다.
그리고 Video를 생성할때 owner도 보내도록 만들어 준다.
Video.create()는 자주 다뤄 봐서 익숙하다. mongoose의 create과 save 같은거 말이다.
video model에 object ID type을 가진 owner property를 추가 했다.
그래서 owner의 _id만 써주면 된다.
user object전체를 전송할 필요는 없고 id만 전송해주면 되는 거다.
이제 다시 영상을 선택해주고 업로드까지 해준다. 영상 재생까지 잘 되는걸 확인 할수 있다.
database도 확인해 본다. db.videos.find({})를 해보면 이제 video에 owner가 추가 된걸 알수 있다.
이 owner는 ObjectId이다.
성공적으로 model들을 user와 연결 시켰다. 현재는 그렇게 대단하게 보이지 않지만
populate를 배우게 되는 순간부터는 달라 질거다.
populate가 왜 중요한지에 대해 알아 보겠다.
그 이유는 populate가 있어야 영상 주인만 아래 버튼이 보이기 때문이다.
(Edit Video와 Delete Video 버튼을 말한다. )
그리고 여기에 누가 올렸는지 보여줄 수도 있다.
일단 버튼을 숨기는 기능을 구현해 보도록 한다.
video에 owner의 id가 있다. 그리고 localMiddleware에 현재 로그인된 사용자가 누구인지 알려주는 부분이 있다.
이 말은 로그인된 사람의 id와 영상의 owner의 id가 일치 하면 로그인된 사용자가 현재 영상의 주인이라는 말이다.
template을 수정해 본다. watch.pug를 열고
extends base
block content
video(src="/" + video.fileUrl,controls)
div
p=video.description
small=video.createdAt
small=video.owner
br
small=loggedInUser._id
a(href=`${video.id}/edit`) Edit Video →
br
a(href=`${video.id}/delete`) Delete Video →
id가 일치하는지 체크해준다. 붙어 있으면 일치하는지 헷갈릴수 있으니 띄워 준다.
이렇게 해주면 영상 주인과 현재 로그인된 사용자의 id가 일치하는걸 알수 있다.
이런 상황일때 아래 두 버튼이 보이도록 만들어 본다.
extends base
block content
video(src="/" + video.fileUrl,controls)
div
p=video.description
small=video.createdAt
if String(video.owner) === String(loggedInUser._id)
a(href=`${video.id}/edit`) Edit Video →
br
a(href=`${video.id}/delete`) Delete Video →
if video.owner === loggedInUser._id 이렇게만 해주었을때는 작동을 하지 않는다.
왜냐하면 video.owner의 id는 ObjectId인데 현재 접속자의 id는 string형태의 데이터 이기 때문이다.
그래서 양쪽에 String()을 넣어주었다. 그래서 새로고침 해서 확인해 보면 잘 작동한다.
이제 video의 owner를 확인 할수 있게 되었다.
이렇게 user의 id를 video model에 저장하니까 유용하다.
누가 영상을 업로드 하였는지 확인 할수가 있게 되었다.
video.owner는 string이고 id라는걸 기억하자.
그러나 아직 해결해야 될게 있다. 영상 소유자의 이름을 가져와야 한다.
누가 비디오를 만들었는지 보여주고 그 사람의 프로칠을 볼수 있는 링크를 걸어 줄 수도 있다.
현재 페이지는 watch페이지이다. watch controller를 찾아 본다.
videoController.js에서
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id);
console.log(video);
if (!video) {
return res.status(404).render("404", { pageTitle: "Video not found." });
}
return res.render("watch", { pageTitle: video.title, video });
};
이곳에서 video를 찾고 있다. video를 console.log해본다.
새로고침해서 node에서 찾아 보면
{
meta: { views: 0, rating: 0 },
_id: new ObjectId("6278c6ea843aa2ab1951cb7a"),
title: 'code',
fileUrl: 'uploads/videos/8354fc579bb23fa577b406bccaafe453',
description: 'codecodecodecodecode',
hashtags: [ '#code' ],
owner: new ObjectId("6278ad69eeed5a64dd710d36"),
createdAt: 2022-05-09T07:46:50.207Z,
__v: 0
}
이런 정보가 나온다. owner도 보인다. 이 말은 owner의 id를 알고 있다는거다.
이렇게 적용해 볼수 있다.
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id);
const owner = await User.findById(video.owner);
if (!video) {
return res.status(404).render("404", { pageTitle: "Video not found." });
}
return res.render("watch", { pageTitle: video.title, video, owner });
};
const owner = 그리고 user를 models에서 import한다.
models에서 User를 import를 해준다.
그리고 User.findById(video.owner)를 해준다.
video에는 owner가 있고 이건 user의 id이다.
그러면 video를 찾고 이걸 가지고 owner도 찾는 거다.
return res.render("watch", { pageTitle: video.title, video, owner }
그래서 owner도 추가해 주었다.
그리고 watch.pug에서
extends base
block content
video(src="/" + video.fileUrl,controls)
div
p=video.description
small=video.createdAt
div
small Uploaded by #{owner.name}
if String(video.owner) === String(loggedInUser._id)
a(href=`${video.id}/edit`) Edit Video →
br
a(href=`${video.id}/delete`) Delete Video →
div
small Uploaded by #{owner.name}
이렇게 추가해 주었다.
이게 가능한 이유는 owner를 watch template으로 보냈기 때문이다.
새로고침을 해주면 비디오를 업로드한 유저의 이름이 나오는걸 확인 할수 있다.
video를 먼저 찾고 owner를 찾는거다. DB에는 2번이나 요청해서 조금 마음에는 안들지만 잘 작동하고 있다.
이게 바로 영상 소유자의 id를 video에 저장하면 좋은 이유이다.
이제 영상을 볼때 owner가 누군지도 알수 있다.
하지만 언제나 더 쉬운 방법이 있기 마련이다. 현재 코드도 직관적이고 좋다.
이보다 더 나은 방법이 있으니 그렇게 시도해 보도록 한다.
DB에 2번이나 요청하는건 별로이기 때문이다.
현재는 영상 소유자의 id를 video에 저장하면 좋은 이유를 기억한다.
먼저 영상 소유주와 현재 접속자의 id를 비교 할수 있다. 현재 id만 비교하고 있다.
또한 영상 소유주의 이름을 보여줄수도 있다.
중요한건
postUpload에서video를 생성할때video.owner에 현재 로그인된 사용자의id를 넣어 주었다는 거다.
req.session.user가 현재 로그인된 사용자를 말한다.
이 말은 video의 owner로 현재 로그인 중인 유저의 id를 쓰겠다는 거다.