블로그로 돌아가기
Javascript

supabase storage 이미지 업로드: 실무 가이드와 예제

supabase storage 이미지 업로드 방법을 개념과 예제로 정리한 실무 가이드입니다. 업로드 패턴, 보안 설정, 성능 최적화와 체크리스트를 바로 적용할 수 있습니다. 실무 적용 흐름과 자주 하는 실수까지 함께 확인할 수 있습니다.

supabasestorage이미지업로드signed-url파일처리
Supabase storage에 이미지 업로드하는 과정을 설명하는 기술 블로그 썸네일

supabase storage 이미지 업로드이 필요한 상황

supabase storage 이미지 업로드는 사용자 프로필, 게시글 이미지, CDN 전달 전처리 등 웹 서비스에서 이미지 파일을 안전하고 효율적으로 다루어야 할 때 쓰입니다. 이 글에서는 개념 이해, 인증/권한 처리, 프론트엔드 업로드 예제, 리사이징·보안·운영 주의점까지 실무에서 바로 적용 가능한 수준으로 정리합니다.

supabase storage 이미지 업로드 핵심 개념

  • 버킷과 객체: Supabase Storage는 버킷(bucket) 단위로 객체(object)를 저장합니다. 버킷마다 공개/비공개(ACL) 설정이 가능합니다.
  • 인증과 권한: 사용자 인증(예: JWT)을 통해 업로드 권한을 제어합니다. 공개 버킷은 URL로 바로 접근 가능, 비공개 버킷은 Signed URL을 발급해 제한적 접근을 허용합니다.
  • 리사이징·변환: 업로드 시 클라이언트 측에서 리사이징하거나 서버/함수에서 처리해 저장소 비용과 전송 비용을 줄입니다.
  • 트랜잭션성: 이미지 업로드와 DB 레코드 생성은 일관성을 위해 실패 시 롤백 로직을 고려합니다.

supabase storage 이미지 업로드 실무 예제

아래 예제는 supabase-js를 사용하는 React/Node 환경의 기본 업로드 흐름입니다. 비공개 버킷에 업로드한 뒤 Signed URL을 발급해 접근하는 패턴을 사용합니다.

// JavaScript (supabase-js) 예제 import { createClient } from '@supabase/supabase-js' const supabase = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) async function uploadImage(file, userId) { const filePath = `images/${userId}/${Date.now()}_${file.name}` // 비공개 버킷에 업로드 const { data, error } = await supabase.storage .from('private-images') .upload(filePath, file, { cacheControl: '3600', upsert: false }) if (error) throw error // Signed URL 발급 (기본 만료 1시간) const { data: urlData, error: urlError } = await supabase.storage .from('private-images') .createSignedUrl(filePath, 60 * 60) if (urlError) throw urlError return { path: filePath, url: urlData.signedUrl } }

핵심 포인트:

  • upsert 옵션: 중복 파일 처리 정책
  • cacheControl: CDN 캐싱 정책 설정
  • createSignedUrl: 비공개 파일에 대한 임시 접근 링크

비교: 공개 버킷 vs 비공개 버킷 (판단 기준표)

구분항목1항목2항목3
내용공개 버킷비공개 버킷권장 상황
내용즉시 URL 접근 가능, CDN 활용 쉬움Signed URL 필요, 보안 우수공개 리소스: 프로필 사진 제외, 상품 이미지 등 공개 콘텐츠
내용캐싱 유리, 비용 절감 가능접근 제어 필요 시 사용회원 전용 리소스, 결제 콘텐츠

언제 쓰면 좋고 언제 피해야 할까

  • 언제 쓰면 좋은가

    • 사용자 프로필, 게시글 첨부 이미지처럼 빈번한 직접 접근이 필요한 경우
    • CDN과 연동해 캐시를 활용해 대역폭 비용을 줄이고 싶을 때
    • 빠른 개발과 쉬운 관리가 우선일 때
  • 언제 피해야 하는가

    • 고도로 민감한 이미지(의료/신분증 등)는 별도 암호화 저장과 엄격한 접근 통제 필요
    • 대용량 이미지 변환을 많이 수행해야 하고 서버 사이드 처리가 복잡하면 전용 WAS/서버리스 처리 파이프라인을 고려

