Vue로 PWA 개발

28. mylog 수정

그랜파 개발자 2024. 10. 25. 14:41

이미 등록한 마이로그 수정 기능을 구현합니다.

ChatGPT에게 물었습니다.

post 수정 기능을 만들어 줘

 

ChatGPT

게시물(Post) 수정 기능을 구현하려면, 사용자가 게시물을 수정할 수 있는 화면을 제공하고, Firestore에서 기존 게시물 데이터를 업데이트하는 로직이 필요합니다. Vue.js와 Firestore를 사용해 게시물 수정 기능을 구현하는 방법을 설명드리겠습니다.

1. Firestore에서 게시물 업데이트

Firestore에서 게시물을 수정하기 위해서는 updateDoc 메서드를 사용하여 기존 문서를 업데이트할 수 있습니다. doc() 메서드를 사용해 특정 문서의 참조를 가져온 후, 수정할 데이터를 전달하면 Firestore에서 해당 데이터를 수정합니다.

2. Vuex Store에서 게시물 수정 액션 구현

Vuex에서 게시물 수정 액션을 정의하고, Firestore에서 게시물을 업데이트하는 로직을 작성합니다.

Vuex Store (store.js)

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

const db = getFirestore();

const store = new Vuex.Store({
  state: {
    posts: [], // 게시물 목록 저장
  },
  mutations: {
    updatePost(state, updatedPost) {
      const index = state.posts.findIndex(post => post.id === updatedPost.id);
      if (index !== -1) {
        state.posts.splice(index, 1, updatedPost); // 상태에서 게시물 수정
      }
    },
  },
  actions: {
    // 게시물 수정 액션
    async updatePost({ commit }, { postId, updatedData }) {
      try {
        const postRef = doc(db, "posts", postId);
        await updateDoc(postRef, {
          title: updatedData.title,
          content: updatedData.content,
          updatedAt: new Date(), // 수정한 시간 기록
        });
        commit('updatePost', { id: postId, ...updatedData });
        console.log("게시물이 수정되었습니다.");
      } catch (error) {
        console.error("게시물 수정 실패:", error);
      }
    },
  },
});

export default store;

3. Vue 컴포넌트에서 게시물 수정 기능 구현

게시물 수정 화면 (EditPost.vue)

<template>
  <div>
    <h3>Edit Post</h3>
    <v-form ref="form" v-model="valid">
      <v-text-field
        label="Title"
        v-model="editedPost.title"
        :rules="[v => !!v || 'Title is required']"
      ></v-text-field>

      <v-textarea
        label="Content"
        v-model="editedPost.content"
        :rules="[v => !!v || 'Content is required']"
      ></v-textarea>

      <v-btn :disabled="!valid" @click="submitPost">Save Changes</v-btn>
    </v-form>
  </div>
</template>

<script>
export default {
  props: {
    post: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      editedPost: { ...this.post }, // 초기값을 props로 전달된 post로 설정
      valid: false, // 유효성 검사
    };
  },
  methods: {
    async submitPost() {
      if (this.$refs.form.validate()) {
        // Vuex 액션 호출하여 게시물 수정
        await this.$store.dispatch('updatePost', {
          postId: this.post.id,
          updatedData: this.editedPost,
        });
        this.$router.push({ name: 'PostDetail', params: { postId: this.post.id } });
      }
    },
  },
};
</script>

4. 게시물 수정 화면에서의 주요 로직 설명

  1. props로 게시물 데이터 전달: post 데이터를 부모 컴포넌트에서 받아와, 이 데이터를 수정할 수 있게 editedPost로 저장합니다.
  2. 폼 유효성 검사: v-form과 Vuetify의 유효성 검사 규칙을 사용해 게시물의 제목과 내용을 필수 입력으로 설정합니다.
  3. 게시물 수정 요청: 수정된 내용을 저장하기 위해 submitPost 메서드에서 Vuex의 updatePost 액션을 호출합니다. Firestore에 데이터를 업데이트한 후, 수정이 완료되면 게시물 상세 화면으로 이동합니다.

