072DATA

next.js supabase 이미지 업로드 본문

FrontEnd/Next.js

next.js supabase 이미지 업로드

0720 2024. 10. 15. 02:17

이미지 업로드 

 

supabase를 사용하여 스토리지 기능으로 이미지를 업로드하는 방법

 

파일 업로드 창 안 보이게 하기

우선 파일 업로드 창이 못 생겼으니 숨기고 나서 지정한 영역을 클릭하면 파일 업로더가 표시되도록 구현

 

파일 업로드 버튼을 테일윈드를 사용하여  hidden 속성으로 보이지 않게 하고,

사용자가 이미지를 클릭하면 파일 선택 창이 열리도록 구현하였음

이를 위해 useRef를 사용해서 클릭 이벤트로 파일 선택 창을 열 수 있게 함.

const fileInputRef = useRef<HTMLInputElement>(null);

// 미리보기 창 선택 시 이미지 업로더 선택
const handlePreviewClick = () => {
  if (fileInputRef.current) {
    fileInputRef.current.click();
  }
};

// JSX

<div className="border cursor-pointer" onClick={handlePreviewClick}>
	// 이 영역을 누르면 파일 업로드 표시
</div>
      
<input
  type="file"
  accept="image/*"
  multiple
  ref={fileInputRef}
  className="hidden"
  onChange={handleSetImage}
/>

 

 

 

이미지 상태 관리와 미리보기

 

파일을 선택하면 그 이미지의 미리보기 사용자에게 보여주는게 좋으니

setImageState를 통해 이미지 상태를 관리하고, 선택한 이미지의 URL을 생성해 미리보기 창에 표시

 

// 이미지 관련 상태 업데이트
const handleSetImage = (e: React.ChangeEvent<HTMLInputElement>) => {
  const files = e.target.files;

  if (files && files.length > 0) {
    const file = files[0];
    const preview = URL.createObjectURL(file); // 이미지 미리보기 URL 생성
    setImageState({ imageFile: file, prevImage: preview });
  }
};

// JSX
<div className="w-[200px] h-full rounded">
  {imageState.prevImage ? (
    <img className="w-full h-full object-cover" src={imageState.prevImage} alt="업로드 이미지" />
  ) : (
    <div className="m-0">사진을 추가하세요</div>
  )}
</div>

 

 

이미지 업로드 함수 구현

선택한 이미지를 supbase 스토리지에 업로드하는 함수를 작성. uploadImage 함수는

imageState를 인자로 받아, 이미지 파일이 존재하는지 확인한 후 서버에 업로드함

export const uploadImage = async (imageState: ImageType) => {
  if (!imageState.imageFile) {
    throw new Error("이미지 파일이 없습니다.");
  }

  const { data, error } = await browserClient.storage
    .from("post")
    .upload(`post_${imageState.imageFile.lastModified}`, imageState.imageFile);

  if (error) throw error;
  return data;
};

 

 

컴포넌트에서 API 함수 호출 

//생략...
  const [imageState, setImageState] = useState<ImageType>({ imageFile: null, prevImage: null });
    const handleUpload = async () => {
        try {
        	await uploadImage(imageState);
           	 alert("이미지 업로드 성공");
        } catch (error) {
       		console.error("업로드 실패:", error);
        }
    };

  return (
    <div>
      <ImageUploader 
        imageState={imageState} 
        setImageState={setImageState} 
        setFormData={setFormData} 
      />
    </div>
  );