본 자료는 Elice 플랫폼의 자료를 사용하여 정리하였습니다.
Hash
Hash 사용하기
const hash = crypto.createHash('sha1'); // sha224, sha256 등 사용가능
hash.update(password);
hash.digest('hex');
const MongoStore = require('connect-mongo');
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: true,
store: MongoStore.create({
mongoUrl: 'mongoUrl',
}),
}));
connect-mongo
패키지를 사용해 express-session 설정 시 store 옵션에 전달하고, mongoUrl을 설정const author = await User.find({
shortId: req.user.shortId,
});
if (!author) {
throw new Error('No User');
}
await Post.create({
title,
content,
author,
});
req.user
에는 strategy에서 최소한의 정보로 저장한 shortId, email, username만 가지고 있다.// ./routes/posts.js
router.get('/', ... {
...
const posts = await Post.find({})
.populate('author');
res.render('posts/list', { posts });
// ./views/posts/list.pug
...
td post.author.name
post.author.{field}
로 사용 가능하다.const post = await Post.find({ shortId, }).populate('author')
if (post.author.shortId !== req.user.shortId) {
throw new Error('Not Authorized');
}
author: {
types: Schema.Types.ObjectId,
ref: 'User',
required: true,
index: true,
},
index: true
옵션을 사용하면 mongoose가 자동으로 MongoDB에 인덱스를 생성해준다.// ./routes/users.js
router.get('/:shortId/posts', ... => {
...
const { shortId } = req.params;
const user = await User.find({ shortId });
const posts = await Post.find({ author: user }).populate('author');
res.render('posts/list', { posts, user });
});
/users/{userId}/posts
로 구성h2= user ? `${user.name}의 게시글`: "전체 게시글"
...
td: a(href=`/users/${post.author.shortId}/posts`) = post.author.name
"###의 게시글"
이라는 제목 사용// posts/view.pug
...
table
thead
tr
td(colspan="2")
input#content(type="text")
td: button(onclick="writeComment()")
댓글 작성
tbody#comments
template#comment-template
tr
td.content
td.author
td.createdAt
const CommentSchema = new Schema({
content: String,
author: {
type: Schema.Types.ObjectId,
ref: 'User',
},
}, {
timestamps: true,
});
const PostSchema = new Schema({
...
comments: [CommentSchema],
...
router.post('/posts/:shortId/comments', ... {
const { shortId } = req.params;
const { content } = req.body;
const authro = await User.findOne({ shortId: req.user.shortId });
await Post.updateOne({ shortId }, {
$push: { comments: {
content,
author,
}},
});
res.json({ result: 'success' });
});
api/posts/{postId}/comments
경로로 댓글 작성 기능 구현$push
를 사용하여 comments 배열에 새로 작성된 댓글 추가 동시에 들어오는 요청에 대해 정확하게 처리...
router.post('/posts/:shortId/comments', ... {
const { shortId } = req.params;
const post = await Post.findOne({ shortId });
await User.populate(post.comments, {
path: 'authro'
});
res.json(post.comments);
});
/api/posts/{postId}/comments
로 RESTful 경로 설정...
script.
function writeComment() {
const input = document.querySelector('#content')
const content = input.value;
fetch('/api/posts/#{post.shortId}/comments', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content }),
})
.then(() => {
if (res.ok) {
input.value = '';
loadComments();
} else {
alert('오류가 발생했습니다.');
}
});
writeComment()
실행input#content
에서 내용을 읽어 fetch로 댓글 작성 api 호출// 댓글 목록 api 호출하기
script.
loadComments();
function loadComments() {
document
.querySelector('#comments')
.innerHTML = '', // 이전 목록 삭제
fetch('/api/posts/#{post.shortId}/comments')
.then((res) => {
if (res.ok) {
return res.json();
} else {
throw new Error('댓글을 불러오지 못했습니다.');
}
})
.then((comments) => {
comments.forEach(addComment);
});
.catch((err) => alert(err.message));
}
// HTML Template 사용하여 댓글 화면에 표시하기
function addComment(comment) {
const template = document.querySelector('#comment-template');
const node = document.importNode(template.content, true);
node.querySelector('.content').textContent = comment.content;
node.querySelector('.authro').textContent = comment.author.name;
node.querySelector('.createdAt').textContent = comment.createdAt;
document.querySelector('#comments').appendChild(node);
}
db.posts.aggregate([
{ $group: { _id: '$authro', count { $sum: 1 } } },
{ $match: { sum: { $gt: 10 } } },
{ $lookup: { from: 'users', localField: '_id', foreignField: '_id', as: 'users' } },
]);