Supabase로 웹사이트 3개 클론하기 (Next.js 14)를 수강하며 얻은 지식들을 정리합니다.
제가 수강중인 강의는 다음 링크에서 확인 가능해요!
Storage
Supabase는 Supabase Storage라는 Storage 프레임워크를 제공합니다.
이미지, 비디오, 문서 등 거의 모든 파일 유형을 저장할 수 있을 뿐더러 CDN을 통해 지역과 관계없이 빠른 레이턴시로 응답을 가능하게 만들어주고
또 이미지 최적화 도구도 내장되어있다고해요 사실 S3, Firebase Storage 등 다른 SaaS 서비스들도 제공하는 기능이긴 합니다
이 Storage는 파일, 폴더, 버킷으로 구분되는데요 각각의 정의는 아래에서 다루어보겠습니다.
File
파일은 모든 종류의 파일일 수 있습니다.
이미지, GIF, 비디오 등이 포함되며 파일 크기 때문에 DB 외부에 파일을 저장하는 것이 좋은 것들입니다.
보안을 위해서 HTML 파일의 경우에는 일반 텍스트로 반환된다고 해요
Folder
폴더는 파일을 정리하는 방법입니다. 컴퓨터를 사용하는 사람이라면 너무 익숙한 개념이다보니 굳이 따로 설명을 하지 않아도 될 것 같아요
우리가 생각하는 그 폴더와 완전히 동일합니다.
Bucket
버킷은 파일과 폴더를 위한 별도의 컨테이너입니다.
Supabase의 Docs에서는 폴더는 폴더인데 그냥 Super 한 폴더다. 라고 생각하면 된다. 라고 소개하는데요
보통 보안 정책, 액세스 규칙에 따라 버킷을 나누어서 만든다고 합니다.
Supabase Storage
앞서 버킷이 슈퍼폴더같은거라고 설명을 했습니다.
supabase에서도 storage를 사용할 때에는 먼저 버킷을 생성해야하는데요 이 과정에서 CRUD Policy를 설정할 수 있어요
예를들면 사진과 같이 MIME types(인터넷에서 데이터를 전송할 때 그 데이터가 어떤 형식인지 나타내는 표준이에요)
가 image인 것만 허용을 한다면 image가 아닌 것들은 허용하지 않겠다.라는 의미가 되는거죠
MIME 타입은 type/subtype 형태가 되기때문에 image/png 와 같은 형태로 표기됩니다.
그런데 위와 같이 image/* 라고 표기했다면 type은 image로 제한하지만 뒤에 오는 서브타입은 상관하지않겠다. 라는 의미인거죠
서버액션을 통해 파일 업로드하기
서버액션은 next.js approuter에서 제공하는 기능으로 서버에서 실행하는 비동기 함수입니다.
// Server Component
export default function Page() {
// Server Action
async function create() {
'use server'
// ...
}
return (
// ...
)
}
그리고 next.js 13버전이 발표될때 온 커뮤니티를 nextjs 밈으로 만들어버린 'use server' 키워드를 사용하는 기능이기도 하고요
서버액션이 유용한 점은 기존에 서버에서만 수행할 수 있기때문에 별도의 API Endpoint를 만들어 수행하던 작업을
API Endpoint를 만드는 대신 마치 직접 서버코드를 사용하는 것 같은 형태로 바꿔 작성할 수 있는 점인 것 같습니다.
export async function uploadFile(formData: FormData) {
const supabase = await createServerSupabaseClient();
const files = Array.from(formData.entries()).map(
([name, file]) => file as File
);
const results = await Promise.all(
files.map((file) =>
supabase.storage
.from(process.env.NEXT_PUBLIC_STORAGE_BUCKET)
.upload(file.name, file, { upsert: true })
)
);
return results;
}
예컨대 이렇게 uploadFile이라는 서버액션 코드를 정의해두고 클라이언트에서는 다음과 같이 사용해버립니다.
const uploadImageMutation = useMutation({
mutationFn: uploadFile,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["images"],
});
},
});
만약 서버액션이 불가했다면 uploadFile을 위한 API Endpoint를 새로 생성하고
그 API Endpoint로 요구되는 body를 갖추어서 fetch 요청을 보내는 코드를 추가적으로 작성해주어야했을 것입니다.
이런 관점에서 서버액션은.. 조롱 당하기도 했지만 개발자 입장에서 참 편리한 기능인 것도 사실인 것 같습니다.
혹시 서버액션에 대해 더 많은 정보가 궁금하신 경우에는 아래 링크를 참고하세요
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
react-dropzone 라이브러리
파일과 밀접한 관련이 있는 사이트들을 이용하다보면 이렇게 드래그앤드롭으로 파일을 업로드할 수 있는 UX가 제공되는 경우가 많습니다.
이 역시도 쓰는 입장에서는 별 생각없이 쓰지만.. 막상 구현해보라고하면 조금 머리가 새하얘지기 일쑤인데요
react-dropzone의 경우 이런 페인포인트를 해결하는 라이브러리입니다.
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
multiple: true,
});
return (
<div
{...getRootProps()}
className="w-full py-20 border-4 border-dotted border-indigo-700 flex flex-col items-center justify-center cursor-pointer"
>
<input {...getInputProps()} />
{uploadImageMutation.isPending ? (
<Spinner />
) : isDragActive ? (
<p>파일을 놓아주세요.</p>
) : (
<p>파일을 여기에 끌어다 놓거나 클릭하여 업로드하세요.</p>
)}
</div>
);
API도 상당히 직관적이기 때문에 쉽게 이해할 수 있었습니다.
개인적으로는 dropzone 구현이 필요할때 다른 훨씬 좋은 선택지가 생기지 않는다면 계속 사용할 것 같아요
마치며
이번에는 supabase의 storage와 더불어 서버액션, dropzone 구현에 대한 내용을 다루었습니다.
해당 내용 뿐만아니라 더 많은 유용한 정보들을 빠르게 학습하고 싶으시다면
해당 강의를 수강해보시는 것을 추천드리겠습니다.
그럼 이만 글 마치도록 하겠습니다.
읽어주셔서 감사합니다!
'TIL' 카테고리의 다른 글
Supabase로 웹사이트 3개 클론하기 (Next.js 14)를 수강하며 (3) (1) | 2024.08.13 |
---|---|
Supabase로 웹사이트 3개 클론하기 (Next.js 14)를 수강하며 (1) (0) | 2024.08.12 |
javascript koans (0) | 2023.03.03 |
에라토스테네스의 체 소수 찾기 알고리즘을 자바스크립트로..? (0) | 2023.02.22 |
2.21 TIL (0) | 2023.02.21 |