티스토리 뷰

what i learned/TIL

[TIL] 2021/12/02 Thu -

zubetcha 2021. 12. 2. 22:46

 

 

 

 

 

 

Today I Learned

를 가장한 Yesterday I Learned

 

 

 

오늘도 개인 과제만 했다!

 

 

무한스크롤, 좋아요 기능, 레이아웃 선택 등 구현해야 하는 것들이 여러가지 남아있었지만,

그중에서도 삭제 기능은 저번 주 과제할 때 추가로 넣었던 기능이라 금방 끝날 줄 알고 포스트 삭제를 먼저 구현하기 시작했다.

 

 

👩🏻‍🌾 오늘의 수확

 

 

📍 포스트 삭제 버그 해결

 

 

처음 코드를 작성해 나가는 데는 큰 어려움은 없었지만

다 작성하고 확인해 보니 두 가지 문제가 발생하고 있음을 발견했다.

 

 

1) 삭제 버튼을 누르면 포스트는 그대로 남고 이미지만 사라지는 문제

 

   이번 주에는 포스트에는 이미지를 업로드 할 수 있어 Firebase의 Firestore 뿐만 아니라

   Storage 도 함께 이용하여 업로드한 이미지는 Storage 에 저장되게끔 하였다.

   

   Firestore의 데이터 필드 중 이미지 url은 Storage에 저장된 이미지의 url을 가져다 사용하고 있기도 하고,

   문서는 삭제했는데 Storage에는 이미지가 그대로 쌓여 있는 게 이상해서 둘 다 동시에 삭제하기로 하였다.

 

   다만 별다른 장치 없이 Firestore 삭제 -> Redux 삭제 -> Storage 삭제 순서대로 코드를 작성했더니

   Storage 의 이미지가 먼저 삭제되는 경우에는 Firestore와 Redux에 설정되어 있는 이미지 url이 사라지는 게 돼서 포스트는 삭제되지 않고 포스트 상의 이미지만 사라지는 문제가 발생하고 있었다.

 

   그래서 중첩이 발생하지 않도록 .then()을 이용하여 순서를 잡아줬더니 문제가 해결되었다!

  

   게시글을 포스트할 때는 Storage에 이미지를 먼저 저장해서 이미지 url을 생성하는 게 먼저지만

   삭제할 때에는 이미지 url이 가장 마지막에 삭제되어야 해서 마지막 순서로 지정했다.

 

 

// 포스트 삭제 미들웨어

const deletePostFB = (post_id, image) => {
  return async function (dispatch, getState, { history }) {
    if (!post_id) {
      window.alert("게시물 정보가 없습니다.");
      return;
    }

    const _image = storage.ref().child(`images/${image}`);

    await deleteDoc(doc(firestore, "post", post_id))
      .then(() => {
        dispatch(deletePost(post_id));
        _image.delete().then(() => {
					window.location.reload();
				})
      })
      .catch((err) => {
        console.log("게시글 삭제에 문제가 발생했습니다", err);
      });
  };
};

 

 

   그리고 Storage에서 파일을 삭제하려면 삭제하려는 파일의 참조를 먼저 만들어야 하는데

   문서를 보니 내가 Storage에 저장할 때 사용한 파일 이름을 넣어줘야 참조를 만들 수 있었다.

 

   나는 Storage에 저장할 때 파일 이름의 양식을 uid_포스트 작성 시간으로 설정했기 때문에

   이미지의 url이 부여되면 아래의 노란색의 하이라이트 부분과 같이 저장한 파일명만 추출해야 했다.

 

 

https://firebasestorage.googleapis.com/v0/b/clickme-2590c.appspot.com/o/images%2FlyzEovLcNMfthwSBqhjWED87F9y1_1638461508328?alt=media&token=6aaf0012-ef85-413a-b11a-b7d594f6e69e

 

  

  url에서 파일명을 추출할 때에는 정규식을 사용하는 멋드러지는 방법도 있지만,

  나는 split과 substring을 이용하여 노가다 아닌 노가다로 파일명을 추출했다.

 

 

image_url = "https://firebasestorage.googleapis.com/v0/b/clickme-2590c.appspot.com/o/images%2FlyzEovLcNMfthwSBqhjWED87F9y1_1638461508328?alt=media&token=6aaf0012-ef85-413a-b11a-b7d594f6e69e";

