Vue로 PWA 개발

35. mylog 찾기

그랜파 개발자 2024. 10. 28. 00:42

글들이 많아지면 찾기 기능이 필요합니다. 마이로그 찾기는 간단하게 검색어를 포함하고 있는 마이로그들을 찾아 보여줍니다.

ChatGPT에게 물었습니다.

post의 title 또는 content에 검색어를 포함하는 post를 찾아줘

 

ChatGPT

게시물의 title 또는 content에 검색어를 포함하는 게시물을 찾기 위해 Firebase Firestore에서 쿼리를 사용하여 검색 기능을 구현할 수 있습니다. 하지만 Firestore는 기본적으로 부분 일치 검색을 제공하지 않기 때문에, 일반적인 SQL처럼 LIKE 쿼리는 사용할 수 없습니다. 다음은 Vue.js와 Firestore를 사용하여 title 또는 content에 검색어를 포함하는 게시물을 찾는 기능을 구현하는 방법입니다. 여기서는 전방 일치 검색 및 간단한 문자열 매칭 방법을 사용합니다.

1. SearchPosts.vue 구현

아래 예시는 검색어가 게시물의 title 또는 content에 포함된 경우 검색되는 기능입니다.

<template>
  <v-container>
    <v-row>
      <v-col cols="12" sm="8">
        <v-text-field
          v-model="searchTerm"
          label="Search posts"
          @input="searchPosts"
          placeholder="Enter keyword..."
        ></v-text-field>
      </v-col>
    </v-row>

    <v-row>
      <v-col v-for="post in filteredPosts" :key="post.id" cols="12" sm="6" md="4">
        <v-card>
          <v-card-title>{{ post.title }}</v-card-title>
          <v-card-text>{{ post.content }}</v-card-text>
          <v-card-actions>
            <v-btn @click="goToPost(post.id)">View Post</v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import { getFirestore, collection, getDocs } from "firebase/firestore";

export default {
  data() {
    return {
      searchTerm: "",     // 검색어
      posts: [],          // 전체 게시물 목록
      filteredPosts: [],  // 검색된 게시물 목록
    };
  },
  methods: {
    // Firestore에서 게시물 검색
    async searchPosts() {
      if (!this.searchTerm) {
        // 검색어가 없을 경우 전체 게시물을 표시
        this.filteredPosts = this.posts;
        return;
      }

      // 검색어 소문자로 변환
      const searchTermLower = this.searchTerm.toLowerCase();

      // 검색된 결과 필터링
      this.filteredPosts = this.posts.filter((post) => {
        return (
          post.title.toLowerCase().includes(searchTermLower) ||
          post.content.toLowerCase().includes(searchTermLower)
        );
      });
    },

    // 게시물 세부 페이지로 이동
    goToPost(postId) {
      this.$router.push({ name: "PostDetail", params: { postId } });
    },

    // Firestore에서 전체 게시물 가져오기
    async fetchAllPosts() {
      const db = getFirestore();
      const postsCollection = collection(db, "posts");
      const querySnapshot = await getDocs(postsCollection);

      this.posts = [];
      querySnapshot.forEach((doc) => {
        const post = doc.data();
        post.id = doc.id;
        this.posts.push(post);
      });

      this.filteredPosts = this.posts;  // 초기 상태에서 모든 게시물 표시
    }
  },

  mounted() {
    this.fetchAllPosts();  // 컴포넌트가 마운트되면 전체 게시물 가져오기
  },
};
</script>

2. 주요 기능 설명

1. Firestore에서 게시물 가져오기:

  • fetchAllPosts() 메서드는 Firestore에서 posts 컬렉션에 있는 모든 게시물을 가져옵니다. 가져온 게시물은 posts 배열에 저장됩니다.

2. 검색 기능 구현:

  • searchPosts() 메서드는 사용자가 입력한 검색어가 title 또는 content에 포함된 게시물을 필터링합니다.
  • 검색어는 대소문자를 구분하지 않도록 toLowerCase()로 변환하여 처리합니다.
  • filter() 메서드를 사용하여 각 게시물의 title과 content에서 검색어를 포함하는지 확인합니다.

3. 검색된 게시물 표시:

  • 검색 결과는 filteredPosts 배열에 저장되며, 이를 카드 뷰(v-card)로 리스트 형태로 화면에 표시합니다.

4. 게시물 상세 페이지로 이동:

  • 각 게시물의 "View Post" 버튼을 클릭하면 goToPost() 메서드가 호출되어 해당 게시물의 postId를 라우터로 전달해 상세 페이지로 이동합니다.

3. 성능 최적화

Firestore에서 모든 게시물을 가져온 후, 검색어를 기반으로 클라이언트에서 필터링을 수행합니다. 검색할 게시물의 양이 적다면 이 방법은 간단하고 유효하지만, 많은 데이터를 처리할 경우에는 다음과 같은 성능 최적화 방법을 고려할 수 있습니다.

서버에서 직접 필터링:

Firestore에서 서버 측에서 검색어를 기반으로 필터링된 결과를 가져오려면, 전방 일치 검색(>=, <=)을 사용할 수 있습니다.

예를 들어:

const q = query(postsCollection, where('title', '>=', searchTerm), where('title', '<=', searchTerm + '\uf8ff'));

 

그러나 이 방식은 검색어가 앞부분에 일치하는 경우에만 사용할 수 있습니다. 부분 검색이 필요하다면, Algolia 같은 외부 검색 서비스를 고려할 수 있습니다.

4. 확장 가능성

  • 키워드 인덱스 사용: 각 게시물에 대해 keywords 필드를 추가하고, 그 안에 title과 content에 나오는 단어들을 배열로 저장하여 array-contains를 통해 더 효율적인 검색을 구현할 수 있습니다.
  • 외부 검색 엔진 사용: 복잡한 부분 일치 검색이 필요할 경우, Algolia 또는 ElasticSearch와 같은 외부 검색 엔진을 사용하여 Firestore와 통합할 수 있습니다.

이 구현을 통해 간단한 게시물 검색 기능을 만들 수 있습니다.

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

37. mylog 구독  (0) 2024.10.28
36. mylog 찾기 구현  (0) 2024.10.28
34. mylog 답글 구현  (0) 2024.10.26
33. mylog 답글  (0) 2024.10.26
32. mylog 댓글 쓰기 구현  (0) 2024.10.26