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
를 쓰겠다는 거다.