image_url.split("/")
// ["https:", "", "firebasestorage.googleapis.com", "v0", "b", "clickme-2590c.appspot.com", "o", "images%2FlyzEovLcNMfthwSBqhjWED87F9y1_1638461508328?alt=media&token=6aaf0012-ef85-413a-b11a-b7d594f6e69e"]

// 위의 배열에서 파일명이 포함되어 있는 인덱스는 7이기 때문에

image_url.split("/")[7]
// "images%2FlyzEovLcNMfthwSBqhjWED87F9y1_1638461508328?alt=media&token=6aaf0012-ef85-413a-b11a-b7d594f6e69e"

// 다시 ? 로 split

image_url.split("/")[7].split("?")
// ["images%2FlyzEovLcNMfthwSBqhjWED87F9y1_1638461508328", "alt=media&token=6aaf0012-ef85-413a-b11a-b7d594f6e69e"];

// 위의 배열 중 파일명을 포함하고 있는 요소는 0번 째이기 때문에

image_url.split("/")[7].split("?")[0]
// "images%2FlyzEovLcNMfthwSBqhjWED87F9y1_1638461508328"

// 위의 문자열에서 파일명은 images%2F 다음부터 끝까지이기 때문에
// substirng()을 이용하여 파일명만 추출

image_url.split("/")[7].split("?")[0].substring(9)
// "lyzEovLcNMfthwSBqhjWED87F9y1_1638461508328"

 

 

머리가 안 좋으면 머리가 고생한다(?).

 

 

 

 

2) 포스트를 새로 작성한 직후에는 삭제가 되지 않는 문제 (리프레쉬 후에만 삭제 가능)

  

 

    사실 이건 삭제 기능의 문제라기 보다는 포스트 추가 기능의 문제였다.

 

    알고 보니 포스트를 새로 작성한 직후에는 포스트에 문서 id가 부여되지 않고

    새로고침을 해준 후에야 포스트에 id가 부여되고 있었다.

 

    그래서 포스트를 새로 작성한 직후에는 추가된 포스트에 id가 없기 때문에

    삭제할 때 포스트 참조를 위해 넘겨줄 수 있는 id도 없어서 발생하는 문제였다.

 

 

    Firestore에 문서를 추가해주는 addDoc 앞에 await 을 붙이고 싶었으나 async 를 쓸 수 없어 포기하고,

    8 버전으로 다시 작성할 까 하다가 addDoc 후에 then으로 넘어갈 때 인자에 docRef를 넣어주니 문제가 해결되었다.

 

 

// 생략

_upload
      .then((snapshot) => {
        snapshot.ref
          .getDownloadURL()
          .then((url) => {
            return url;
          })
          .then((url) => {
            const docRef = addDoc(collection(firestore, "post"), {
              ...user_info,
              ..._post,
              image_url: url,
            }).then((docRef) => {
              let post = { user_info, ..._post, id: docRef.id, image_url: url };
              dispatch(addPost(post));
              history.replace("/");

              dispatch(imageActions.setPreview(null));
            });
          })
          .catch((err) => {
            window.alert("게시글 작성에 문제가 있습니다.");
            console.log("게시글 작성에 실패했습니다.", err);
          });
      })
      .catch((err) => {
        window.alert("이미지 업로드에 문제가 있습니다.");
        console.log("이미지 업로드에 문제가 있습니다.", err);
      });
      
// 생략

 

 

 

📍 무한 스크롤 구현

  

 

throttle과 lodash를 이용하여 무한스크롤을 구현해보았다.

 

정말 신기한데....

이게 왜 되지? 하는 찝찝함....

 

과제를 끝내고 다시 복습해야겠다.

 

 

 

 

 

 

 

 

'what i learned > TIL' 카테고리의 다른 글

[TIL] 2021/12/10 Fri -  (0) 2021.12.10
[TIL] 2021/12/06 Mon -  (0) 2021.12.06
[TIL] 2021/12/01 Wed -  (0) 2021.12.01
[TIL] 2021/11/30 Tue -  (2) 2021.11.30
[TIL] 2021/11/29 Mon -  (0) 2021.11.29
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Total
Today
Yesterday