스토리지 (Storage)
파일 업로드 및 관리 API입니다. 모든 메서드는 storageId (stg_xxx 형식, 콘솔에서 발급)를 받습니다.
💡 Connect Base의 파일 업로드는 Presigned URL 방식입니다. SDK가 내부적으로 ① presigned URL 발급 → ② Object Storage에 직접 PUT → ③ 완료 알림 의 3단계를 자동으로 처리합니다.
⚠️ 아래 메서드가 어떤 파일을 보고 지울 수 있는지는 스토리지의 접근 수준이 정합니다. 콘솔에서 새로 만든 스토리지는
private이라 로그인하지 않으면 목록 조회와 업로드가 401 입니다.
파일 업로드
기본 업로드
<input type="file" id="avatar" />const input = document.getElementById('avatar') as HTMLInputElement
const file = input.files?.[0]
if (!file) throw new Error('파일을 선택해주세요')
// cb.storage.uploadFile(storageId, file, parentId?)
const result = await cb.storage.uploadFile('stg_xxx', file)
console.log(result.url, result.id, result.size)폴더 안에 업로드
먼저 createFolder 로 폴더를 만들고, 반환된 폴더 ID를 parentId 로 전달합니다.
const folder = await cb.storage.createFolder('stg_xxx', { name: 'avatars' })
const result = await cb.storage.uploadFile('stg_xxx', file, folder.id)여러 파일 업로드
const input = document.getElementById('files') as HTMLInputElement
const files = Array.from(input.files ?? [])
const results = await cb.storage.uploadFiles('stg_xxx', files)
results.forEach((r) => console.log(r.url))경로 기반 업로드 (덮어쓰기)
같은 경로에 다시 업로드하면 파일만 교체되어 URL이 유지됩니다. 프로필 이미지처럼 고정 URL이 필요할 때 사용합니다.
const result = await cb.storage.uploadByPath(
'stg_xxx',
'/profiles/user123/avatar.png',
file
)
console.log(result.url) // 다시 업로드해도 동일한 URL파일 조회
목록
const files = await cb.storage.getFiles('stg_xxx')
files.forEach((f) => console.log(f.name, f.url, f.size))경로로 조회
const file = await cb.storage.getByPath('stg_xxx', '/profiles/user123/avatar.png')
console.log(file.url)
// URL만 필요하면 (없으면 null)
const url = await cb.storage.getUrlByPath('stg_xxx', '/profiles/user123/avatar.png')파일 삭제 / 이동 / 이름 변경
// 삭제
await cb.storage.deleteFile('stg_xxx', 'file_123')
// 이동 (다른 폴더로) — 루트로 이동하려면 new_parent_id 생략
await cb.storage.moveFile('stg_xxx', 'file_123', { new_parent_id: 'folder_456' })
// 이름 변경
await cb.storage.renameFile('stg_xxx', 'file_123', { name: 'new-name.png' })헬퍼 메서드
const file = (await cb.storage.getFiles('stg_xxx'))[0]
cb.storage.getFileUrl(file) // file.url 반환 (없으면 null)
cb.storage.isImageFile(file) // mime_type 으로 이미지 여부 판단접근 수준 (access_level)
퍼블릭 키(cb_pk_)는 브라우저 번들에 그대로 실려 나가는 공개 식별자라 자격증명이 아닙니다. 그래서 파일 스토리지는 업로드한 파일에 업로더를 기록하고 그 귀속으로 인가합니다. 접근 수준은 그 강도를 스토리지 단위로 정하며, 콘솔 → 스토리지 → 파일 스토리지 → 보안 설정에서 바꿉니다.
| 접근 수준 | 목록 조회 | 업로드 | 삭제 / 덮어쓰기 |
|---|---|---|---|
shared | 제한 없음 | 로그인 없이 가능 | 로그인한 멤버가 올린 파일은 그 멤버만. 업로더 기록이 없는 파일은 누구나 |
public_read | 제한 없음 | 로그인 없이 가능 | 올린 본인만. 기록이 없는 파일은 콘솔이나 Secret Key 로만 |
private | 자기가 올린 파일만 (익명은 401) | 멤버 토큰 필수 | 올린 본인만 |
- 기존 스토리지는
shared라 동작이 바뀌지 않습니다. 새로 만드는 스토리지는private입니다. - 로그인하면(
cb.auth.signIn()) SDK 가 멤버 토큰을 자동으로 붙이고, 그때 올린 파일에만 업로더가 기록됩니다. - 콘솔과 Secret Key(
cb_sk_) 요청은 접근 수준과 관계없이 항상 전체 파일에 접근합니다.
공개 갤러리를 만들 때
로그인 없이 목록을 보여 주는 화면은 public_read 를 쓰세요. private 에서는 아래 코드가 401 로 실패해 갤러리가 빈 채로 남습니다.
// public_read 에서만 동작 — private 이면 401 UNAUTHORIZED
const files = await cb.storage.getFiles('stg_xxx')
const urls = files
.filter((f) => cb.storage.isImageFile(f))
.map((f) => cb.storage.getFileUrl(f))실패 응답
| HTTP | 언제 |
|---|---|
| 401 | private 스토리지에 로그인하지 않고 목록 조회나 업로드 |
| 403 | 다른 멤버가 올린 파일을 삭제하거나 덮어쓰기. public_read / private 에서는 업로더 기록이 없는 파일도 해당 |
| 404 | private 스토리지에서 자기에게 보이지 않는 파일 ID 로 조회하거나 삭제 |
moveFile과renameFile은 퍼블릭 키 경로가 없어 콘솔(JWT) 전용이며, 접근 수준의 영향을 받지 않습니다.
페이지 메타 (정적 호스팅 SEO)
웹 스토리지에 배포된 페이지마다 OG 태그 / JSON-LD 구조화 데이터를 설정할 수 있습니다.
await cb.storage.setPageMeta('web_storage_id', {
path: '/products/123',
title: '최신 스마트폰',
description: '최고의 성능, 최저가 보장',
image: 'https://example.com/product.jpg',
og_type: 'product',
json_ld: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Product',
name: '최신 스마트폰'
})
})
// 일괄 설정 (최대 100개)
await cb.storage.batchSetPageMeta('web_storage_id', {
pages: [
{ path: '/products/1', title: '상품 1', description: '설명 1' },
{ path: '/products/2', title: '상품 2', description: '설명 2' }
]
})
// 조회 / 삭제
const meta = await cb.storage.getPageMeta('web_storage_id', '/products/123')
const list = await cb.storage.listPageMetas('web_storage_id', { limit: 20, offset: 0 })
await cb.storage.deletePageMeta('web_storage_id', '/products/123')
await cb.storage.deleteAllPageMetas('web_storage_id')응답 타입
interface UploadFileResponse {
id: string
name: string
path: string
type: string // 'file' | 'folder'
mime_type: string
size: number
url: string
parent_id?: string
created_at: string
}