플랫폼별 통합

Angular

Angular에서는 ViewChild로 컨테이너를 잡고 ngAfterViewInit에서 마운트, ngOnDestroy에서 정리합니다.

공통 전제

뷰어 산출물이 /pdfv/ 경로에 배포되어 있어야 합니다 — 시작하기 참고. SDK는 src/index.html<script src="/pdfv/sdk/pdfv-sdk.js">로 로드하고, 개발 중에는 proxy.conf.json으로 /pdfv를 운영 서버에 프록시하세요.

컴포넌트 예제

pdf-editor.component.ts ts
import {
  Component, ElementRef, ViewChild,
  AfterViewInit, OnDestroy, Input,
} from '@angular/core';

// 전역 SDK 선언 (src/typings.d.ts 등에 두어도 됩니다)
declare const Inko: any;

@Component({
  selector: 'app-pdf-editor',
  standalone: true,
  template: `<div #container style="width:100%; height:80vh"></div>`,
})
export class PdfEditorComponent implements AfterViewInit, OnDestroy {
  @Input() docId!: number;
  @Input() pdfUrl!: string;
  @Input() initialCanvasData?: string;

  @ViewChild('container', { static: true })
  container!: ElementRef<HTMLDivElement>;

  private viewer: any;

  ngAfterViewInit(): void {
    this.viewer = Inko.mount(this.container.nativeElement, {
      src: '/pdfv/index.html',
      pdfUrl: this.pdfUrl,
      initialCanvasData: this.initialCanvasData,
      onSave: (canvasData: string, ok: boolean) => {
        if (!ok) return;
        fetch('/api/annotations', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ docId: this.docId, canvasData }),
        });
      },
    });
  }

  // 외부 버튼에서 호출할 수 있게 노출
  save(): void {
    this.viewer?.save();
  }

  ngOnDestroy(): void {
    this.viewer?.destroy();
  }
}
  • declare const Inko: any; 선언으로 전역 SDK를 타입 오류 없이 사용합니다. 프로젝트 공용 typings.d.ts에 두면 모든 컴포넌트에서 재사용됩니다.
  • standalone: true는 Angular 14+ 기준이며, NgModule 방식이라면 선언만 모듈로 옮기면 됩니다.

HttpClient와 Zone

예제의 fetch는 Zone과 무관하게 동작합니다. Angular의 HttpClient를 쓰고 콜백 결과로 화면 상태를 갱신한다면, SDK 콜백이 Angular Zone 밖에서 호출될 수 있으므로 NgZone.run()으로 감싸 변경 감지를 보장하세요.

HttpClient 사용 시 ts
// Angular 스타일로 HttpClient를 쓰려면 — NgZone 밖 콜백에서 재진입
import { HttpClient } from '@angular/common/http';
import { NgZone } from '@angular/core';

constructor(private http: HttpClient, private zone: NgZone) {}

// onSave 콜백 안에서:
onSave: (canvasData: string, ok: boolean) => {
  if (!ok) return;
  // SDK 콜백은 Angular Zone 밖에서 올 수 있으므로 zone.run으로 감쌉니다
  this.zone.run(() => {
    this.http.post('/api/annotations', {
      docId: this.docId,
      canvasData,
    }).subscribe();
  });
}

주의사항

  • destroy() 필수ngOnDestroy에서 호출하지 않으면 라우팅마다 iframe·리스너가 누적됩니다.
  • SSR(Angular Universal) — 서버 렌더 단계에는 window가 없으므로 브라우저에서만 실행되도록 isPlatformBrowser 가드를 두세요.
  • 문서 교체@Input 변경으로 재마운트하는 대신 this.viewer.loadPdfUrl()을 호출하면 인스턴스를 유지한 채 문서만 바뀝니다.