웹에서 PDF 뷰어 연동하기(2): react-pdf

Jimin Lee·2022년 7월 21일
1

pdfjs

목록 보기
2/2

react-pdf를 사용하여 좀 더 쉽게 pdf viewer를 구현해보자.

react-pdf

(react-pdf/renderer와는 다른 라이브러리)

이전 포스트에서는 pdfjs-dist와 canvas를 사용해서 pdf 뷰어를 구현했다.
react-pdf에는 이미 pdfjs + canvas를 사용해서 구현이 되어있다..! 👍 손쉽게 pdf 뷰어 구현이 가능하다. 용량만 안컸어도 이걸 사용했을 것이다.......

살펴보기

https://github.com/wojtekmaj/react-pdf
공식 문서를 읽어보면 알겠지만 웬만한 건 구현되어 있다고 보면 된다.사용하기가 몹시 편하다.
Document, Page, Outline 3가지로 구성되며 Document는 전체 파일을 로드, Page는 각 페이지를 랜더링하는 역할을 한다.



설치

$ npm install react-pdf
$ yarn add react-pdf



구현

import하기

pdfjs-dist 때와 마찬가지로, react-pdf가 정상작동하기 위해선 PDF.js worker를 설정해줘야 한다.
자주 사용되는 bundler의 경우 entry file이 있어서 entry file을 사용하면 별도의 설정없이 import 가능하다.

1. webpack 혹은 parcel을 사용하는 경우

// webpack5를 사용할 경우
import { Document, Page } from "react-pdf/dist/esm/entry.webpack5";


다른 bundler 사용 시에도 마찬가지이다. 위의 entry file로 호출하면 된다.

2. CRA를 사용하는 경우

CRA4에서 webpack4를 사용하는 경우 1에서 처럼 entry file을 사용하면 된다.
하지만 CRA5에서 webpack5를 사용한다면.... JavaScript heap out of memory 에러가 발생한다. ㅠㅡㅠ

이 경우 npm run start 실행 시 변수를 추가해주거나 다른 방법을 사용해야 한다.

1) package.json에서 스크립트 변경
GENERATE_SOURCEMAP=false를 추가해준다.

 "start": "set \"GENERATE_SOURCEMAP=false\" && dotenv -e .env.development craco start",

2) workerSrc 선언

import { Document, Page, pdfjs } from "react-pdf";

// external CDN에서 호출
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;



page rendering

import React, { useRef, useState } from "react";
import { Document, Page, pdfjs } from "react-pdf";
import styles from "./style.module.scss";

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;

type PDFViewerProps = {
  path: string;
  scale: number;
};

const PDFViewer = ({ path, scale }: PDFViewerProps) => {
  const [numPages, setNumPages] = useState<number>(0);

  const onDocumentLoadSuccess = ({ numPages }: pdfjs.PDFDocumentProxy) => {
    setNumPages(numPages);
  };

  const onDocumentError = (error: Error) => {
    logger.error("pdf viewer error", error);
  };

  const onDocumentLocked = () => {
    logger.error("pdf locked");
  };

  return (
    <div className={styles.container}>
      <Document
        className={styles.doc}
        file={path}
        onLoadSuccess={onDocumentLoadSuccess}
        onLoadError={onDocumentError}
        onPassword={onDocumentLocked}
      >
        {Array.from(new Array(numPages), (_, index) => {
          return (
            <Page
              key={`page_${index + 1}`}
              className={styles.page}
              pageNumber={index + 1}
              width={700}
              renderAnnotationLayer={false}
              scale={scale}
            />
          );
        })}
      </Document>
    </div>
  );
};

export default PDFViewer;



참고

0개의 댓글