5. Vuex의 상태 동기화

Vuex의 updatePost 뮤테이션을 사용해 Firestore에서 데이터를 업데이트한 후, 상태를 동기화하여 화면에서 바로 반영되도록 합니다. 수정된 게시물 데이터를 Vuex의 posts 배열에서 찾아 수정된 내용을 덮어씌웁니다.

6. 게시물 수정 화면으로 이동

게시물을 수정하는 페이지로 이동하기 위해서는 게시물 상세 화면에 수정 버튼을 추가하고, 해당 버튼을 클릭했을 때 수정 페이지로 이동하는 기능을 구현합니다.

게시물 상세 화면 (PostDetail.vue)

<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>

    <!-- 게시물 수정 버튼 -->
    <v-btn @click="goToEdit">Edit Post</v-btn>
  </div>
</template>

<script>
export default {
  props: {
    post: {
      type: Object,
      required: true,
    },
  },
  methods: {
    goToEdit() {
      this.$router.push({ name: 'EditPost', params: { postId: this.post.id } });
    },
  },
};
</script>

7. 라우터 설정

수정 페이지로 이동할 수 있도록 Vue Router에서 라우팅 설정을 추가합니다.

router.js

import Vue from 'vue';
import Router from 'vue-router';
import PostDetail from './components/PostDetail.vue';
import EditPost from './components/EditPost.vue';

Vue.use(Router);

const routes = [
  {
    path: '/post/:postId',
    name: 'PostDetail',
    component: PostDetail,
    props: true,
  },
  {
    path: '/post/:postId/edit',
    name: 'EditPost',
    component: EditPost,
    props: true,
  },
];

export default new Router({
  mode: 'history',
  routes,
});

요약

  • Firestore에서 게시물 수정: updateDoc을 사용해 Firestore에서 특정 게시물을 업데이트합니다.
  • Vuex의 상태 동기화: Firestore에서 게시물 수정 후 Vuex 상태를 업데이트하여 UI에서 바로 수정된 내용을 반영합니다.
  • Vue 컴포넌트: 사용자가 게시물을 수정할 수 있는 입력 폼을 제공하고, 수정된 내용을 Firestore에 반영합니다.
  • 라우터 설정: 게시물 상세 페이지에서 수정 페이지로 이동할 수 있도록 라우터를 설정합니다.

이 방법으로 Vue.js와 Firestore를 사용하여 게시물 수정 기능을 쉽게 구현할 수 있습니다.

ChatGPT에게 물었습니다.

수정화면에 porps를 넘기는 방법은?

 

ChatGPT

Vue.js에서 props를 사용하여 수정 화면에 데이터를 전달하는 방법은 라우터를 활용하는 방식입니다. 게시물의 수정 화면에 데이터를 넘기려면 라우트 파라미터를 이용하여 수정할 게시물의 postId와 관련된 데이터를 전달할 수 있습니다.

1. 라우터에서 props로 데이터 전달

Vue Router에서는 props 옵션을 통해 라우트 파라미터를 컴포넌트로 전달할 수 있습니다. postId를 라우트로 전달하고, 해당 postId를 이용해 수정할 게시물의 데이터를 Firestore에서 가져와 수정 화면에서 사용할 수 있습니다.

1-1. router.js에 props 옵션 추가

import Vue from 'vue';
import Router from 'vue-router';
import EditPost from './components/EditPost.vue';

Vue.use(Router);

const routes = [
  {
    path: '/edit-post/:postId',  // postId를 라우트 파라미터로 받음
    name: 'EditPost',
    component: EditPost,
    props: true,  // postId를 props로 전달
  },
];

export default new Router({
  mode: 'history',
  routes,
});

 

props: true로 설정하면 postId를 URL 파라미터로 받아서 해당 컴포넌트에 props로 전달할 수 있습니다.

2. 컴포넌트에서 props 사용

EditPost.vue 컴포넌트에서 props로 전달받은 postId를 이용해 Firestore에서 해당 게시물을 불러와 화면에 출력하고 수정할 수 있습니다.

