소개
Inko SDK 개요
Inko는 웹 앱에 PDF뷰어와 PDF 마크업 기능을 더하는 무료 오픈소스 self-hosted PDF SDK입니다. 문서 열람·검색부터 펜·형광펜·텍스트·도형 마크업, 편집 상태 반환·복원과 검토본 레이어까지 연결합니다. 저장·인증·권한·버전 정책은 호스트 앱이 관리합니다.
- PDF뷰어 — 문서를 열고 확대·축소·페이지 이동으로 살펴봅니다.
- PDF 마크업 기능 — 펜·형광펜·텍스트·도형으로 문서 위에 검토 의견을 남깁니다.
- 편집 상태 반환·복원 — 전체 편집 상태를
canvasData로 반환하고 다시 주입합니다. - 복수 검토자 레이어 — 저장된 여러 편집본을 한 화면에 겹쳐 보고 개별 토글합니다.
- 이어서 편집 — 선택한 저장 시점을 편집 캔버스로 불러와 작업을 계속합니다.
- PDF 원문 사용 — Text Layer가 있는 PDF에서
contentSelect로 텍스트를 선택·복사하고, 가상화된 전체 페이지를 Unicode 리터럴로 검색합니다. - PDF 내장 목차 — outline이 있는 문서는 중첩 책갈피를 표시하고 해당 페이지로 이동합니다.
- 네이티브 AcroForm — 지원하는 양식 필드를 표시·입력하고, 현재 값을 별도 PDF 바이트로 내보냅니다.
이 문서는 Inko를 직접 빌드·배포하는 개발자를 위한 통합 가이드와 API 레퍼런스를 제공합니다.
소스 코드는 GitHub, 배포 패키지는 npm에서 확인할 수 있습니다. 사용·수정·재배포 조건은 저장소의 Apache-2.0 LICENSE가 정합니다.
Inko의 소스·문서·릴리스는 있는 그대로 제공됩니다. 설치·연동·환경 검증·업데이트·보안 패치 적용·포크 유지보수는 이용자가 담당하며, NextH는 개별 기술지원·SLA·LTS를 제공하지 않으며, 호환성이나 운영 결과를 보증하지 않습니다. 공개 저장소가 생기더라도 이슈와 기여 제안의 응답·검토·수락·해결 또는 기한을 약속하지 않습니다.
동작 구조
Inko는 뷰어 본체(정적 빌드 산출물)와 SDK 래퍼 두 부분으로 구성됩니다.
npm 패키지는 래퍼를 sdk/inko-sdk.js로 제공하며, NextH의 self-hosted 데모는 같은 공개 API 번들을
기존 산출물 이름인 /pdfv/sdk/pdfv-sdk.js로 제공합니다. 두 파일 모두 브라우저 전역에는 window.Inko만 등록합니다.
뷰어 본체를 이용자 서버의 /pdfv/ 경로에 배포하면, SDK가 해당 뷰어를 iframe으로 마운트하고(지정한 영역에 뷰어 화면을 생성해 붙이고), postMessage(브라우저 내장 창↔iframe 메시지 통신 기능)로 양방향 통신합니다.
- 배포본 통합 시 호스트 빌드 의존성 없음 — 사전 빌드된 릴리스는 호스트 앱의 npm 설치·번들러 설정 없이
<script>로 불러옵니다. 소스 빌드에는 Node.js와 npm이 필요합니다. - 통합 패턴 제공 — JSP·React·Vue·Angular·PHP 등 주요 웹 스택의 예제를 제공합니다.
- origin 검증 내장 — SDK와 뷰어 간 메시지는 출처(origin·source)를 검증한 뒤에만 처리됩니다.
<div id="pdf-container" style="width:100%;height:80vh"></div>
<!-- NextH self-hosted 데모의 실제 번들 경로. npm 패키지는 sdk/inko-sdk.js를 제공합니다. -->
<script src="/pdfv/sdk/pdfv-sdk.js"></script>
<script>
var viewer = Inko.mount('#pdf-container', {
src: '/pdfv/index.html',
pdfUrl: '/files/contract.pdf',
onSave: function (canvasData, ok) {
if (!ok) return;
// 호스트 API가 새 레코드로 저장하면 '버전 1개'가 됩니다.
}
});
</script>핵심 개념
canvasData — 편집 데이터의 단위
사용자가 PDF 위에 남긴 마크업(펜·형광펜·텍스트·도형)은 canvasData라는 직렬화된 문자열 하나(편집 내용 전체를 저장·전송하기 쉽게 텍스트로 변환한 것)로 표현됩니다.
원본 PDF는 변경되지 않으며,
편집 내용은 PDF와 분리된 레이어로 관리됩니다.
SDK는 canvasData를 호스트 저장소에 영속 저장하지 않습니다. onSave 콜백으로 받은 값을 호스트 앱의 DB에 그대로 저장하고,
다시 보여줄 때 그대로 전달하면 됩니다. SDK 번들에는 내장 외부 전송 엔드포인트가 없으며,
실제 데이터 경로는 이용자가 지정한 PDF URL·호스트 API·배포 구성에 따라 결정됩니다.
PDF 바이트 — 네이티브 양식 값의 별도 내보내기
exportPdf()는 지원하는 네이티브 AcroForm의 현재 값을 반영한 Promise<ArrayBuffer>를 반환합니다. 이 PDF 바이트에는 Inko의 펜·형광펜·텍스트·도형 canvasData가 합성되지 않습니다. 다시 편집할 드로잉과 양식 값이 반영된 PDF가 모두 필요하면
호스트 앱이 canvasData와 PDF 바이트를 각각 저장해야 합니다.
텍스트 선택·복사와 검색은 PDF.js Text Layer가 만들어지는 원문 텍스트를 대상으로 하며 OCR을 제공하지 않습니다. 책갈피는 PDF에 들어 있는 outline을 읽는 탐색 UI로, 생성·편집 기능이 아닙니다. 공개 fixture에서는 텍스트 필드·체크박스·선택 필드의 AcroForm 왕복을 검증했지만 모든 AcroForm 유형이나 XFA를 보장하지 않으므로 대상 PDF군에서 직접 확인해야 합니다.
호스트 버전 — append-only로 쌓는 이력
저장할 때마다 받은 canvasData를 호스트 서버가 새 행(row)으로 INSERT하면 버전 이력을 구성할 수 있습니다.
UPDATE·DELETE 제한, 작성자 검증, 권한, 백업과 보존 정책은 호스트 백엔드가 적용하며,
특정 버전을 initialCanvasData로 다시 주입하면 그 시점부터 이어서 편집할 수 있습니다.
자세한 설계 방법은 저장과 버전 관리를 참고하세요.
레이어 — 사용자별 작업의 겹쳐 보기
여러 사용자(또는 여러 버전)의 canvasData를 loadUserCanvasOverlay()로 주입하면,
뷰어 우측 이력 패널에 목록이 나타나고 각 항목을 켜고 끄며 겹쳐 볼 수 있습니다.
계약 검토·도면 회람처럼 여러 명의 흔적을 비교해야 하는 업무에 사용합니다.
자세한 내용은 다중 사용자 레이어를 참고하세요.
통합 가이드 제공 환경
| 환경 | 통합 방식 | 가이드 |
|---|---|---|
| JavaScript | <script> 태그 + Inko.mount() | 바로가기 |
| React · Next.js | useEffect + ref로 마운트 | 바로가기 |
| Vue · Nuxt | onMounted에서 마운트 | 바로가기 |
| Angular | AfterViewInit에서 마운트 | 바로가기 |
| Java · Spring (JSP·Thymeleaf) | 서버 렌더 페이지에 스크립트 한 줄 | 바로가기 |
| PHP · Laravel | 서버 렌더 페이지에 스크립트 한 줄 | 바로가기 |
| ASP.NET · Classic ASP | Razor·ASP 뷰에 스크립트 한 줄 | 바로가기 |
사용 중인 기술 스택의 가이드를 선택하면 마운트 코드부터 저장 엔드포인트까지 전체 예제를 볼 수 있습니다.
문서 구성
| 문서 | 내용 |
|---|---|
| 시작하기 | 뷰어 배포부터 첫 마운트·저장 API 연결까지 퀵스타트 |
| PDF 불러오기 | URL·Base64 로드, 읽기 전용, 런타임 문서 교체 |
| 저장과 버전 관리 | canvasData 저장 흐름, append-only 버전 테이블 설계, 이어서 편집 |
| 다중 사용자 레이어 | 여러 사용자 작업 겹쳐 보기, 버전 이력 패널 |
| 커스터마이징 | 브랜드 컬러·로고·도구 구성·검색·책갈피 기능 스위치·다국어 |
| 플랫폼별 통합 (7종) | JavaScript·React·Vue·Angular·Spring(JSP)·PHP·ASP.NET — iframe·postMessage 기반 예제와 저장 엔드포인트 |
| API 레퍼런스 | mount 옵션·콜백·exportPdf()·메시지 타입과 PDF 원문 기능 범위 |
| FAQ · 트러블슈팅 | 임베드 차단·CORS 등 자주 묻는 질문 |