Firebase 배우기 11 – Firestore Database 키워드 검색 및 삭제(Delete)하기

Firebase 배우기 11 – Firestore Database 키워드 검색 및 삭제(Delete)하기

앞선 글에서 Firestore DB에 저장된 자료의 특정 필드를 대상으로 키워드 검색하는 것을 소개한 바 있었다.

https://blog.naver.com/mythee1/223494445392

그런데 DB 등록을 하다 보면, 다음과 같이 실수로 중복 등록을 했다든가, 더 이상 해당 문서가 필요하지 않게 되는 등의 이유로 특정 문서를 삭제해야 할 필요가 생기기도 한다.

본 글에서는 이런 경우를 대비하여, 이와 같이 검색된 레코드에 버튼을 추가하고, 해당 버튼이 눌려지면, 해당 레코드를 “추가 확인을 거쳐” 삭제하는 과정을 소개한다.

우선 버튼은 부트스트랩의 버튼을 이용하여 쉽게 생성할 수 있는데, 나의 경우에는 다음과 같은 외곽선 형태의 버튼을 사용하기로 했고, 필요한 색상만 고르기로 했다.

그리고 이왕 만드는 김에 “삭제” 외에도, “좋아요” 버튼과, “수정” 등의 버튼도 함께 만들기로 했다.

다음과 같이 부트스트랩의 버튼 요소를 활용하여 코드를 구성했고,

그 결과 다음과 같은 형태로 버튼이 반영되었다.

이제 이 삭제 버튼이 눌려졌을 때 실제 삭제가 이루어지도록 삭제 버튼에 대한 핸들러를 만들었는데, 삭제는 복구가 어려우므로 삭제 전엔 추가로 한 번 더 확인을 거칠 수 있도록 다음과 같은 단계를 두었다.

그리고 실제 삭제 버튼에 대한 핸들러 부분은 선택된 문서의 ID를 가져와야 하므로, Copilot의 도움을 받아 다음과 같이 코드를 생성했다.

이 코드를 적용하면 해당 이미지에서 성공적으로 이미지 파일이 삭제되고, DB에서도 해당 문서가 지워지게 된다.

다시 해당 키워드로 검색을 하면 3개의 레코드였던 것이 이제는 1개 레코드가 삭제됨에 따라 2개의 레코드만 보이게 된다.

이렇게 키워드 검색 후 삭제 버튼을 추가하고, 삭제 버튼 선택에 따라 실제 삭제 작업이 수행되는 부분에 대한 코드는 다음과 같다. 나머지 버튼들은 아직 dummy 상태이며, 해당 버튼들에 대한 동작도 추가로 만들어 추가할 예정이다.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>키워드 검색후 삭제</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<script src="https://www.gstatic.com/firebasejs/8.6.5/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.5/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.5/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.5/firebase-storage.js"></script>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script>
const firebaseConfig = { 사용자 정보로 생략
     };
      firebase.initializeApp(firebaseConfig);
</script>
<!-- 콘테이너 생성 -->
<div class="container">
<form id="productForm" class="m-3">
<input type="text" id="keyword" name="keyword" class="form-control mb-3" placeholder="검색할 상품명을 입력하세요.">
<input type="button" id="searchit" value="검색시작" class="btn btn-secondary" style="background-color: orange;">
</form>
<div id="productList" class="m-3"></div> <!-- 결과를 표시할 div를 추가합니다. -->
</div>
<script>
var db = firebase.firestore();
var storage = firebase.storage();
$('#searchit').click(function () {
$('#productList').empty(); // 검색 결과를 초기화합니다.

        db.collection('products').where("상품명", "==", $('#keyword').val())
.get()
.then((querySnapshot) => {
          querySnapshot.forEach((doc) =>{
var data = doc.data();
var date = new Date(data.날짜.seconds * 1000).toLocaleString();//YYYY/MM/DD hh:mm:ss 형식              
              console.log(doc.id)
var html = `
                <div class="card mb-3" style="max-width: 540px;" id="${doc.id}"> <!-- 여기에 id 속성을 추가합니다. -->
                  <div class="row g-0">
                    <div class="col-md-4">
                      <img src="${data.사진}" alt="${data.상품명}" style="width: 150px; height: 150px;"> 
                  </div>
                  <div class="col-md-8">
                    <div class="card-body">
                    <h6 class="card-title">${data.상품등록번호}</h6>
                    <h5 class="card-title">${data.상품명}</h5>
                    <p class="card-text">${data.상품설명}</p>
                    <p class="card-text"><small class="text-muted">${data.가격}</small></p> 
                    <p class="card-text"><small class="text-muted">${date}</small></p> 
                    <p class="card-text"><small class="text-muted">참고사항 : ${data.참고노트}</small></p>                     
                    <p class="card-text"><small class="text-muted">&hearts; : ${data.좋아요}</small></p> 
                  <button class="btn btn-outline-danger delete">삭제</button>
                  <button class="btn btn-outline-primary edit">수정</button>
                  <button class="btn btn-outline-success like">좋아요</button>
                  <button class="btn btn-outline-info note">Note</button>
                  </div>
                </div>
              </div>
            </div>
          `;
$('#productList').append(html);
});
})
.catch((error) => {
                console.log("Error getting documents : ", error);
});
});
$(document).on('click', '.delete', function() {
if (confirm('정말로 이 상품을 삭제하시겠습니까?')) {
var docId = $(this).closest('.card').attr('id'); // 가장 가까운 .card 요소에서 id를 가져옵니다.
        
        db.collection('products').doc(docId).get().then((doc) => {
var data = doc.data();
var imageRef = storage.refFromURL(data.사진);
        imageRef.delete().then(() => {
        console.log("Image successfully deleted!");

        db.collection('products').doc(docId).delete().then(() => {
          console.log("Document successfully deleted!");
$(this).closest('card').remove();
          location.reload();
}).catch((error) => {
          console.error("Error removing document: ", error);
});
}).catch((error) => {
        console.error("Error removing image: ", error);
});
});
};
});
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>