
오늘은 동적 템플릿인 handlebars.js의 오류인 Access has been denied to resolve the property "from" because it is not an "own property" of its parent 해결법을 다뤄보겠다.
이 에러를 대강 해석해보면 프로퍼티가 상위 프로퍼티에 들어있지 않기에 엑서스 할 수 없다는 의미다. 이런 상황은 다음과 같은 경우에 발생한다.
게시글 모델
const mongoose = require('mongoose');
const postSchema = new mongoose.Schema({
title: String,
content: String,
writer: {
type: mongoose.Schema.Types.ObjectId;
ref: "User"
}
})
위 코드는 post의 db model이다. 이제 여기서 쿼리를 하고 해당 값을 handlebars.js로 넘겨 렌더링해보자. 다음은 쿼리하는 코드다.
const post = await Post.findOne({_id: postId}).populate("User").exec();
이제 이 값을 handlebars.js에서 렌더링하기 위해 res.render의 두번째 인자로 보낸다고 생각해보자
postRouter.js
const post = await Post.findOne({_id: postId}).populate("User").exec();
res.render("postPage", {post})
postPage.hbs
<h1>{{post.string}}</h1>
<p>{{post.writer.name}}</p>
<p>{{post.content}}</p>
이제 에러가 발생할 것이다. mongodb에서 쿼리한 document는 BSON이기 때문에 handlebars.js에서 일반 배열, 객체처럼 접근할 수 없는 것이다. 그렇다면 어떻게 해야 할까?
바로 lean( )메서드를 사용하면 된다. lean( )메서드는 몽고디비의 document를 JS객체로 만들어준다. 즉 이 값을 res.render의 두번째 인자로 넘기면 정상 작동하게 된다.
postRouter.js
const post = await Post.findOne({_id: postId}).lean().populate("User").exec();
res.render("postPage", {post})
postPage.hbs
<h1>{{post.string}}</h1>
<p>{{post.writer.name}}</p>
<p>{{post.content}}</p>
끝