Storage JS SDK
Storage JS SDK는 사용자 계정 root / 기준으로 파일을 업로드, 조회, 다운로드, 삭제한다.
현재 배포 버전은 0.1.3이다.
설치
npm install @spectra-platform/storage-sdk
API tree
Storage JS SDK
├─ Client setup
│ ├─ new SpectraStorageClient(config)
│ └─ createSpectraStorageClient(config)
└─ Files
├─ listFiles(options?)
├─ uploadFile(input)
├─ uploadImage(input)
├─ uploadFile(fileOrBlob, options) # legacy compatible
├─ uploadImage(file, options?) # legacy compatible
├─ getDownloadUrl(path)
├─ downloadBlob(path)
└─ deleteFile(path)
Auth 객체와 함께 사용
Storage SDK는 Auth SDK의 access token provider를 사용한다. SDK 내부에서 auth.getAccessToken({ service: "storage" })를 호출하므로 기본 Storage SDK 설정은 Storage secret이나 Secret Key를 요구하지 않는다.
import { SpectraAuthClient } from "@spectra-platform/auth-sdk";
import { SpectraStorageClient } from "@spectra-platform/storage-sdk";
const auth = new SpectraAuthClient({
projectId: "proj_...",
// Current Auth SDK compatibility field. It is not a primary product key.
publicClientId: "app_...",
environment: "test",
redirectUri: "https://myapp.example.com/auth/callback",
});
const storage = new SpectraStorageClient({
projectId: "proj_...",
auth,
});
업로드 직전에 문제가 생기면 Auth session과 Storage service token을 한 번만 분리해서 확인한다.
일반 앱 코드에서 매 업로드마다 forceRefresh: true를 선행 호출하지 않는다. Storage SDK가 필요한
service token 발급과 401/403 재시도를 내부에서 처리한다.
const session = await auth.getSession();
const storageToken = await auth.getAccessToken({
service: "storage",
});
console.log(Boolean(session), Boolean(storageToken));
session이 없으면 소비 앱의 Auth callback/sessionStore 문제다. session은 있는데 APP_SESSION_UNAUTHORIZED가
나오면 SDK error의 requestId를 Platform CS에 전달한다. Platform은 Auth API audit denial_reason으로
service-token 발급 거절 원인을 좁힌다.
forceRefresh: true는 Platform CS가 명시적으로 요청한 단발성 진단에서만 사용하고, 업로드 루프나 파일 선택 이벤트에서 반복 호출하지 않는다.
API detail
new SpectraStorageClient(config)
Storage client를 만든다.
projectId: Console Project IDauth:getAccessToken({ service: "storage" })을 제공하는 Auth 객체baseUrl: 선택 사항. 기본값은https://storage.spectra.krfetch: 선택 사항. 테스트 또는 특수 runtime에서 주입한다.crypto: 선택 사항. 자동 checksum과 idempotency key 생성을 위해 Web Crypto를 사용한다.
createSpectraStorageClient(config)
new SpectraStorageClient(config)와 같은 결과를 반환하는 factory helper다.
listFiles(options?)
user-root prefix 기준으로 파일과 하위 prefix를 조회한다.
const listed = await storage.listFiles({
prefix: "/community/reviews/",
limit: 50,
});
console.log(listed.files, listed.prefixes, listed.nextCursor);
주요 입력:
prefix:/로 시작하는 user-root prefixcursor: 다음 페이지 cursorlimit: 페이지 크기
uploadFile(input)
일반 파일, 이미지, 영상 Blob을 업로드한다. 권장 public API는 객체형 입력이다. SDK는 먼저 upload intent를 만들고 signed URL로 bytes를 올린 뒤 complete 요청을 보낸다.
const object = await storage.uploadFile({
file,
path: "/community/reviews/photo.jpg",
visibility: "private",
context: "community",
fileInfo: {
originalName: file.name,
fingerprint: `${file.name}|${file.size}|${file.type}|${file.lastModified}`,
lastModified: file.lastModified,
},
onProgress: ({ loaded, total }) => {
console.log(loaded, total);
},
});
주요 객체형 입력:
file: browserFile또는Blobpath:/로 시작하고 파일명으로 끝나는 user-root object keyvisibility: 선택 사항.private또는public_read; 기본값은privatecontentType: 선택 사항. 없으면 Blob type 또는application/octet-streamcontext: 선택 사항. 예:community,chat,reviewfileInfo.originalName: 선택 사항. 한글 파일명 같은 non-ASCII 값을 넣어도 된다.fileInfo.fingerprint: 선택 사항. 소비 앱이 중복 업로드나 디버깅에 쓰는 문자열fileInfo.lastModified: 선택 사항.File.lastModified같은 epoch millisecondsmetadata: advanced 선택 사항. key는 소문자 영문·숫자·.·_·-만 허용한다.checksumSha256: 선택 사항. 없으면 SDK가 Web Crypto로 계산한다.onProgress: fetch 업로드 특성상 bytes 단위 progress가 아니라 업로드 전/후 신호로 동작한다.
객체형 입력의 context/fileInfo는 SDK가 safe metadata key로 바꿔 서버에 보낸다.
{
"context": "community",
"original_file_name": "한글파일명.png",
"file_fingerprint": "한글파일명.png|12345|image/png|1786...",
"last_modified": "1786..."
}
Storage API는 이 logical metadata를 원문으로 저장한다. 단, signed PUT에 필요한
x-amz-meta-user-* header value는 Storage API가 브라우저-safe ASCII 값으로 인코딩해서 내려준다.
소비 앱이 직접 S3/MinIO metadata header를 만들면 안 된다.
uploadImage(input)
이미지 전용 helper다. image/* Blob만 허용한다.
const image = await storage.uploadImage({
file,
directory: "/reviews/",
visibility: "private",
context: "review",
fileInfo: {
originalName: file.name,
lastModified: file.lastModified,
},
});
path와 directory는 동시에 넣을 수 없다.
visibility: "public_read"는 읽기 URL을 가진 사람이 object를 읽을 수 있다는 뜻이다. 쓰기, 덮어쓰기, 삭제, quota, audit, moderation은 여전히 Storage 정책을 따른다. Bucket ACL, CDN, signed PUT header 같은 내부 설정은 기본 앱 코드에서 직접 다루지 않는다.
getDownloadUrl(path)
임시 download URL을 발급받는다.
const url = await storage.getDownloadUrl(object.objectKey);
window.open(url, "_blank", "noopener,noreferrer");
downloadBlob(path)
download URL을 발급받아 Blob으로 내려받는다.
const blob = await storage.downloadBlob(object.objectKey);
deleteFile(path)
user-root 파일을 삭제한다.
await storage.deleteFile(object.objectKey);
Chat, 커뮤니티, 리뷰 첨부
Storage SDK는 파일의 binary 저장을 맡고, Chat 또는 앱 Backend는 object reference만 저장한다.
const image = await storage.uploadImage({
file,
directory: "/community/reviews/",
visibility: "private",
context: "community",
fileInfo: {
originalName: file.name,
lastModified: file.lastModified,
},
});
await chat.sendMessage(room.id, {
text: "사진 첨부",
attachments: [
{
objectKey: image.objectKey,
contentType: image.contentType,
byteSize: image.byteSize,
checksumSha256: image.checksumSha256,
},
],
});
주의
Storage SDK는 app-user token으로 내 파일 작업을 수행한다. 서버 관리자 권한이 필요한 bucket 운영, quota 정책 변경, audit export는 browser SDK 범위가 아니다. 그런 작업은 서버에 보관한 환경(test/live)에 묶인 Project ID + Secret Key로 Project를 확인하고 Storage service toggle이 켜져 있을 때 수행한다.