reopt design
DocsExploreTemplatesCanvasToolsPricing
로그인
시작하기
개요
설치와 첫 임베드
문서 모델과 편집
AI 생성과 변경 제안
저장·자산·공유
발표와 파일 출력
API·문제 해결
Deck Studio
Oopt-deck
reopt designreopt design

AI 시대를 위한 디자인 시스템

  • 문서
  • 가격
  • 릴리즈 노트
  • 소개
  • 문의
  • 서비스 약관
  • 개인정보처리방침

주식회사 리옵트사업자등록번호 217-88-02453contact@reopt.ai

© 2026 reopt Inc. All rights reserved.

시작하기
  1. 문서
  2. /
  3. 시작하기
  4. /
  5. opt-deck 저장·자산·공유 연동

저장·자산·공유 연동

호스트가 자동 저장, 충돌 감지, 복구, 자산 업로드와 읽기 전용 공유를 구현하는 기준입니다.

reopt design · 업데이트 2026년 11월 1일

opt-deck설치와 첫 임베드문서 모델과 편집AI 생성과 변경 제안저장·자산·공유 연동발표와 파일 출력API 레퍼런스와 문제 해결
Deck Studio에서 바로 편집하기 →디자인 컬렉션 보기

패키지와 호스트의 경계

opt-deck은 문서 검증·편집·발표·출력을 소유합니다. 인증, 서버 저장, 자산 접근 권한, AI 모델 호출과 사용량 정책은 소비 앱에서 연결합니다. 아래의 /api/presentation-* 주소는 직접 구현해야 하는 호스트 예제입니다.

1. 패키지와 앱의 책임

onChange는 검증된 다음 문서를 전달하며 서버 저장을 수행하지 않습니다. status는 호스트가 전달하는 표시 문구입니다. 실제 저장 응답을 받기 전에는 저장 완료로 표시하지 마세요.

이 저장소의 Builder 어댑터는 EAV 저장·스냅샷·복구·공유를 구현하지만 npm 패키지에 백엔드가 포함되는 것은 아닙니다. 소비 앱은 데이터베이스나 파일 저장소를 자유롭게 선택할 수 있습니다.

2. 읽기와 마이그레이션

외부 파일과 서버 응답은 unknown으로 받고 파싱합니다. 이전 v1 자료를 허용하는 경로는 migrateDeckDocument를, 현재 v2 계약만 받는 API는 parseDeckDocument를 사용합니다.

열기에 실패했을 때 기존 문서나 로컬 복구본을 새 빈 문서로 덮어쓰지 마세요. 권한 오류, 파싱 오류, 자산 접근 실패를 구분해 재시도·다른 파일 선택·복구 선택을 제공합니다.

parse-proposal.ts
import {
  migrateDeckDocument, parseDeckDocument,
} from "@reopt-ai/opt-deck/server";

export function openImportedJson(text: string) {
  const input: unknown = JSON.parse(text);
  // Accept legacy v1 and current v2. Throws on invalid content.
  return migrateDeckDocument(input);
}

export function openCurrentServerRecord(payload: unknown) {
  // Current v2 only. Use this at a host API boundary.
  return parseDeckDocument(payload);
}

3. 자동 저장과 서버 버전

document.revision은 편집 이력용 카운터입니다. 서버 동시성 검사는 별도의 serverVersion과 compare-and-swap으로 처리하세요. 저장 요청은 직렬화하고, 저장 중 새 편집이 들어오면 최신 스냅샷을 다음 요청으로 보냅니다.

409 충돌은 자동 덮어쓰기 대신 최신 서버 자료와 로컬 초안의 조정을 요구해야 합니다. 아래 함수는 저장 요청 한 번의 계약만 보여 줍니다. debounce·직렬 큐·재시도·계정 전환 처리는 소비 앱에서 구성합니다.

save-presentation.ts
import type { DeckDocument } from "@reopt-ai/opt-deck/server";

export type StoredDeck = { document: DeckDocument; serverVersion: number };

// Host-defined endpoint and payload; not a built-in opt-deck API.
export async function saveSnapshot(
  id: string, document: DeckDocument, serverVersion: number,
  signal: AbortSignal,
): Promise<number> {
  const response = await fetch("/api/presentations/" + encodeURIComponent(id), {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ document, expectedVersion: serverVersion }),
    signal,
  });
  if (response.status === 409) throw new Error("Reload or reconcile the conflicting version");
  if (!response.ok) throw new Error("Save failed; retain the local draft");
  const result: unknown = await response.json();
  if (!result || typeof result !== "object" || !("serverVersion" in result)
      || !Number.isSafeInteger(result.serverVersion)) {
    throw new Error("Invalid save response");
  }
  return result.serverVersion as number;
}

4. 자산 업로드 계약

onAssetUpload는 File과 AbortSignal을 받고 DeckAsset을 반환합니다. 필수 필드는 id·type·name·src·mimeType·bytes·embeddable입니다. type은 image/font/video/audio/vector이며, 글꼴에는 family·weight·style·embedding 정보도 사용됩니다.

문서의 src는 편집·발표·출력 시 다시 접근할 수 있어야 합니다. 만료된 서명 URL을 영구 자산 주소처럼 저장하지 마세요. 업로드 취소와 문서 전환 뒤에는 완료 응답을 이전 문서에 적용하지 않습니다. 콜백이 없으면 로컬 자산을 문서에 포함합니다.

upload-asset.ts
import type { DeckEditorProps } from "@reopt-ai/opt-deck";
import { assetSchema } from "@reopt-ai/opt-deck/server";

export const uploadAsset: NonNullable<DeckEditorProps["onAssetUpload"]> =
  async (file, signal) => {
    const body = new FormData();
    body.set("file", file);
    // The host validates ownership, media type and file size.
    const response = await fetch("/api/presentation-assets", {
      method: "POST", body, signal,
    });
    if (!response.ok) throw new Error("Asset upload failed");
    return assetSchema.parse(await response.json());
  };

5. 복구와 사용자 전환

복구 키에는 계정·프로젝트·문서 ID를 포함하고 원본 serverVersion을 함께 기록합니다. 복구본이 서버보다 오래되었거나 서로 수정된 경우 사용자 선택 전에 자동 저장을 시작하지 않습니다.

로그아웃·계정 변경·다른 프로젝트 열기에서는 요청을 취소하고 늦은 응답을 무시하세요. 문서별 key로 편집기를 다시 마운트하면 선택·카메라·history가 이전 문서에서 넘어오는 것을 방지할 수 있습니다.

6. 공유와 권한

onShare(document)는 호스트 공유 UI를 여는 연결점입니다. 링크 생성·취소·만료·소유권 확인은 서버가 처리하고, 공유 화면에서는 DeckViewer를 사용합니다. controls=false는 화면 설정이며 권한 검증을 대신하지 않습니다.

읽기 전용 공유에서도 자산 URL의 접근 범위를 확인해야 합니다. 비공개 자료를 공유할 때 원본 편집 API나 저장 자격 증명을 클라이언트에 노출하지 않습니다. 고객별 파생 자료는 별도 문서 ID와 저장 권한을 부여합니다.

PreviousAI 생성과 변경 제안모델 호출, 제안 파싱, 선택 범위 검증, 검토·취소·충돌 처리시작하기
AI 생성과 변경 제안 페이지로 이동
Next발표와 파일 출력발표자 화면, 모션·미디어와 PNG·PDF·PPTX·MP4·portable 출력 범위시작하기