티스토리 뷰
supabase
파일 시스템 | 데이터베이스 모델링 | 관계형 데이터베이스 |
파일(file) | 엔터티(Entity) | 테이블(table) |
레코드(record) | 튜플(Tuple) | 행(row) |
키(key) | 유일값(identifier) | 기본키(Primary key), unique |
필드(field) | 어트리뷰트(attribute) | 컬럼(column) |
등록
supabase storage에 버킷 생성 후 이미지를 담아줄 폴더 생성
공식 문서를 참고하여 버킷이름, 폴더 경로, 파일 이름을 넣어 이미지 등록 로직 작성
이미지 파일명은 email과 UUID로 생성하여 중복되지 않게 한다
이미지 등록 성공 시 반환되는 data.path 변수에 담아준다 (path : 파일 등록 경로)
글 등록 시 supabase 테이블에 들어갈 내용을 객체 형태로 만들어주고 이미지가 들어가는 곳에 path를 담은 변수를 넣어준다 그럼 reviewimg에 들어간 파일 경로로 이미지를 불러올 수 있다
export const insertReview = async ([
placename,
imgPath,
imgName,
reviewContent,
reset,
setAddImg,
email,
nickname,
avatar
]) => {
// storage에 이미지 등록
let storagePath = '';
if (imgPath) {
const { data, error } = await supabase.storage
.from('reviewImage')
.upload(`reviewFile/files/${email}${imgName}`, imgPath, {
cacheControl: '3600',
upsert: false
});
if (!error) {
storagePath = data.path; // 이미지 등록이 성공하면 이미지 경로 저장("reviewFile/files/kim@naver.com06cea4ae-f3e1-4b2f-a00c-9538c8f763d1")
} else {
console.error('이미지 등록 실패!', error);
}
}
const newReviews = {
marker: placename.placename,
email,
nickname,
avatar,
content: reviewContent,
reviewimg: storagePath,
imageUrl: '' // reviewList component에서 조회 시 url이 들어감
};
// 글 등록
const { data, error } = await supabase.from('reviewWrite').insert([newReviews]).select();
if (data) {
alert('게시물이 등록 되었습니다.');
reset();
setAddImg(null);
return data;
} else {
alert('게시물 등록에 실패했습니다.');
console.error('error', error);
}
};
조회
supabase에 저장된 게시물을 먼저 가져온다
서버에서 가져온 게 데이터를 map으로 반복하며 게시물 reviewImg 레코드로 storage에 저장된 이미지를 조회 후 url로 변환해 준 후 게시물 테이블에 필드를 추가해 준다
export const getReviewList = async () => {
const { data: reviewWrite, error } = await supabase.from('reviewWrite').select('*');
if (error) {
console.error(error);
} else {
// 이미지 조회
const reviewsWriteData = reviewWrite.map((item) => {
const imgUrl = supabase.storage.from('reviewImage').getPublicUrl(item.reviewimg);
if (!imgUrl.error) {
return { ...item, imageUrl: imgUrl.data.publicUrl };
} else {
alert('이미지를 가져오지 못했습니다.');
console.error('이미지 가져오기 실패', imgUrl.error);
}
});
return reviewsWriteData;
}
};
삭제
회원 고유의 값과 게시물 등록 시 이미지 경로를 넣어준 review를 기준으로 데이터베이스에서 값을 찾아 삭제한다
export const deleteReview = async ([id, reviewimg]) => {
console.log('id, reviewimg', id, reviewimg);
// 이미지 삭제
const { data, error: imgError } = await supabase.storage.from('reviewImage').remove(reviewimg);
if (!imgError) {
console.log('이미지 삭제 성공', data);
} else {
console.log('이미지 삭제 실패', imgError);
}
// 게시글 삭제
const { error } = await supabase.from('reviewWrite').delete().eq('id', id);
if (!error) {
alert('게시물이 삭제되었습니다.');
console.log('게시물 삭제 성공');
return;
} else {
console.log('게시물 삭제 실패', error);
}
};
수정
이미지 수정 시 스토리지에 변경 후 파일이 변경 전 파일명과 같을 경우 이전 리소스를 계속 불러오는 브라우저 캐시문제가 발생한다, 이를 해결하기 위해 수정 파일을 등록과 동일하게 새 이름을 만들어 스토리지에 저장하면 해결된다
다만 데이터 베이스에 이전 파일이 그대로 남아버린다는 단점이 있다
게시물도 회원 id값으로 데이터를 찾은 후 등록과 동일하게 객체형태로 담아 저장하면 수정이 완료된다.
export const updateStorage = async (img, storagePath, newPath) => {
const imgUpdate = await supabase.storage.from('reviewImage').upload(newPath, img, {
cacheControl: '3600',
upsert: true
});
if (imgUpdate.error) {
console.log('이미지 수정 실패', imgUpdate.error);
} else {
console.log('이미지 수정 완료', imgUpdate);
// storagePath = imgUpdate.data.path;
return imgUpdate.data.path;
}
};
// 게시물 수정
export const updateReview = async ([id, modifyReviewData, setEditDataId]) => {
const { data, error } = await supabase.from('reviewWrite').update(modifyReviewData).eq('id', id).select();
if (!error) {
console.log('게시물 수정 완료', data);
alert('게시물 수정이 완료되었습니다');
setEditDataId(null);
} else {
console.log('게시물 수정 실패', error);
}
};
Github
https://github.com/NBC4-Outsourcing/zarani
GitHub - NBC4-Outsourcing/zarani: 자전거 도로 후기 및 정보 공유 커뮤니티 제작 Project
자전거 도로 후기 및 정보 공유 커뮤니티 제작 Project. Contribute to NBC4-Outsourcing/zarani development by creating an account on GitHub.
github.com
ZARANI
ZARANI
zarani.vercel.app
'TIL > React' 카테고리의 다른 글
[리액트 React] 아웃소싱프로젝트_수파베이스 (SupaBase) (0) | 2024.02.26 |
---|---|
[리액트 React] 리덕스툴킷 (ReduxToolkit) (0) | 2024.02.24 |
[리액트 React] 리덕스 (Redux) (0) | 2024.02.23 |
[리액트 React] 쓰로틀링, 디바운싱_2 (Throttling & Debouncing) (0) | 2024.02.21 |
[리액트 React] 쓰로틀링, 디바운싱_1 (Throttling & Debouncing) (0) | 2024.02.20 |