상세 컨텐츠

본문 제목

ch16. comment section

노마드/유튜브

by hippo0207 2022. 9. 5. 15:22

본문

1. intro

2. comment Models

  • model 만들기
[Comment.js]
import mongoose from "mongoose";

const commentSchema = new mongoose.Schema({
  text: { type: String, required: true },
  owner: { type: mongoose.Schema.Types.ObjectId, required: true, ref: "User" },
  video: { type: mongoose.Schema.Types.ObjectId, required: true, ref: "Video" },
  createdAt: { type: Date, required: true, default: Date.now },
});

const Comment = mongoose.model("Comment", commentSchema);
export default Comment;
==========================
[Video.js]
...
comments: [{ type: mongoose.Schema.Types.ObjectId, required:true, ref: "Comment" }],
...
==========================
[User.js]
...
comments: [{ type: mongoose.Schema.Types.ObjectId, required:true, ref: "Comment" }],
...
==========================

3. comment Box

[webpack.config.js]
const BASE_JS = "./src/client/js/";
module.exports = {
  entry: {
    main: BASE_JS + "main.js", // 변경할 src code위치
    videoPlayer: BASE_JS + "videoPlayer.js",
    recorder: BASE_JS + "recorder.js",
    commentSection: BASE_JS + "commentSection.js",
  },
  ...
  =================================
  [watch.pug]
  block content
    div#videoContainer(data-id=video._id)
    ...
      if loggedIn
        div.video__comments
            form.video__comment-form#commentForm
                textarea(cols="30", rows="10", placeholder="Write a nice commment...")
                button Add Comment
  
  block scripts
    script(src="/static/js/videoPlayer.js") 
    script(src="/static/js/commentSection.js") 
=================================
[src/client/js/commentSection.js]
const videoContainer = document.getElementById("videoContainer");
const form = document.getElementById("commentForm");
const textarea = form.querySelector("textarea");
const btn = form.querySelector("button");

const handleSubmit = (event) => {
  event.preventDefault();
  const text = textarea.value;
  const video = videoContainer.dataset.id;
};

form.addEventListener("submit", handleSubmit);

4. API Route

  • 로그인안된경우 > comment form 이없음 >> js에서 에러남  (form & querySelector)
    • 방법1 watch.pug 수정 
    • 방법2 js 수정 >> form 유무확인 & form연계된 것들은 함수안에넣기
[watch.pug]
block scripts
    script(src="/static/js/videoPlayer.js")
    if loggedIn
        script(src="/static/js/commentSection.js") 
========================
[commentSection.js]
const videoContainer = document.getElementById("videoContainer");
const form = document.getElementById("commentForm");

const handleSubmit = (event) => {
  event.preventDefault();
  const textarea = form.querySelector("textarea");
  const text = textarea.value;
  const video = videoContainer.dataset.id;
};

if (form) {
  form.addEventListener("submit", handleSubmit);
}
  • 2. fetch 로 backend 에 request보내기
  • 그냥 객체로 req.body에 보내면 >> Object로 들어가버림
    • 서버에서 req.body를 알아먹을수있게 해줘야함 >> text로 보내도 알아먹을 수 있도록

  • text하나만 보낼꺼면 body:text 하면 되지만, 여러개보낼땐 {} 담아서 보내야함 >>
    • 1. body 보낼때 JSON.stringify 중요함 >> object 말고 text로 바꿔서 보내기 

  • >> 위에처럼 json을 stringify했을경우 >> 그냥 text라서 req.body.text 사용을 못함 
  • >> string 을 js object으로 받아먹게하기위해 express.text() 말고 express.json() 적용하기
    • 아래같은 JSON.parse를 알아서 하게끔
    • request 보내기전에 프론트에서 알아서 바꿔줌 
    • express에게 json을 보내고있다고 알려줘야함
      • >> fetch의 headers로 (request 정보 담고있음)
      • >> headers: {"Content-Type": "application/json"}

[commentSections.js]
const handleSubmit = (event) => {
  ...
  if (text === "") {
    return;
  }
  fetch(`/api/videos/${videoId}/comment`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ text}),
  });
};
====================================
[apiRouter.js]
apiRouter.post("/videos/:id([0-9a-f]{24})/comment", createComment);
====================================
[videoController.js]
export const createComment = (req, res) => {
  console.log(req.params);
  console.log(req.body);
  return res.end();
};
==================
[server.js]
app.use(express.json());