2-1. EditPost.vue

<template>
  <div>
    <h2>Edit Post</h2>
    <v-form v-if="post">
      <v-text-field
        v-model="post.title"
        label="Post Title"
      ></v-text-field>
      <v-textarea
        v-model="post.content"
        label="Post Content"
      ></v-textarea>
      <v-btn @click="updatePost">Save Changes</v-btn>
    </v-form>
  </div>
</template>

<script>
import { getFirestore, doc, getDoc, updateDoc } from "firebase/firestore";

export default {
  props: {
    postId: {
      type: String,
      required: true,
    },
  },
  data() {
    return {
      post: null,  // 수정할 게시물 데이터
    };
  },
  methods: {
    async fetchPost() {
      const db = getFirestore();
      const postRef = doc(db, "posts", this.postId);  // Firestore에서 postId로 게시물 가져옴
      const postSnap = await getDoc(postRef);
      if (postSnap.exists()) {
        this.post = postSnap.data();  // 게시물 데이터를 post에 저장
      } else {
        console.log("No such document!");
      }
    },
    async updatePost() {
      const db = getFirestore();
      const postRef = doc(db, "posts", this.postId);
      await updateDoc(postRef, {
        title: this.post.title,
        content: this.post.content,
      });
      this.$router.push({ name: 'PostDetail', params: { postId: this.postId } });  // 수정 후 상세 페이지로 이동
    },
  },
  mounted() {
    this.fetchPost();  // 컴포넌트가 마운트되면 게시물 데이터를 가져옴
  },
};
</script>

3. 주요 로직 설명

  1. props로 postId 받기: props로 라우트에서 전달받은 postId를 사용합니다. 이 postId를 이용해 Firestore에서 해당 게시물을 가져옵니다.
  2. Firestore에서 게시물 데이터 가져오기: fetchPost() 메서드에서 Firestore의 doc()과 getDoc()을 사용하여 postId에 해당하는 게시물 데이터를 가져옵니다.
  3. 수정 후 저장하기: 사용자가 게시물을 수정한 후 저장 버튼을 클릭하면 updatePost() 메서드를 통해 Firestore의 updateDoc()을 사용하여 해당 게시물을 업데이트합니다.
  4. 수정 완료 후 라우팅: 게시물이 성공적으로 수정되면 PostDetail 페이지로 다시 이동하여 변경된 내용을 확인할 수 있습니다.

4. 게시물 수정 페이지로 이동하기

게시물 수정 페이지로 이동할 때는 router.push를 사용하여 postId를 파라미터로 넘겨줍니다.

예시: PostDetail.vue에서 수정 페이지로 이동

<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>

    <!-- 수정 버튼 -->
    <v-btn v-if="isAuthor" @click="goToEdit">Edit Post</v-btn>
  </div>
</template>

<script>
export default {
  methods: {
    goToEdit() {
      this.$router.push({ name: 'EditPost', params: { postId: this.post.id } });
    },
  },
};
</script>

요약

  • 라우트 파라미터로 props 전달: postId를 URL 파라미터로 받아 props로 전달합니다.
  • Firestore에서 게시물 가져오기: postId를 사용해 Firestore에서 해당 게시물 데이터를 가져옵니다.
  • 수정 화면에 표시: Firestore에서 가져온 데이터를 양식 필드에 바인딩하여 사용자에게 표시하고, 수정할 수 있도록 합니다.
  • 수정 후 저장: 수정된 내용을 Firestore에 업데이트한 후, 다시 게시물 상세 페이지로 라우팅합니다.

이 방법으로 수정 화면에서 props로 데이터를 넘기고, Firestore와 연동하여 게시물을 수정할 수 있습니다.

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

30. mylog 수정, 내 마이로그 보기 구현  (0) 2024.10.25
29. mylog 모아보기  (0) 2024.10.25
27. mylog 기본 워크플로우 완성  (0) 2024.10.24
26. mylog 익명 ID  (0) 2024.10.24
25. mylog 날짜별 조회수  (0) 2024.10.24