핵심 가이드

저장과 버전 관리

Inko의 저장 모델은 단순합니다 — 뷰어는 편집 결과를 canvasData 문자열로 내보내고, 저장소는 호스트 DB입니다. 호스트 백엔드가 인증된 작성자·문서 개정·버전 번호와 함께 새 레코드로 저장하면 시점별 편집 이력을 구성할 수 있습니다.

저장 흐름 — save()와 onSave

사용자가 뷰어의 저장 버튼을 누르거나 호스트 코드가 viewer.save()를 호출하면, 뷰어가 현재 편집 상태를 직렬화해(문자열 하나로 변환해) onSave(canvasData, ok, msg) 콜백으로 전달합니다. 이때 ok는 SDK 직렬화 성공만 뜻하며, 호스트 DB 저장 성공은 API 응답으로 확인해야 합니다.

저장 → 자체 DB 적재 js
var viewer = Inko.mount('#pdf-container', {
  src: '/pdfv/index.html',
  pdfUrl: '/files/contract.pdf',

  onSave: async function (canvasData, ok, msg) {
    if (!ok) { console.error('저장 실패:', msg); return; }

    // ok는 SDK 직렬화 성공. 호스트 저장 성공은 API 응답으로 별도 확인
    var response = await fetch('/api/annotations', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        documentId: 'contract-123',
        documentRevisionId: 'pdf-sha256-or-revision-id',
        baseVersion: 7,
        canvasData: canvasData
      })
    });
    if (!response.ok) throw new Error('호스트 저장 API 실패');
  }
});

// 뷰어 내장 저장 버튼 외에, 호스트 쪽 버튼·단축키에서도 트리거 가능
document.querySelector('#my-save-btn').onclick = function () {
  viewer.save();   // 응답은 위 onSave 콜백으로 전달
};
onSave 인자타입설명
canvasDatastring직렬화된 편집 데이터. 내용을 해석하지 말고 그대로 저장합니다.
okboolean직렬화 성공 여부.
msgstring실패 시 사유 메시지.
canvasData는 불투명(opaque) 문자열입니다

내부 형식은 SDK 버전에 따라 최적화될 수 있습니다. 파싱·가공하지 말고 형식 불일치를 줄이려면 받은 그대로 저장하고, 그대로 돌려주는 방식을 사용하세요. DB 컬럼은 길이 제한이 없는 TEXT(또는 동급) 타입을 권장합니다.

append-only 버전 테이블 설계

호스트 백엔드는 저장 요청을 인증하고 문서 권한을 확인한 뒤, 트랜잭션 안에서 버전 번호·부모 버전·해시·멱등키를 확정해 새 레코드로 저장해야 합니다.

버전 테이블 DDL 예시 sql
-- append-only 버전 테이블 예시 (PostgreSQL)
CREATE TABLE doc_annotations (
  id                    BIGSERIAL PRIMARY KEY,
  document_id           TEXT        NOT NULL,
  document_revision_id  TEXT        NOT NULL, -- 원본 PDF 개정 식별자/해시
  version_no            BIGINT      NOT NULL, -- 서버 트랜잭션에서 배정
  parent_version_id     BIGINT,
  principal_id          TEXT        NOT NULL, -- 인증 세션에서 서버가 확정
  canvas_data           TEXT        NOT NULL,
  canvas_sha256         CHAR(64)    NOT NULL,
  idempotency_key       UUID        NOT NULL,
  created_at            TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp(),
  UNIQUE (document_id, document_revision_id, version_no),
  UNIQUE (idempotency_key)
);

-- 조회는 "이 문서의 모든 버전" 또는 "최신 1건"
CREATE INDEX idx_doc_annotations_doc
  ON doc_annotations (document_id, document_revision_id, version_no DESC);

-- UPDATE·DELETE 차단, ACL, 보존·백업 정책은 호스트 DB 권한과 운영 규칙으로 적용합니다.

이 구조로 구성할 수 있는 것들:

  • 운영 이력 — 서버가 확인한 작성자·시각·편집 상태를 행 단위로 남깁니다. 위변조 방지 감사로그나 전자서명은 별도 설계가 필요합니다.
  • 시점 복원 — 저장 당시와 호환되는 SDK 버전에서 canvas_data를 다시 불러와 편집 상태를 복원합니다.
  • 버전 비교 화면 — 여러 버전을 레이어로 겹쳐 시각적으로 비교할 수 있습니다.

이어서 편집 — initialCanvasData

마운트 옵션 initialCanvasData에 저장해 둔 버전을 넘기면, 뷰어가 그 상태를 편집 캔버스에 복원한 채로 열립니다. 사용자는 중단한 지점부터 계속 작업합니다.

최신 버전부터 이어서 편집 js
// 1) 서버: 최신 버전 1건 조회
//    SELECT canvas_data FROM doc_annotations
//     WHERE document_id = 'contract-123'
//     ORDER BY version_no DESC LIMIT 1;

// 2) 클라이언트: 받은 값을 그대로 주입
Inko.mount('#pdf-container', {
  src: '/pdfv/index.html',
  pdfUrl: '/files/contract.pdf',
  initialCanvasData: latestCanvasData   // ← 그 시점부터 이어서 편집
});

// 특정 과거 버전부터 다시 작업하려면 그 버전의 canvas_data를 넘기면 됩니다.
// 이후 onSave 결과를 호스트 백엔드가 새 행으로 INSERT하고 UPDATE·DELETE를 제한해야
// 새 버전과 기존 이력이 보존됩니다.
문서 교체 시에도 동일합니다

loadPdfUrl(url, fileName, canvasData) · loadPdfBase64(base64, fileName, canvasData)의 세 번째 인자가 initialCanvasData와 같은 역할을 합니다.

변경 감지와 자동저장 — onChange · getLastCanvasData

편집이 발생할 때마다 onChange(canvasData)가 호출됩니다. SDK는 마지막 변경분을 내부에 캐시하므로, viewer.getLastCanvasData()로 언제든 최신 상태를 꺼내 자동저장에 활용할 수 있습니다.

임시 저장 · 주기적 자동저장 js
var viewer = Inko.mount('#pdf-container', {
  src: '/pdfv/index.html',
  pdfUrl: '/files/contract.pdf',
  onChange: function (canvasData) {
    // 편집이 발생할 때마다 호출 — 임시 저장에 활용
    sessionStorage.setItem('draft-123', canvasData);
  }
});

// 또는 주기적 자동저장: 마지막 변경분 캐시를 읽어 서버로
setInterval(function () {
  var draft = viewer.getLastCanvasData();
  if (draft) navigator.sendBeacon('/api/annotations/draft', draft);
}, 30000);

현재 페이지 편집 초기화 — clear()

viewer.clear()현재 보고 있는 페이지의 편집 캔버스를 비웁니다. 호스트 DB에 이미 저장된 과거 버전에는 영향을 주지 않습니다. 단, 실제 보존 여부는 호스트 DB 권한·삭제 제한·백업 정책에 따릅니다.