댓글 기능을 만들어 보겠습니다.
댓글 기능을 말로 설명하면
1. 글의 상세페이지에 댓글을 작성할 공간, 보여줄 공간을 만들기
2. 작성할 공간에서 작성버튼을 누르면 서버로 데이터를 보내기
3. 서버에서 받은 데이터를 검증한 후 db에 저장하기
4. 서버에서 db에서 저장한 데이터를 가져와서 html을 생성해준다.
이렇게 4단계를 순서대로 만들면 될것 같습니다.
1. 먼저 댓글을 작성할 폼을 만들어 줍니다.
이렇게 input 하나 button 하나 구성하고, 폼태그로 감싸서 post 요청 해주면 될듯
<div>
<div class="comment-display">댓글 보여줄 공간</div>
<form method="post" action="/comment" class="comment-form">
<input class="comment-input" name="comment" type="text" placeholder="댓글 작성 공간">
<button type="submit" class="comment-submit">댓글 작성</button>
</form>
</div>
이제 댓글작성 버튼을 클리갛면 /comment 로 post 요청을 해줄듯합니다.
이제 insertOne() 함수를 이용해서 저장해주면 되겠네요
comment 컬렉션의 documnet 한개에 댓글 하나를 저장하고
document 에 글의 _id, 댓글을 작성한 userId 이거 두개를 저장해 두면
댓글을 쉽게 찾을수 있을것 같습니다.
router.post('/comment/:id', async (req, res)=>{
try{
if(req.session.userId){
await db.collection('comment')
.insertOne({
writerId : req.params._id,
userId : req.session.userId,
comment : req.body.comment
})
}
}catch(err){
console.log(err)
}
})
음 그런데 나중에 username : commnet 이런 형식으로 댓글을 보여주고 싶어서
username 도 가져와서 저장하겠습니다.
const userinfo = await db.collection('user').findOne({ _id: new ObjectId(req.session.userId) });
const username = userinfo.username;
await db.collection('comment').insertOne({
postId: req.params.id,
userId: req.session.userId,
comment: req.body.comment,
username: username
});
이렇게 user 컬렉션에서, 현재 로그인한 유저 컬렉션 찾아와서 username 변수에 userinfo.username 을 저장하고 username 을 comment 컬렉션에 저장해주면 사용할수 있을것 같습니다.
이제 내용을 입력하면, db에 잘 저장됩니다.
그럼 이제 /detail/:id 요청 처리할때
comment 컬렉션의 commnet 와 username을 찾아서 render할때 detail.ejs 파일로 보내주고
html으로 생성해주면 끝일것 같네요
router.get('/detail/:id', async (req, res) => {
try {
const postId = req.params.id;
const post = await db.collection('post').findOne({_id: new ObjectId(postId)});
const comments = await db.collection('comment').find({postId: postId}).toArray();
const errorMessage = req.query.error;
res.render('detail.ejs', {
result: post,
comments: comments,
sessionUserId: req.session.userId,
error: errorMessage
});
} catch (err) {
console.log(err);
res.status(500).send('서버 오류');
}
});
<div>
<% if(comments && comments.length > 0){ %>
<% comments.forEach(function(comment) { %>
<div class="comment-display">
<span class="comment-username"><%= comment.username %>:</span>
<span class="comment-text"><%= comment.comment %></span>
</div>
<% }); %>
<% } %>
and 연산자를 이용해서
comments 가 존재하지 않으면 if(false) 값이 되므로 실행되지 않고
comments 가 존재하면 if(comments.length >0) 이 실행되도록 해줬습니다.
그리고 댓글 폼 밑에
<form method="post" action="/comment/<%= result._id %>" class="comment-form">
<input class="comment-input" name="comment" type="text" placeholder="댓글 작성 공간">
<button type="submit" class="comment-submit">댓글 작성</button>
</form>
<% if (error) { %>
<div class="comment-error-message"><%= error %></div>
<% } %>
변수 error 을 통해서 로그인하지 않고 입력할경우 html을 생성해서 경고메시지를 보내주도록 작성했습니다.
router.post('/comment/:id', async (req, res) => {
try {
if(req.session.userId) {
const userinfo = await db.collection('user').findOne({ _id: new ObjectId(req.session.userId) });
const username = userinfo.username;
await db.collection('comment').insertOne({
postId: req.params.id,
userId: req.session.userId,
comment: req.body.comment,
username: username
});
res.redirect(`/detail/${req.params.id}`);
} else {
res.redirect(`/detail/${req.params.id}?error=로그인 후 이용해 주세요`);
}
} catch (err) {
console.log(err);
res.redirect(`/detail/${req.params.id}?error=서버 오류`);
}
});
댓글 작성 버튼을
if문을 이용해서 로그인 되어있다면 그대로 진행되고
로그인 되어있지 않다면 쿼리 스트링 문법을 이용해서 error 정보를 보내주도록 작성했습니다.
로그인 안한경우 메시지 출력
댓글 작성
잘 작성되는군요.
뭔가 좀 허전한게, 내가 쓴 댓글은 수정, 삭제가 기능을 추가해주면 좋을것 같은데
개인적으로 댓글은 수정 삭제가 안되었으면 좋겠어서 기능을 일단 보류해두고
성능개선 과정을 통해서 다시 결정해 보겠습니다.
오늘의 포스팅은 여기까지입니다.