어제에 이어 사진 삭제 문제 해결을 시도해 본다.
게시판 글이 삭제될 때 해당 글에 첨부되어 있던 사진을 함께 지우지 못하고 있다.
특히 글을 처음 작성하는 경우, 해당 글의 id 는 supabase table에 처음 insert 될 때까지는 생성되지 않는데, 사진이 storage에 저장되는 것은 게시글 insert가 발생하기 이전 시점이다. 따라서 게시글 id 를 가지고 storage에서 해당 id와 연결되어 있는 사진을 삭제하는 식의 접근은 불가능하다.
사진 삭제 로직이 어딘가에 어떤식으로든 들어가지 않으면 결국 게시글이 지워져도 storage에 저장된 사진의 수는 시간이 지남에 따라 항상 늘어나기만 하므로 장기적인 관점에서 제대로된 프로젝트를 만들었다고 평가하기 어려울 것이다.
현재 게시판 게시글 table은 다음과 같이 생겼다.
먼저 각 게시글의 고유 식별자인 id가 있고, category, title, content, place_name, created_at을 저장하는 컬럼이 하나씩 있으며, 마지막으로 user_id 는 users 테이블의 id 를 외래키로 받아오고 있는 구조이다.
사진과 관련된 정보는 별도의 컬럼에 저장되어 있지 않은데, 그래도 화면 출력에 문제가 생기지 않는 이유는 storage에 저장된 사진에서 생성된 사진 url 이 content 내부의 img 태그의 src로 직접 들어가기 때문이다.
그렇지만 storage에 저장되어 있는 사진을 게시글이 삭제될때 함께 삭제되도록 하기 위해서는 테이블에도 사진의 정보를 담는 컬럼이 있어야 하겠다고 생각했고 이를 아래와 같이 추가해 주었다.
사진에서 NULL 로 표시된 row 들은 이 코드를 작성하기 이전에 등록된 게시물들 이므로 신경쓰지 않아도 된다. 중요한것은 이제 사진명이 배열로 attached_images 컬럼에 저장된다는 것. 사진이 없을 경우에는 []
이렇게 빈 배열로 저장되도록 하였다.
이렇게 사진이름 정보를 테이블에 함께 넣어주기 위해서 코드의 이곳 저곳을 수정했는데 그중 핵심적인 부분들만 가져오자면
//quill 이미지 핸들러
const imageHandler = async () => {
🎇const fileName = Date.now().toString();
🎇setInputs((prevInputs) => ({
...prevInputs,
images: [...prevInputs.images, fileName],
}));
(후략)
//신규 게시글 등록 데이터
const formData = {
title: inputs.title,
category: inputs.category,
content: inputs.content,
placeName: inputs.place_name,
userId,
attached_images: inputs.images,
};
// 게시글 삭제
export const deletePost = async ({
userId,
boardId,
images,
}: {
userId: string;
boardId: string;
images: string[];
}) => {
//저장된 이미지가 있을 경우 이를 storage 에서 제거
if (images && images.length !== 0) {
const { data, error } = await supabase.storage
.from('board_images')
.remove(images);
}
const { error } = await supabase
.from('boards')
.delete()
.eq('user_id', userId)
.eq('id', boardId);
if (error) {
console.log(error);
}
};
먼저 이미지 핸들러 함수에서 이미지가 삽입될때 해당 이미지의 이름을 Date.now()로 생성하고 생성한 이름을 state에 저장한다.
그후 게시글이 등록될때 등록 함수에 전달하는 formData에 이 이미지 이름들을 함께 넣어서 전달한다.
이렇게 하면 boards 테이블에 해당 게시물에 첨부된 이미지들의 이름들이 배열로 저장되게 된다.
그리고 게시글 삭제 함수에 images 배열이 존재하고, 그 배열의 길이가 0이 아닌 경우에 storage에서 images 배열에 등록되어있는 이름의 파일들을 삭제하도록 하고 있다.