Vue로 PWA 개발

31. mylog 댓글 쓰기

그랜파 개발자 2024. 10. 26. 15:07

로그인 후에는 마이로그에 댓글을 쓸 수 있습니다.

ChatGPT에게 물었습니다.

post에 댓글을 쓰고 싶어

 

ChatGPT

게시물(Post)에 댓글 기능을 구현하려면, 댓글을 Firestore에 저장하고, 이를 화면에 실시간으로 표시하는 구조로 설계할 수 있습니다. 댓글 기능은 기본적으로 입력 폼을 통해 댓글을 작성하고, Firestore에 저장한 후, 저장된 댓글을 다시 불러와 화면에 표시하는 방식입니다. 여기서는 Vue.js, Vuex, Firestore를 사용하여 댓글 작성 및 불러오기 기능을 구현하는 방법을 설명하겠습니다.

1. Firestore에서 댓글 컬렉션 구조

게시물(post)마다 여러 개의 댓글이 있을 수 있습니다. Firestore에서는 하위 컬렉션을 사용하여 게시물마다 댓글을 관리할 수 있습니다.

Firestore 구조 예시:

  • posts (컬렉션)
  • postId (문서)
    • comments (하위 컬렉션)
      • commentId (문서)
        • content: "This is a comment"
        • author: "User123"
        • createdAt: serverTimestamp()

2. Firestore에 댓글 저장하기 (Vuex의 actions 사용)

Vuex에서 댓글을 저장하는 action을 정의한 후, Firestore에 댓글을 추가하는 로직을 작성합니다.

Vuex Store (store.js)

import { getFirestore, collection, addDoc, serverTimestamp, query, orderBy, getDocs } from "firebase/firestore";

const db = getFirestore();

const store = new Vuex.Store({
  state: {
    comments: [], // 댓글 목록 저장
  },
  mutations: {
    setComments(state, comments) {
      state.comments = comments;
    },
    addComment(state, comment) {
      state.comments.push(comment);
    },
  },
  actions: {
    async fetchComments({ commit }, postId) {
      try {
        const q = query(collection(db, "posts", postId, "comments"), orderBy("createdAt", "asc"));
        const querySnapshot = await getDocs(q);
        const comments = [];
        querySnapshot.forEach((doc) => {
          comments.push({ id: doc.id, ...doc.data() });
        });
        commit('setComments', comments); // 댓글을 상태에 저장
      } catch (error) {
        console.error("댓글 가져오기 실패:", error);
      }
    },

    async addComment({ commit }, { postId, content, author }) {
      try {
        const commentRef = await addDoc(collection(db, "posts", postId, "comments"), {
          content: content,
          author: author,
          createdAt: serverTimestamp(),
        });
        const newComment = { id: commentRef.id, content, author, createdAt: new Date() };
        commit('addComment', newComment); // 새 댓글을 상태에 추가
      } catch (error) {
        console.error("댓글 추가 실패:", error);
      }
    },
  },
});

export default store;

3. Vue 컴포넌트에서 댓글 기능 구현

댓글 작성 화면 (PostComments.vue)

<template>
  <div>
    <h3>Comments</h3>

    <!-- 댓글 목록 -->
    <ul v-if="comments.length > 0">
      <li v-for="comment in comments" :key="comment.id">
        <strong>{{ comment.author }}</strong>: {{ comment.content }}
      </li>
    </ul>

    <!-- 댓글 작성 폼 -->
    <div>
      <input v-model="newComment" placeholder="Write a comment..." />
      <button @click="submitComment">Add Comment</button>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    postId: {
      type: String,
      required: true,
    },
  },
  data() {
    return {
      newComment: '',
    };
  },
  computed: {
    comments() {
      return this.$store.state.comments;
    },
  },
  methods: {
    async submitComment() {
      const author = "Anonymous"; // 여기서 사용자 정보를 가져올 수 있음
      if (this.newComment.trim()) {
        await this.$store.dispatch('addComment', {
          postId: this.postId,
          content: this.newComment,
          author: author,
        });
        this.newComment = ''; // 댓글 입력 필드 초기화
      }
    },
  },
  mounted() {
    // 컴포넌트가 로드되면 해당 게시물의 댓글을 불러옴
    this.$store.dispatch('fetchComments', this.postId);
  },
};
</script>

4. 설명

  1. fetchComments: 특정 게시물(postId)에 달린 댓글을 Firestore에서 가져와 상태에 저장하는 Vuex action입니다.
  2. addComment: 댓글을 Firestore의 해당 게시물 하위 컬렉션에 추가하는 Vuex action입니다. 댓글이 성공적으로 추가되면 상태에 즉시 반영됩니다.
  3. mounted: 컴포넌트가 마운트되면 fetchComments를 호출하여 게시물에 달린 모든 댓글을 불러옵니다.
  4. submitComment: 댓글을 작성하고 제출 버튼을 클릭하면 Firestore에 댓글을 저장하는 액션을 실행합니다.

5. 추가 기능

댓글 삭제 기능

import { deleteDoc, doc } from "firebase/firestore";

async deleteComment({ postId, commentId }) {
  const commentRef = doc(db, "posts", postId, "comments", commentId);
  try {
    await deleteDoc(commentRef);
    console.log("댓글이 삭제되었습니다.");
  } catch (error) {
    console.error("댓글 삭제 실패:", error);
  }
}

댓글 수정 기능

import { updateDoc, doc } from "firebase/firestore";

async updateComment({ postId, commentId, newContent }) {
  const commentRef = doc(db, "posts", postId, "comments", commentId);
  try {
    await updateDoc(commentRef, {
      content: newContent,
      updatedAt: serverTimestamp(),  // 수정된 시간 기록
    });
    console.log("댓글이 수정되었습니다.");
  } catch (error) {
    console.error("댓글 수정 실패:", error);
  }
}

요약

Firestore 하위 컬렉션을 사용하여 게시물마다 댓글을 관리할 수 있습니다. Vuex의 actions를 사용하여 댓글을 작성하고, Firestore에 저장하며, 이를 상태로 관리할 수 있습니다. 컴포넌트에서 댓글 작성 폼과 목록을 보여주고, 작성된 댓글을 실시간으로 반영합니다. 추가적으로 댓글 수정 및 삭제 기능도 쉽게 구현할 수 있습니다. 이 구조를 기반으로 Firestore와 Vuex를 사용하여 댓글 기능을 쉽게 확장할 수 있습니다.

'Vue로 PWA 개발' 카테고리의 다른 글

33. mylog 답글  (0) 2024.10.26
32. mylog 댓글 쓰기 구현  (0) 2024.10.26
30. mylog 수정, 내 마이로그 보기 구현  (0) 2024.10.25
29. mylog 모아보기  (0) 2024.10.25
28. mylog 수정  (0) 2024.10.25