실무 체크리스트

  • 인증/권한
    • 업로드 API 호출 시 JWT 또는 서버 검증 로직 적용
    • 비공개 버킷 사용 시 Signed URL 발급 정책 결정
  • 파일 처리
    • 허용 확장자 및 최대 파일 크기 검증
    • 멀웨어/바이러스 스캐닝 고려
  • 저장 정책
    • 버킷별 캐시 정책(cacheControl) 설정
    • 파일 네이밍 규칙(중복 방지 및 폴더 분리)
  • 운영
    • 백업 및 수명 주기 정책(Lifecycle) 설정
    • 모니터링(오류률, 비용 추적) 구성

성능·보안·운영 주의점

성능

  • 다중 부분 업로드(Multipart) 또는 리사이즈 후 업로드로 클라이언트 대역폭 최적화
  • CDN과의 연계로 정적 이미지 캐싱 활용

보안

  • 민감 데이터는 버킷 암호화·비공개 설정 후 Signed URL로만 제공
  • 업로드 요청은 서버에서 토큰 교환 또는 프록시 검증을 통해 직접 인증 후 처리
  • CORS 설정: 허용 도메인 최소화

운영

  • 저장 비용 모니터링: 오래된 파일 정리(Lifecycle)
  • 로그와 에러 추적을 통해 업로드 실패율, 재시도 로직 개선

자주 묻는 질문

Q1: Supabase에서 이미지 업로드 시 파일 크기 제한이 있나요?

  • A: Supabase 자체는 업로드 크기를 제한하지 않지만, 브라우저와 네트워크 한계, 프록시 또는 서버 설정(Nginx 등)에 의한 제한은 있을 수 있습니다. 클라이언트에서 최대 허용 크기를 검증하고 서버 설정을 확인하세요.

Q2: 비공개 버킷 이미지를 CDN으로 제공하려면 어떻게 하나요?

  • A: 일반적으로 Signed URL을 통해 CDN 엔드포인트에 전달하거나, 프록시 서버에서 인증 후 캐시 가능한 공개 URL로 변환하는 패턴을 사용합니다. CDN이 Signed URL을 지원하는지 확인해야 합니다.

Q3: 업로드 도중 중복 파일 이름 처리 어떻게 해야 하나요?

  • A: 타임스탬프, 유저ID, 해시를 조합한 파일명 규칙을 사용하거나 upsert 옵션을 false로 두고 충돌 시 에러를 반환해 처리하면 안전합니다.

Q4: 이미지 리사이즈는 클라이언트에서 할까 서버에서 할까?

  • A: 사용자 환경 다양성을 고려하면 원본을 보관하고 서버(또는 서버리스 함수)에서 다양한 사이즈를 생성해 저장·캐시하는 방식이 일반적입니다. 다만 클라이언트에서 사전 리사이즈하면 업로드 비용과 대역폭을 줄일 수 있습니다.

정리

  • supabase storage 이미지 업로드는 버킷 설정(공개/비공개), 인증, Signed URL 패턴을 이해하면 실무 적용이 쉽습니다.
  • 업로드 전 파일 검증, 캐시 정책, 네이밍 규칙을 반드시 적용하세요.
  • 보안이 중요한 리소스는 비공개 버킷 + Signed URL + 최소 권한 원칙을 사용하세요.
  • 성능 최적화는 리사이즈, CDN 연계, 멀티파트 업로드 전략으로 접근하세요.
  • 체크리스트를 기반으로 운영·모니터링을 설정해 비용과 안정성을 관리하세요.