5. Commenting

  • add comment >> 프론트에서 백엔드로 쿠키를 보냄 >> 백엔드는 세션을 찾아봄 >> 컨트롤러에서 사용가능 (req.session.user 등을)
export const createComment = async (req, res) => {
  const {
    session: { user },
    body: { text },
    params: { id },
  } = req;

  const video = await Video.findById(id);
  if (!video) {
    return res.sendStatus(404);
  }

  const comment = await Comment.create({
    text,
    owner: user._id,
    video: id,
  });
  return res.sendStatus(201);
};

 

6. Rendering Comments

  • 댓글 생성 후 비디오 업데이트를 시켜줘야 함 >> comment [] 에 comment._id 들어가도록
[videoController.js]
export const watch = async (req, res) => {
..
  const video = await Video.findById(id).populate("owner").populate("comments");
  ..
 }
 
export const createComment = async (req, res) => {
 ...
  video.comments.push(comment._id);
  video.save();
  ..
};
  • 댓글 보이게하기
[watch.pug]
    div.video__comments
        ul 
            each comment in video.comments.reverse()
                li.video__comment
                    i.fas.fa-comment
                    |  #{comment.text}
===========================
[commentSection.js]

async 
.. await fetch
..
window.location.reload(); 
>> 댓글새로 달릴때마다 리로드 But 부하걸리니 다른방법으로 할거임

7. Realtime Comments

  • fetch 완료시 >> 가짜코멘트 만들기
[commentSection.js]
const addComment = (text) => {
  const videoComments = document.querySelector(".video__comments ul");
  const newComment = document.createElement("li");
  newComment.className = "video__comment";
  const icon = document.createElement("i");
  icon.className = "fas fa-comment";
  const span = document.createElement("span");
  span.innerText = `${text}`;
  newComment.appendChild(icon);
  newComment.appendChild(span);
  videoComments.prepend(newComment);
};

const handleSubmit = async (event) => {
  ...
  const { status } = await fetch(`/api/videos/${videoId}/comment`, {
    ...
  });
  if (status === 201) {
    addComment(text);
  }...

8. Comment Ids

  • 삭제기능 추가하기
    • 컨트롤러부분 수정 >> return 시 comment._id도 같이 보내도록  >> addComment에도 추가하기
  •  
[videoController.js]
export const createComment = async (req, res) => {
  ... 
  return res.status(201).json({ newCommentId: comment._id });
};

============================
[commentSection.js]

const addComment = (text, id) => {
  ...
  newComment.dataset.id = id;      <<      <<      <<
  ...
  const span2 = document.createElement("span");
  span2.innerText = "❌";
  ..
  newComment.appendChild(span2);
  videoComments.prepend(newComment);
};

const handleSubmit = async (event) => {
  const response = await fetch(`/api/videos/${videoId}/comment`, {
    ...
  });
  if (response.status === 201) {
    ...
    const { newCommentId } = await response.json();
    addComment(text, newCommentId);
  }
};

 

 

 

 

 

 

 

'노마드 > 유튜브' 카테고리의 다른 글

ch17. deployment  (0) 2022.09.08
ch15. flash message  (0) 2022.09.05
ch14. webassembly video transcode  (0) 2022.09.02
ch13. video recorder  (0) 2022.09.01
ch12. Views api << 템플릿 렌더링 X  (0) 2022.09.01

관련글 더보기

댓글 영역