- 프로젝트: 공우 어드민
- 키워드: firebase storage, recursively delete
- 상황
- 하나의 뉴스는 위지윅(WYSIWYG)으로 작성된 텍스트 파일, 썸네일 이미지, 첨부파일을 포함한다.
- 위의 3가지 정보(텍스트파일, 이미지, 첨부파일)는 firebase storage에 저장한다.
- 뉴스 id가 123 일 경우, 'news/123/content/content.txt', 'news/123/content/contentEng.txt', 'news/123/picture/thumbnail.png', 'news/123/attachments/example_1'...과 같이 저장한다.
- 뉴스 목록에서 삭제 버튼을 누르면 DB에 저장된 뉴스 정보와 함께 firebase storage의 파일들도 모두 삭제해야한다.
- 하지만 firebase storage API 에서 폴더 삭제(delete folder)를 지원하지 않는다.
- 해결방법
- 특정 폴더 안에 있는 모든 파일을 삭제할 경우, 빈 폴더는 자동 삭제되는 것을 확인했다. 따라서, news/123 이 포함하는 모든 txt, png, docx 등의 파일을 지우면 news/123 폴더는 자동 삭제될 것이다.
- deleteFolderContents 라는 함수를 만들고 삭제하고자하는 최상위 폴더를 인자로 넘긴다.
// firebase storage 데이터 삭제 deleteFolderContents(`example.com/news/123`);
- storage 의 listAll API(https://firebase.google.com/docs/storage/web/list-files#list_all_files) 를 사용하여 'news/123' 하위 목록을 얻는다.
// NOTE: 삭제할 firebase storage directory path 를 받아, listAll 로 파일 목록을 불러온 후 파일을 재귀적으로 삭제. export function deleteFolderContents(path: string) { const ref = storage.refFromURL(path); ref.listAll() .then(res => { res.items.forEach(fileRef => { deleteFile(ref.fullPath, fileRef.name); }); res.prefixes.forEach(folderRef => { deleteFolderContents(`gs://${folderRef.bucket}/${folderRef.fullPath}`); }); }) .catch(() => { alert('firebase storage 데이터 나열에 실패했습니다.'); }); }
이때, 각 res는 items 또는 prefixes를 가지는데, items일 경우 해당 객체가 파일임을 의미하고, prefixes면 폴더임을 의미한다.
items는 파일이므로 deleteFile 함수를 호출하여 파일 삭제를 실행하고, prefixes는 여전히 folder이므로 deleteFolderContents 함수를 재귀 호출한다.
- items일 경우 파일을 삭제하는 deleteFile 함수를 구현한다.
export function deleteFile(pathToFile: string, fileName: string) { const ref = storage.ref(pathToFile); const childRef = ref.child(fileName); childRef.delete().then(() => { console.log(`firebase storage ${pathToFile}/${fileName} 데이터 삭제 성공`); }).catch(() => { console.log(`firebase storage ${pathToFile}/${fileName} 데이터 삭제 실패`); }); }
- 이제 삭제 버튼을 누르고 firebase storage 를 확인하면 'news' 폴더 안에 'news/123' 이라는 폴더는 존재하지 않는다!
- Known issues
- 프로젝트에 storage.ref, storage.refFromURL의 사용이 혼재되어있다.
'프론트엔드' 카테고리의 다른 글
번들링 최적화를 통해 import cost 줄이기(1) (0) | 2021.11.25 |
---|---|
Chrome과 안드로이드 기기를 유선/무선 연결하기 (0) | 2021.11.23 |
safari inset, intersection observer 크로스 브라우징하기 (0) | 2021.11.18 |
css animation steps로 Spinner 구현하기 (0) | 2021.11.17 |
env 파일의 보안 취약점과 api key 유출에 대비하기 (0) | 2021.11.16 |