전 단계에서 영상에 영상 소유자의
id
를 저장해봤다.
DB
를 보면 이 video
를 업로드한 유저의 id
를 볼수 있다.
추가적으로 watch
화면에서 영상 소유자의 이름을 보여주도록 만들었다.
여기까지의 코드를 보고 여기에 쓴 reference
가 무슨 쓸모가 있는지 궁금해 진다.
왜냐하면 video.owner
가 User id
라는걸 아는데 이걸 직접 해주고 있으니 그렇다.
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id);
const owner = await User.findById(video.owner);
const owner = await User.findById(video.owner);
그래서 이 코드를 지워 준다.
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id);
이렇게 하면 owner
가 없으니까 에러가 난다. 그러니 지워 준다.
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id);
if (!video) {
return res.status(404).render("404", { pageTitle: "Video not found." });
}
return res.render("watch", { pageTitle: video.title, video, owner });
};
return res.render("watch", { pageTitle: video.title, video});
그래도 에러가 나오니 좀 이상해 질거다.
하지만 이 작업의 핵심은 같은 기능을 더 짧은 코드로 구현해 보는거다.
여기서 video
를 console.log
해주면 DB
에서 찾은 video
를 확인할수 있을거다.
이 상태에서 브라우저를 새로고침하면 오류가 생길거다.
걱정하지 않아도 된다. 핵심은 node console
에 출력된 video
이다.
이제 mongoose
의 도움을 받아 볼거다.
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
}
mongoose
는 이 objectID
가 User
에서 오는걸 아니까 도와 줄거다.
그래서 mongoose
가 찾게 만들어 볼거다.
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id).populate();
populate
가 뭘 하냐면
owner: new ObjectId("6278ad69eeed5a64dd710d36"),
이 부분을 실제 User
데이터로 채워 준다.
owner
를 populate
해준다.
export const watch = async (req, res) => {
const { id } = req.params;
const video = await Video.findById(id).populate("owner");
owner
만 적어주면 끝이다.
populate
와 relationship
만 적어주면 된다.
그리고 이제 populate
한 video
를 console.log
해본다.
오류는 걱정하지 말고 일단 새로고침을 해본다. 에러가 있지만 코드를 한번 보도록 한다.
차이가 보일 것이다.
video
안에 owner object
전체 정보가 들어와 있다.
populate
하기전의 owner
는 단순히 string
이지만
populate
를 하면 mongoose
가 video
를 찾고 그 안에서 owner
도 찾아 줄거다.
mongoose
는 owner
가 object ID
인 것을 알고 이 id
가 User
에서 온 것임을 안다.
그래서 mongoose
가 해당 User
를 찾고 video
를 로드했을때 User
정보도 얻을수 있다.
id
뿐만 아니라 모든 정보를 볼수 있다는 건 정말 대단한 일이다.
이제 template
만 수정해서 작동하게 만들어 본다.
이전 코드에서는 이 두가지를 string
으로 변환하고 비교 해야했다.
왜냐하면 이전에는 owner
가 id
에 불과 했다. 하지만 이제는 object
이니깐 수정이 필요하다.
watch.pug
에서
if String(video.owner) === String(loggedInUser._id)
if String(video.owner._id) === String(loggedInUser._id)
이 작업만 하면 mongoose
가 나머지는 다 해결해주는 거다.
이제 이 부분의 오류도 해결할수 있다.
기존 코드 대신 video.owner.name
으로 바꿔 볼거다.
small Uploaded by #{owner.name}
small Uploaded by #{video.owner.name}
이런 식으로 바꿔 주고 홈페이지 새로고침을 해주면 작동 되는걸 확인할수 있다.
보다시피 영상 소유자가 보이게 된다. 이 기능은 코드 한줄로 구현 된거다.
이게 바로 mongoose relationship
의 힘이다.
현재 id
만 저장하고 있다. User
전체가 아니라 id
만 저장한다.
DB
에서 populate
를 써도 작동이 되는지 해보니 작동하지 않는다.
populate
는function
이 아니다.
하지만 코드에서 populate("owner")
를 사용하면 owner object
전체가 불려지는걸 볼수 있다.
id
를 저장하고 mongoose
에 이 id
가 User model
에서 왔다고 알려주기만 하면 된다.
그래서 이런식으로 이름을 통일하고 사전에 모든 model
들을 import
하는게 좋은거다.
그래야 mongoose
가 도와 줄수 있다.
이제 여기에 링크를 걸어본다. 소유자 프로필에 갈수 있게 만들어 본다.
이건 다른 populate, relation
을 할수 있게 도와 줄거다.
video
에owner
를 추가하는건 끝났다.
다음 단계는 특정 사용자가 업로드한 모든 영상을 볼 수 있게 만드는 거다.
그러기 위해선 User.js
코드를 수정해야 한다.
이제
watch template
을 수정해 본다.
small Uploaded by #{video.owner.name}
small Uploaded by
a(href=`/users/${video.owner._id}`)=video.owner.name
새로고침하고 링크를 눌러주면 프로필 화면으로 넘어간다.
이제 사용자가 업로드한 영상들을 가져와야 한다.
여러가지 방법이 있는데 이해를 돕기 위해 좀더 긴 코드를 먼저 보도록 한다.
그 다음 짧은 코드를 보도록 한다.
userController.js
를 띄워 준다.
userController
에서 user
를 찾고 있다.
그리고 id
를 owner
로 가진 video
들을 찾을 수도 있다.
export const see = async (req, res) => {
const { id } = req.params;
const user = await User.findById(id);
if (!user) {
return res.status(404).render("404", { pageTitle: "User not found." });
}
export const see = async (req, res) => {
const { id } = req.params;
const user = await User.findById(id);
if (!user) {
return res.status(404).render("404", { pageTitle: "User not found." });
}
const videos = await Video.find({ owner: user._id });
Video
을 쓰고 여러개의 video
를 찾아 올거다.
그리고 findOne
이런거 말고 그냥 find
를 써서 video
의 owner
가 params
의 id
와 같은 video
들을 찾는거다.
video
의 owner id
rk URL
에 있는 id
와 같은 video
를 찾는거다.
추가해 준다. 그리고 import
가 안되는 경우도 있으니 꼭 확인한다.
안되 있으면
import Video from "../models/Video";
추가 해준다.
그리고 video
를 console.log
해주고 새로고침을 해보면 array
가 나온다.
이 URL
의 id
와 video owner id
가 일치한 경우만 나온거다.
현재 지금 user
와 owner
의 id
가 같은 video
들을 찾고 있다.
이것만 해도 충분하다. template
으로 videos
를 보낼수 있다.
const videos = await Video.find({ owner: user._id });
return res.render("users/profile", {
pageTitle: user.name,
user,
videos,
});
users/profile.pug
에서
block content
h1 hello
이 말은 users/profile
에서 hello
대신에 videos
를 보여 줄수 있다는 거다.
videos
를 보여주는 방법은 home
에서 하는 방법 이랑 똑같다.
block content
each video in videos
+video(video)
이렇게 바꿔 줄수 있다.
videos array
를 보내고 each video in videos
를 썼을 뿐이다.
home
하는 방식과 똑같고 mixin
도 사용했다. 코드를 복붙해도 코드가 작동하는데 문제가 없다.
물론 minxin
을 include
해줘야 한다.
include ../mixins/video
왜냐하면 지금 /users/profile.pug
안에 있기 때문이다.
새로고침해서 확인해 보면 유저가 업로드한 영상이 나오고 있다.
home
에서도 다룬거라 새로운 내용은 아니다.
차이점은 profile
의 videos
가 특정 유저의 id
와 owner id
가 같은 video
만 가져 온다는 거다.
그리고 user.id
는 URL
에 있는 id
로 찾은 거다.
하지만 이 방법은 긴 코드로 작성 되었다. 짧게 만들 수도 있다.
하지만 이 지름길을 사용하려면 또 다시 DB
를 초기화 시켜야 한다.
초기화 해야하는 이유는 model
을 수정해야 하기 때문이다.
이제 아무것도 안되고 영상들도 다 사라졌다.
database
를 초기화 하고 다음 파트로 넘어가도록 한다.