파일
버킷과 업로드, 공개와 비공개의 차이, S3로 쓰기, Supabase에서 파일 옮기기, 이어 올리기(TUS).
파일
POST /storage/v1/bucket {"id":"avatars","public":true}
POST /storage/v1/object/avatars/<이름> 본문: 파일 바이트
GET /storage/v1/object/avatars/<이름>
DELETE /storage/v1/object/avatars/<이름>공개 버킷과 비공개 버킷
public: true인 버킷의 파일은 누구나 받을 수 있고 CDN이 캐시해요.
그렇지 않은 버킷은 올린 사람만 받을 수 있고 캐시되지 않아요.
프로필 사진처럼 이미 공개된 것은 공개 버킷, 그 외에는 비공개가 기본이에요.
Supabase용으로 쓴 파일 규칙도 그대로 써요. storage.foldername(name), storage.filename(name), storage.extension(name)과 storage.buckets의 name·owner 열이 있어서, (storage.foldername(name))[1] = auth.uid()::text 같은 조건을 콘솔의 [접근 규칙] 화면, Supabase에서 옮기기, 또는 SQL 편집기·run_sql·마이그레이션의 create policy … on storage.objects로 넣으면 이 프로젝트의 이름으로 바뀌어 동작해요. SQL로 넣으면 나머지 SQL이 끝난 뒤 One Server가 그 규칙을 만들어요.
S3로 쓰기
AWS SDK, aws CLI, rclone처럼 S3를 쓰는 도구로 같은 버킷을 다뤄요. REST로 올린 파일이 S3에 보이고, 그 반대도 같아요.
endpoint: https://<ref>.<zone>/storage/v1/s3
region: ap-northeast-2
forcePathStyle: true접근 키는 create_s3_key로 만들고(비밀 접근 키는 그 응답에만 있어요), list_s3_keys로 보고, revoke_s3_key로 폐기해요.
접근 키는 서비스 역할이라 접근 규칙(RLS)을 무시해요. 서버에만 두세요.
앱 사용자의 권한으로 쓰려면 세션 토큰 방식이에요: 접근 키 ID에 프로젝트 ref, 비밀 접근 키에 공개 키(bw_publishable_…), 세션 토큰에 사용자의 액세스 토큰을 넣어요.
그 사용자의 접근 규칙이 그대로 적용돼요.
ListBuckets, CreateBucket, DeleteBucket, HeadBucket, ListObjectsV2, GetObject(Range), HeadObject, PutObject, CopyObject, DeleteObject(s), 멀티파트 업로드를 지원해요. 버전 관리·ACL·태그·수명 주기는 NotImplemented로 답해요.
Supabase에서 파일 옮기기
Supabase Storage도 S3로 열 수 있어서, rclone 하나로 버킷을 통째로 옮겨요.
경로가 그대로라 표에 저장된 파일 경로(avatars/123.png)는 바꾸지 않아도 돼요.
1. 여기에 같은 이름의 버킷을 먼저 만들어요(create_bucket). 공개 여부도 Supabase와 같게 골라요.
2. Supabase 대시보드의 Storage 설정에서 S3 접근 키를 만들고, 여기서는 create_s3_key로 만들어요.
3. rclone 설정(~/.config/rclone/rclone.conf)에 두 곳을 적어요.
[supabase]
type = s3
provider = Other
endpoint = https://<supabase-ref>.supabase.co/storage/v1/s3
region = <Supabase 프로젝트의 리전>
access_key_id = <Supabase 접근 키 ID>
secret_access_key = <Supabase 비밀 접근 키>
[oneend]
type = s3
provider = Other
endpoint = https://<ref>.<zone>/storage/v1/s3
region = ap-northeast-2
access_key_id = <create_s3_key의 접근 키 ID>
secret_access_key = <create_s3_key의 비밀 접근 키>4. 버킷마다 복사해요. 다시 실행하면 바뀐 파일만 보내요.
rclone copy supabase:avatars oneend:avatars --progress
rclone check supabase:avatars oneend:avatars # 빠진 파일이 없는지 확인aws CLI만 있으면 내려받았다가 올려요.
aws s3 sync s3://avatars ./avatars --endpoint-url https://<supabase-ref>.supabase.co/storage/v1/s3
aws s3 sync ./avatars s3://avatars --endpoint-url https://<ref>.<zone>/storage/v1/s3파일 하나의 최대 크기는 요금제를 따라요(무료 50MB, Pro 5GB). 공개 주소는 https://<ref>.<zone>/storage/v1/object/public/<버킷>/<경로>로 바뀌니, 표에 전체 주소를 저장했다면 그 주소만 고쳐요.
이어 올리기(TUS)
큰 파일은 TUS로 올리면 연결이 끊겨도 이어서 보낼 수 있어요. tus-js-client나 Uppy를 그대로 써요.
endpoint: https://<ref>.<zone>/storage/v1/upload/resumable
headers: Authorization: Bearer <key or access token>, x-upsert: true
metadata: bucketName, objectName, contentType, cacheControl하루 동안 이어 받지 않은 업로드는 만료되고 지워져요. 일반 업로드도 S3·TUS로 올리는 파일 하나도 요금제 한도(무료 50MB, Pro 5GB)를 따르고, 버킷 한도가 더 작으면 그걸 따라요.
도구로 파일 다루기
list_objects 버킷 안의 폴더 보기 (prefix, search)
upload_object 파일 하나 올리기 (2MB까지, 바이너리는 base64)
download_object 파일 하나 받기 (2MB까지)
delete_object 파일 하나 지우기
create_signed_url 비공개 파일을 정해진 시간 동안 받을 수 있는 주소 (최대 7일)
create_upload_url 큰 파일(이미지·영상)을 PUT으로 올릴 주소 (2시간, 한 파일)
update_bucket 버킷의 공개 여부, 파일 크기 한도, 받을 형식 바꾸기
empty_bucket 버킷 안의 파일 모두 지우기 (confirm에 버킷 이름)
delete_bucket 빈 버킷 지우기 (confirm에 버킷 이름)더 큰 파일은 위의 /storage/v1 주소로 올리고 받아요.
이미지·영상은 내용을 도구 인자로 보내지 말고 create_upload_url로 주소를 받아
그 url에 PUT해요: curl -X PUT -H 'content-type: video/mp4' --data-binary @./intro.mp4 '<url>'.
한 번에 max_bytes(요금제의 파일 하나 한도: 무료 50MB, Pro 5GB. 버킷 한도가 더 작으면 그것)까지 올려요. 느린 회선에서 큰 파일은 끊긴 곳부터 잇는 이어 올리기(TUS)가 편해요.
REST로는 POST /v1/projects/<ref>/buckets/<버킷>/upload-urls이에요.
버킷을 만들 때(create_bucket)나 나중에(update_bucket) file_size_limit(예: "5MB")와 allowed_mime_types(예: ["image/*"])로 받을 파일을 정해요.
버킷을 지우려면 먼저 empty_bucket으로 비우고, delete_bucket의 confirm에 버킷 이름을 그대로 넣어요. empty_bucket도 confirm에 버킷 이름을 받아요.
되돌릴 수 없는 도구는 모두 이렇게 confirm에 지울 것의 이름을 받아요: empty_bucket, delete_queue, purge_queue, reset_branch, delete_branch, remove_function, remove_domain, delete_gpu_server, disable_extension, remove_user(이메일 또는 id), reset_database_password·set_spend_cap(끌 때)·rotate_signing_key(grace_hours: 0일 때)는 프로젝트 이름. 틀리거나 비우면 무엇을 넣어야 하는지 알려 주며 거절해요.
REST로는 PATCH /v1/projects/<ref>/buckets/<버킷>, POST /v1/projects/<ref>/buckets/<버킷>/empty, DELETE /v1/projects/<ref>/buckets/<버킷> {confirm}이에요.
저장소 설정, 이전 버전, 배포에 연결한 버킷
get_storage_settings 파일 하나 최대 크기, 이미지 변환, S3 주소, 버킷마다 버전 보관
set_storage_settings 프로젝트 전체의 파일 크기 한도와 이미지 변환 (빠진 항목은 그대로)
set_s3_enabled S3 주소 켜기·끄기 (키는 남아요)
set_bucket_versioning 버킷이 덮어쓴·지운 파일을 이전 버전으로 남길지, 며칠 둘지
list_object_versions 이전 버전 목록 (name을 주면 그 파일만)
restore_object_version 이전 버전을 지금 파일로 되돌리기
remove_object_version 이전 버전 영구 삭제 (confirm에 파일 이름)
list_bucket_connections 배포에 연결한 버킷과 넣는 환경 변수
connect_bucket 버킷 하나만 여는 S3 키를 배포의 <접두어>_BUCKET 등으로 넣기
disconnect_bucket 연결의 키를 폐기하고 변수 빼기 (confirm에 접두어)
list_storage_policies 파일 표(objects)·버킷 표(buckets)의 접근 규칙
create_storage_policy 콘솔의 틀(public-read, signed-in-read, own-folder …)이나 직접 쓴 규칙 만들기
remove_storage_policy 규칙 삭제 (confirm에 규칙 이름, 기본 규칙은 못 지워요)파일 표의 규칙은 run_sql로 만들 수 없어서 create_storage_policy를 써요. 조건식의 auth.uid()는 uid()로 바뀌어요.
production에 넣는 연결과 끊기는 소유자·관리자만, 나머지는 개발자 이상이 할 수 있어요. 무료 요금제에는 없어요.