[🎬 μ˜ν™” 검색 μ‚¬μ΄νŠΈ λ§Œλ“€κΈ°][νŒ€] μ˜ν™” 검색 μ‚¬μ΄νŠΈ λ§Œλ“€κΈ° 개발 기둝

μ˜ν™” 검색 μ‚¬μ΄νŠΈλ₯Ό κ°œλ°œν•˜λ©΄μ„œ λ°œμƒν–ˆλ˜ μ†Œμ†Œν•œ μ΄μŠˆμ™€ 해결방법듀을 μ •λ¦¬ν•΄λ³΄λ €ν•œλ‹€. 

 

리뷰 이슈

μƒˆλ‘œκ³ μΉ¨ 

등둝, μ‚­μ œ, μˆ˜μ •μ„ ν•  λ•Œ λ³€κ²½ 사항을 λ°˜μ˜ν•˜κΈ° μœ„ν•΄μ„œ 화면을 μƒˆλ‘œκ³ μΉ¨ν•˜λ„λ‘ ν–ˆλ‹€. 

 

μ•„λž˜λŠ” μˆ˜μ • λ²„νŠΌ 클릭슀 λ°œμƒν•˜λŠ” μ΄λ²€νŠΈμ΄λ‹€. μˆ˜μ •μ΄ μ™„λ£Œλœ ν›„ μƒˆλ‘œκ³ μΉ¨μ„ ν•˜μ—¬ λ³€κ²½λœ 데이터λ₯Ό 보이도둝 ν–ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ„ˆλ¬΄ λŒ€λ†“κ³  κΉœλΉ‘μ΄λŠ” ν˜„μƒμ΄ 보기 λΆˆνŽΈν•΄μ„œ λ‹€λ₯Έ 방법이 μžˆλ‚˜ κ³ λ―Όν•˜λ˜ 쀑, DOM 을 직접 μˆ˜μ •ν•˜μ—¬ λ³€κ²½ 사항을 μ €μž₯ν•˜λŠ” 방법이 μžˆλŠ” 것을 μ•Œμ•˜λ‹€.

saveUpdateButton.addEventListener('click', async () => {
  if (window.confirm('μ •λ§λ‘œ 이 리뷰λ₯Ό μˆ˜μ •ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?')) {
    const updatedContent = reviewItem.querySelector('#review-content').value;
    const reviewId = reviewItem.getAttribute('data-id');

    await updateReviewData(reviewId, updatedContent);

    window.location.reload();
    window.alert('μˆ˜μ •μ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.');
  }
});

 

DOM 을 μ‘°μž‘ν•˜μ—¬ λ³€κ²½ 사항을 λ°”λ‘œ λ°˜μ˜ν•˜λŠ” λ°©λ²•μœΌλ‘œ λ³€κ²½ν•˜μ—¬ κΉœλΉ‘μ΄λŠ” 문제λ₯Ό ν•΄κ²°ν•˜μ˜€λ‹€. 

saveUpdateButton.addEventListener('click', async () => {
  if (window.confirm('μ •λ§λ‘œ 이 리뷰λ₯Ό μˆ˜μ •ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?')) {
    const updatedContent = reviewItem.querySelector('#review-content').value;
    const reviewId = reviewItem.getAttribute('data-id');

    await updateReviewData(reviewId, updatedContent);
    // DOM을 직접 μˆ˜μ •ν•˜μ—¬ λ³€κ²½ 사항 반영
    reviewItem.innerHTML = `
    <div class="review-header">
      <span id="user-name">${userName}</span>
      <div>
        <button class="update-button">μˆ˜μ •</button>
        <button class="delete-button">μ‚­μ œ</button>
      </div>
    </div>
    <span id="review-content">${updatedContent}</span>
`;

    // μˆ˜μ •, μ‚­μ œ 이벀트 λ¦¬μŠ€λ„ˆ λ‹€μ‹œ μ„€μ •
    setupDeleteReviewEventListener(reviewItem);
    setupUpdateReviewButtonEventListener(reviewItem);
    window.alert('μˆ˜μ •μ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.');
  }
});

 

νŒŒμ΄μ–΄λ² μ΄μŠ€ 이슈

λΆˆν•„μš”ν•œ μž‘μ—…

λ‚˜λŠ” νŒŒμ΄μ–΄λ² μ΄μŠ€μ— 리뷰λ₯Ό 등둝할 λ•Œ, DB ꡬ쑰에 ν•΄λ‹Ή κΈ€μ˜ κ³ μœ ν•œ ID κ°€ μ—†μ–΄μ„œ 리뷰 등둝할 λ•Œ UUID λ₯Ό λ„£μ—ˆλ‹€.

 

κ·ΈλŸ¬λ‚˜..? λ‚˜μ€‘μ— μ•Œκ³  λ³΄λ‹ˆκΉŒ νŒŒμ΄μ–΄λ² μ΄μŠ€μ—μ„œ μ œκ³΅ν•˜λŠ” addDoc() λ©”μ„œλ“œλ‘œ 등둝을 ν•˜λ©΄ return κ°’μœΌλ‘œ 고유 ID λ₯Ό μ€€λ‹€λŠ” 것을 λ‚˜μ€‘μ— μ•Œκ²Œ λ˜μ—ˆλ‹€. 

 

