파이어베이스 onSnapshot(웹 네임스페이스화된 API 방식 참고)

김효진·2023년 10월 11일
0
post-custom-banner

파이어베이스로 프로젝트를 진행하다가 댓글작성, 수정 등 변화가 있을 때 새로고침 없이도 데이터가 실시간으로 반영되게 하고싶어서 알아봤는데
get() 대신 onSnapshot() 이라는 기능이 있었다.

<파이어베이스 문서 내용>

db.collection("cities").doc("SF")
    .onSnapshot((doc) => {
        console.log("Current data: ", doc.data());
    });

위 코드를 참고하여 내 코드에 넣어보았다.

docRef = database
  .collection('comment')
  .orderBy('createdAt', 'desc')
  .onSnapshot((snapshot) => {
   
    let temp_html = ''

    snapshot.forEach((doc) => {
      let id = doc.id
      let data = doc.data()
      let name = data.name
      let comment = data.comment
      let createdAt = data.createdAt

      //  날짜 형식 변환
      createdAt = new Date(createdAt)
      var year = createdAt.getFullYear().toString().slice(-2) //년도 뒤에 두자리
      var month = ('0' + (createdAt.getMonth() + 1)).slice(-2) //월 2자리 (01, 02 ... 12)
      var day = ('0' + createdAt.getDate()).slice(-2) //일 2자리 (01, 02 ... 31)
      var hour = ('0' + createdAt.getHours()).slice(-2) //시 2자리 (00, 01 ... 23)
      var minute = ('0' + createdAt.getMinutes()).slice(-2) //분 2자리 (00, 01 ... 59)
      var second = ('0' + createdAt.getSeconds()).slice(-2) //초 2자리 (00, 01 ... 59)
      createdAt =
        year +
        '.' +
        month +
        '.' +
        day +
        '. ' +
        hour +
        ':' +
        minute +
        ':' +
        second

      temp_html += `
                    <tr data-documentId=${id} data-collectionName="comment">
                        <td>${name}</td>
                        <td>${comment}</td>
                        <td>${createdAt}</td>
                        <td><button class="edit">edit</button></td>
                        <td><button class="del">del</button></td>
                    </tr>
                    `
    })
    $('#tbody').append(temp_html)
})

그런데 데이터를 입력하면 업데이트되는 화면에 오류가 있었다.
1번째 데이터를 입력하면 1째만 나오는데 2번째 데이터를 입력하면 1,2번째 데이터가 1번째 데이터에 추가되어 보여지고 3번째 데이터를 입력하면 1,2,3번째 데이터가 그 아래 또 추가가 되는 것이다. 그래서 3개의 데이터를 입력하면 보여지는 데이터가 6개였다.

로그에 찍어봐도 하나씩 잘 저장되고 있고 실제 데이터베이스에도 중복이 없는데 보여지는 화면에 문제가 있어 한참을 헤멨다.

알고보니 아주 간단한 오류였다.

데이터를 불러올때 저장된 모든 데이터가 불러와지는 로직인데
화면이 실시간 업데이트 되면서 '기존에 화면에 보여지던 데이터' + '저장된 모든 데이터' 이렇게 추가로 화면에 뿌려지면서 보여지는 오류였던 것이다.

그래서 추가로 아래 코드를 구현해
실시간 업데이트 될때마다 기존의 리스트가 초기화 되게 하였다.

    document.getElementById('tbody').innerHTML = ''
    let temp_html = ''

<최종 조회 코드>

docRef = database
  .collection('comment')
  .orderBy('createdAt', 'desc')
  .onSnapshot((snapshot) => {
  
    // 리스트 초기화
    document.getElementById('tbody').innerHTML = ''
    let temp_html = ''

    snapshot.forEach((doc) => {
      let id = doc.id
      let data = doc.data()
      let name = data.name
      let comment = data.comment
      let createdAt = data.createdAt

      //  날짜 형식 변환
      createdAt = new Date(createdAt)
      var year = createdAt.getFullYear().toString().slice(-2) //년도 뒤에 두자리
      var month = ('0' + (createdAt.getMonth() + 1)).slice(-2) //월 2자리 (01, 02 ... 12)
      var day = ('0' + createdAt.getDate()).slice(-2) //일 2자리 (01, 02 ... 31)
      var hour = ('0' + createdAt.getHours()).slice(-2) //시 2자리 (00, 01 ... 23)
      var minute = ('0' + createdAt.getMinutes()).slice(-2) //분 2자리 (00, 01 ... 59)
      var second = ('0' + createdAt.getSeconds()).slice(-2) //초 2자리 (00, 01 ... 59)
      createdAt =
        year +
        '.' +
        month +
        '.' +
        day +
        '. ' +
        hour +
        ':' +
        minute +
        ':' +
        second

      temp_html += `
                    <tr data-documentId=${id} data-collectionName="comment">
                        <td>${name}</td>
                        <td>${comment}</td>
                        <td>${createdAt}</td>
                        <td><button class="edit">edit</button></td>
                        <td><button class="del">del</button></td>
                    </tr>
                    `
    })
    $('#tbody').append(temp_html)

아직 개발 초보라 알고보면 큰 오류도 아닌데 하루 종일 헤메기도 한다.
하지만 해결되고 보면 더 성장한 나를 발견하고 내가 만든 코드가 잘 돌아갈 때 느끼는 뿌듯함이 너무 좋다.

profile
더 많은 사람들이 더 좋은 정보와 서비스를 누릴 수 있게!!
post-custom-banner

0개의 댓글