본문으로 건너뛰기

스토리지 (Storage)

파일 업로드 및 관리 API입니다. 모든 메서드는 storageId (stg_xxx 형식, 콘솔에서 발급)를 받습니다.

💡 Connect Base의 파일 업로드는 Presigned URL 방식입니다. SDK가 내부적으로 ① presigned URL 발급 → ② Object Storage에 직접 PUT → ③ 완료 알림 의 3단계를 자동으로 처리합니다.

⚠️ 아래 메서드가 어떤 파일을 보고 지울 수 있는지는 스토리지의 접근 수준이 정합니다. 콘솔에서 새로 만든 스토리지는 private 이라 로그인하지 않으면 목록 조회와 업로드가 401 입니다.

파일 업로드

기본 업로드

html
<input type="file" id="avatar" />
typescript
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 로 전달합니다.

typescript
const folder = await cb.storage.createFolder('stg_xxx', { name: 'avatars' })
const result = await cb.storage.uploadFile('stg_xxx', file, folder.id)

여러 파일 업로드

typescript
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이 필요할 때 사용합니다.

typescript
const result = await cb.storage.uploadByPath(
  'stg_xxx',
  '/profiles/user123/avatar.png',
  file
)
console.log(result.url) // 다시 업로드해도 동일한 URL

파일 조회

목록

typescript
const files = await cb.storage.getFiles('stg_xxx')
files.forEach((f) => console.log(f.name, f.url, f.size))

경로로 조회

typescript
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')

파일 삭제 / 이동 / 이름 변경

typescript
// 삭제
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' })

헬퍼 메서드

typescript
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 로 실패해 갤러리가 빈 채로 남습니다.

typescript
// 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언제
401private 스토리지에 로그인하지 않고 목록 조회나 업로드
403다른 멤버가 올린 파일을 삭제하거나 덮어쓰기. public_read / private 에서는 업로더 기록이 없는 파일도 해당
404private 스토리지에서 자기에게 보이지 않는 파일 ID 로 조회하거나 삭제

moveFilerenameFile 은 퍼블릭 키 경로가 없어 콘솔(JWT) 전용이며, 접근 수준의 영향을 받지 않습니다.

페이지 메타 (정적 호스팅 SEO)

웹 스토리지에 배포된 페이지마다 OG 태그 / JSON-LD 구조화 데이터를 설정할 수 있습니다.

typescript
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')

응답 타입

typescript
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
}