λ¬΄μž‘μ • id λ₯Ό μ €μž₯ μ•ˆ ν•˜λ„€? ν•˜μ§€ 말고 κ΄€λ ¨ λ¬Έμ„œλ₯Ό μ’€ 더 μ°Ύμ•„λ³΄λŠ” μŠ΅κ΄€μ„ κ°€μ Έμ•Όκ² λ‹€κ³  μƒκ°ν–ˆλ‹€.

 

볡합 색인

상세 νŽ˜μ΄μ§€μ—μ„œ ν΄λ¦­ν•œ μ˜ν™”μ— λŒ€ν•œ νŒŒμ΄μ–΄λ² μ΄μŠ€μ— μ €μž₯된 리뷰 λͺ©λ‘μ„ μ‘°νšŒν•˜λŠ” μž‘μ—…μ„ ν•˜μ˜€λ‹€. ν•„μš”ν•œ 검색 쑰건은 μ˜ν™” ID 와 정렬이닀. μ•„λž˜ μ½”λ“œμ˜ 쑰회 ν•˜λŠ” λ‘œμ§μ„ 보면  where 쑰건으둜 movieId λ₯Ό μ£Όκ³ , orderBy 둜 μ΅œμ‹ μˆœμœΌλ‘œ μ •λ ¬ν•΄ μ£ΌλŠ” 것이닀. 

export const getReviewData = async (movieId) => {
  const getReviewsByMovieId = query(
    collection(db, 'reviews'),
    where('movieId', '==', movieId),
    orderBy('date', 'desc')
  );
  return await getDocs(getReviewsByMovieId);
};

 

κ·ΈλŸ¬λ‚˜.. 인터넷에 λ‚˜μ™€μžˆλŠ” μ˜ˆμ‹œλ“€κ³Ό λ˜‘κ°™μ΄ ν–ˆλŠ”λ° λ‚˜λ§Œ 였λ₯˜κ°€ λœ¨λŠ”κ²ƒμ΄λ‹€. 🀯 μ²˜μŒμ—” λ‘œμ§μ„ 살짝 잘λͺ» μ μ—ˆλ‚˜ μ‹Άμ–΄μ„œ λ‹€λ₯Έ μ‚¬λžŒλ“€μ΄ ν•œ μ˜ˆμ‹œλ₯Ό 계속 찾아보고 변경해보고 해도 μ•ˆλλ‹€. κ·Έλž˜μ„œ 였λ₯˜ 메세지λ₯Ό λ΄λ³΄μ•˜λŠ”λ°.. 

 

μ•„λž˜ 였λ₯˜ 메세지가 ꡉμž₯히 μΉœμ ˆν•˜κ²Œ 무슨 였λ₯˜μΈμ§€ μ•Œλ €μ£Όκ³ μžˆμ—ˆλ‹€. 🀦🏻‍♀️ 

Uncaught (in promise) FirebaseError: The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/cinespot8-95f00/firestore/indexes?create_composite=Ck9wcm9qZWN0cy9jaW5lc3BvdDgtOTVmMDAvZGF0YWJhc2VzLyhkZWZhdWx0KS9jb2xsZWN0aW9uR3JvdXBzL3Jldmlld3MvaW5kZXhlcy9fEAEaCwoHbW92aWVJZBABGggKBGRhdGUQAhoMCghfX25hbWVfXxAC
Promise.then (async)
(anonymous) @ script.js:13

해석해보면 '쿼리에 색인이 ν•„μš”ν•©λ‹ˆλ‹€. μ—¬κΈ°μ—μ„œ 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.' λΌλ©΄μ„œ μ£Όμ†ŒκΉŒμ§€ μΉœμ ˆν•˜κ²Œ μ•Œλ €μ£Όκ³ μžˆμ—ˆλ‹€. 

 

였λ₯˜ 메세지λ₯Ό 톡해 였λ₯˜ 원인을 μ•Œκ³  μ™œ λ”°λ‘œ 색인 생성이 ν•„μš”ν•œμ§€ μ°Ύμ•„λ³΄λ‹ˆκΉŒ λ¬Έμ„œμ— λ‹€μŒκ³Ό 같은 μ„€λͺ…이 λ‚˜μ˜¨λ‹€. νŒŒμ΄μ–΄λ² μ΄μŠ€ λ‚΄λΆ€ κ΅¬μ‘°λ‚˜ κ·œμΉ™μœΌλ‘œ 인해 볡합 색인을 ν•  κ²½μš°μ—” νŒŒμ΄μ–΄λ² μ΄μŠ€ μ½˜μ†”μ— λ“€μ–΄κ°€μ„œ λ”°λ‘œ 섀정을 ν•΄μ£Όμ–΄μ•Όν•œλ‹€λŠ” μ„€λͺ….

 

νŒŒμ΄μ–΄λ² μ΄μŠ€ μ½˜μ†” λ“€μ–΄κ°€μ„œ μ•„λž˜μ™€ 같이 색인 섀정을 ν•΄μ£Όλ‹ˆ.. 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•Šκ³  μ›ν•˜λŠ” 쑰건으둜 μ‘°νšŒκ°€ 잘 λ˜μ—ˆλ‹€. ν—ˆν—ˆ

 

λΌμ΄λΈŒμ„œλ²„ 이슈

VScode μ—μ„œ λΌμ΄λΈŒμ„œλ²„λ‘œ νŒŒμΌμ„ μ—΄μ—ˆμ„ λ•Œ 였λ₯˜ λ°œμƒν•˜κΈ°λ„ ν–ˆλ‹€. κ΄€λ ¨ λ‚΄μš©μ€ 여기에 정리! γ…Žγ…Ž