Daily Front_Minhhk

next.js 에서 react-pdf 적용 error 본문

에러

next.js 에서 react-pdf 적용 error

Minhhk 2023. 7. 27. 00:34

npm i -D @types/react-pdf

 

react-pdf

Display PDFs in your React app as easily as if they were images.. Latest version: 7.2.0, last published: 5 days ago. Start using react-pdf in your project by running `npm i react-pdf`. There are 632 other projects in the npm registry using react-pdf.

www.npmjs.com

 

 

./node_modules/canvas/build/Release/canvas.node Module parse failed: Unexpected character ' ' (1:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders (Source code omitted for this binary file)

이딴 쓰레기 같은 에러가 났다.

 

 

링크를 들어가서 보았더니

🙃 기본적으로 webpack은 JavaScript 및 JSON 파일만 이해합니다. 로더를 사용하면 웹팩이 다른 유형의 파일을 처리하고 애플리케이션에서 사용할 수 있고 종속성 그래프에 추가할 수 있는 유효한 모듈 로 변환할 수 있습니다.

라고 말한다.

 

pdf 파일을 읽지 못하고, 이해도 못하고~~ 그렇다 에러가 난 것이다.

 

추가적으로

모듈식 프로그래밍 에서 개발자는 프로그램을 모듈 이라는 개별 기능 덩어리로 나눕니다.각 모듈은 전체 프로그램보다 표면적이 작기 때문에 확인, 디버깅 및 테스트가 간단합니다. 잘 작성된 모듈은 견고한 추상화 및 캡슐화 경계를 제공하므로 각 모듈은 전체 애플리케이션 내에서 일관된 디자인과 명확한 목적을 갖습니다.

Node.js는 거의 처음부터 모듈식 프로그래밍을 지원했습니다. 그러나 웹에서는 모듈 지원이 더디게 이루어졌습니다. 다양한 이점과 제한 사항이 있는 웹에서 모듈식 JavaScript를 지원하는 여러 도구가 있습니다.

Webpack은 이러한 시스템에서 배운 교훈을 바탕으로 구축되며 프로젝트의 모든 파일에 모듈개념을 적용합니다.

 

->

 

https://github.com/Automattic/node-canvas/issues/867

 

github.com

 

 


 

 

그리고 파일로더를 사용해서 해결 해보자!

 

File 로더 - Webpack 러닝 가이드

// 이미지 포멧: PNG, JP(E)G, GIF, SVG, WEBP

yamoo9.gitbook.io

 

📌 npm i file-loader -D

 

설치해주었다.

 

 

next.config.js

파일에 추가하기!

webpack(config) {
    config.module.rules.push({
      test: /canvas\\.node$/,
      use: 'file-loader',
    });

    return config;
  },

 

 

자 ! 다음 단계의 에러 예상했지

 

 

width 속성이 필요하다? 코드 중에서 찾아서 넣어주었다.

<Page height={400} width={0} pageNumber={pageNumber} />

 

 

 

 

 

받아오긴했는데 텍스트가 없다..

 

 

 

 

콘솔창을 보니 이런 경고가 뜬다.

 

Cmap 관련 에러인 것 같다…

‼️ Warning: Error during font loading: CMapReaderFactory not initialized, see the useWorkerFetch parameter.

 

 

해결 방법으로 Document 컴포넌트에 options 속성을 넣어주자!

https://unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,
          cMapPacked: true,
        }}
        className="flex justify-center"
      >

 

 

→ 그리고 기본 예제에서 버튼을 눌러서 이전, 다음 페이지로 이동 했는데, Documents 컴포넌트 안에

 

 

<div className="w-full h-[510px] overflow-scroll no-scrollbar">
          {Array.from(new Array(numPages), (_, index) => (
            <Page
              width={400}
              height={600}
              key={index}
              pageNumber={index + 1}
              renderAnnotationLayer={false}
            />
          ))}
        </div>

작성하여, scroll 하여 전체 pdf 가 보여질 수 있도록 했다.

 

 

여기 h-[510px] 높이 값을 주지 않는 다면!

pdf 파일의 페이지가, 현재 보이는 화면 높이 값 맞춰서 다 랜더링 될 것이다.

 

 

 

 

 

no-scrollbar 클래스 네임을 두어 globals.css 에 아래 코드를 추가 해주자!

스크롤바가 사라지고 깔끔해진다~

@layer utilities {
  @variants responsive {
    /* Hide scrollbar for Chrome, Safari and Opera */
    .no-scrollbar::-webkit-scrollbar {
      display: none;
    }

    /* Hide scrollbar for IE, Edge and Firefox */
    .no-scrollbar {
      -ms-overflow-style: none; /* IE and Edge */
      scrollbar-width: none; /* Firefox */
    }
  }
}

완성^^

 

 

아래는 사용된 pdf 코드이다.

속성에 관련해서는 상단의 react-pdf 페이지를 참조하면 될 것 같다.

        {/* 우클릭 막기 */}
        <div onContextMenu={e => e.preventDefault()}>
          <Document
            file={selectedImage && URL.createObjectURL(selectedImage)} // pdf 주소
            onLoadSuccess={onDocumentLoadSuccess}
            options={{
              cMapUrl: `https://unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,
              cMapPacked: true,
            }}
            loading={<Pdf />}
            noData={<Pdf />}
          >
            <div className="w-full">
              {Array.from(new Array(numPages), (_, index) => (
                <Page
                  key={index}
                  width={pdfSize}
                  pageNumber={index + 1}
                  renderAnnotationLayer={false}
                  renderTextLayer={true}
                  loading={<div />}
                  noData={<div />}
                />
              ))}
            </div>
          </Document>