Vue

Vue3에서 pdfmake로 pdf 문서 만들기(feat. Grunt, Typescript, 에러해결)

HYEPPY98 2023. 10. 16. 10:24

Vue3에서 pdf 문서를 만들어봅시다!

 

이걸 만들면서 수없는 에러를 마주했다..

pdf 문서를 만드는 것 부터 만들면서 마주한 모든 에러를 기록해보려 한다!

 

# pdfmake란?

pdfmake는 자바스크립트에서 pdf 문서를 만들 수 있도록 도와주는 라이브러리 입니다!

 

- pdfmake 공식 사이트

http://pdfmake.org/#/

 

- 공식 문서

https://pdfmake.github.io/docs/0.1/

 

- 공식 사이트에서 playground를 통해 테스트하기

http://pdfmake.org/playground.html

 

# pdfmake 설치하기

pdmake 사용을 위해 npm으로 설치했다!

 npm i pdfmake

 

설치 후 import를 하자마자 빨간줄이 뜬다 ㅜ

에러는 다음과 같다.

could not find a declaration file for module 'pdfmake/build/pdfmake'.
Try `npm i --save-dev @types/pdfmake` if it exists or add a new declaration (.d.ts) file containing `declare module `pdfmake/build/pdfmake`;`

 

대충 읽어보면 pdfmake 찾을 수 없고, `npm i --save-dev @types/pdfmake` 시도해봐라~ 라고 말하는 것 같다..

바로 시도해본다 ㅎ

npm i --save-dev @types/pdfmake

 

혹시 설치 후에도 빨간줄이 사라지지 않는다면, vscode를 껐다 켜보자!

 

 

# pdf 문서 만들기

pdf 문서를 만드는 코드는 생각보다 정말 간단하다!

<template>
  <div class="page">
    <v-btn @click="openPDF">OPEN PDF</v-btn> // 버튼 클릭 시 openPDF 함수 실행
  </div>
</template>

<script setup lang="ts">
import * as pdfMake from "pdfmake/build/pdfmake"; 
import * as pdfFonts from "pdfmake/build/vfs_fonts";

(<any>pdfMake).vfs = pdfFonts.pdfMake.vfs;

function openPDF() {
  var docDefinition = {
    content: [
      { text: "HYEPPY TISTORY", style: "header" }, // pdf에 들어갈 content 및 스타일 정의
      {
        text: "안녕하세요!! pdf 문서를 만들어봅시다~~~.",
        style: "subheader",
        margin: 30,
      },
    ],
    styles: {
      header: {
        fontSize: 40,
        bold: true,
      },
      subheader: {
        fontSize: 20,
        bold: true,
      },
    },
  };
  pdfMake.createPdf(docDefinition).open(); // pdf 문서 열기
}

 

짠!!

 

매우 간단하지만 한글 불러오는건 어려운가보네,,ㅎㅎ

 

# 왜 한글이 깨지는걸까?

한글이 깨지는 문제가 발생했다. 왜일까?

문제를 해결하기 전에 중요한 한 가지를 먼저 알고 가는게 좋을 것 같다

 

공식문서에도 나와있듯이 vfs_font.js는 Roboto 폰트가 디폴트인데,

Roboto 폰트가 한글을 지원하지 않아서 이러한 문제가 생기는 것이다.

 

디폴트 폰트가 무엇인지 확인할 수 있는데

프로젝트 내 node_modules/pdfmake/build/ 경로 아래에 vfs_font.js가 존재한다.

 

vfs_font.js를 열어서 유심히보면

아래와 같은 형식으로 되어있을 것이다!

this.pdfMake = this.pdfMake || {}; this.pdfMake.vfs = {
  "Roboto-Italic.ttf": "AAEAAAARAQAABAA~~",
  "Roboto-MediumItalic.ttf": ARAQAABAA~~~",
  "Roboto-Regular.ttf": ARAQAABAA~~~",
  }

 

즉, vfs_font.js 내에 있는 폰트만 사용할 수 있다!

vfs_font.js 파일이 어디에 존재하고 어떠한 형식인지 알았다면 다음 단계로 넘어가도 좋다!!!

 

이것을 봐놓는것이 나중에 중요할 것이여,, 제가 헤맸거든여,,

 

 

# pdfmake 한글 깨짐 현상 해결하기(feat. Grunt)

한글이 깨지니 한글을 지원하는 폰트를 사용해야 한다.

 

pdfmake는 14개의 폰트를 지원하지만 나는 custom 폰트를 사용하려고 한다!

https://pdfmake.github.io/docs/0.1/fonts/standard-14-fonts/

 

내가 시도한 custom 폰트를 사용하는 방법은 다음과 같다.

1. 사용하려는 font를 다운받는다.(otf, ttf)

2. 다운받은 font를 vfs_font.js에 추가한다.

3. 다운받은 font를 정의하여 사용한다!

+ 결론부터 말하자면, 나는 otf를 다운받아 사용했는데, 문서가 열리지 않는 버그가 있었다.
ttf를 다운받아서 사용하니 문제가 사라졌다. 그러니 ttf로 따라해보고, 만약 otf가 잘 동작한다면 댓글로 공유해주세여><

 

1. 사용하려는 font를 다운받는다.(otf, ttf)

나는 네이버 글꼴 모음(https://hangeul.naver.com/font/nanum)에서 나눔고딕을 다운받았고, 

src/examples/fonts 폴더 아래 다운받은 폰트를 넣었다.

 

2. 다운받은 font를 vfs_font.js에 추가한다.

이제 다운받은 font를 vfs_font.js에 추가해야한다.

이 부분이 제일 오래걸리고 어려웠다 ㅜ 하지만 지나고 나니 이것도 별거 아니였어.. 그니까 겁먹지말고 끝까지 따라해보세욧!!

 

이제 다운받은 font를 vfs_font.js에 추가하기 위해서는 Grunt를 설치해야 한다.

 

1. Grunt 란?

Grunt는 자바스크립트 태스크 러너인데, 나도 처음 들어봐서 블로그(https://ux.stories.pe.kr/71) 보고 아~ 이런거구나 했다.

 

2. Grunt 사용하기

먼저 Grunt를 설치하자!

npm install -g grunt-cli
npm install grunt --save-dev

 

Grunt를 설치하면 Gruntfile.js 파일 생성된다. 

만약 생성되지 않았다면 프로젝트 상위 Gruntfile.js 파일을 만들자!

그리고 아래와 같이 Gruntfile.js 내 코드를 작성하자

/***** Gruntfile.js *****/
module.exports = function (grunt) {
  /* ... */

  grunt.initConfig({
    dump_dir: {
      fonts: {
        options: {
          pre: "this.pdfMake = this.pdfMake || {}; this.pdfMake.vfs = ",
          rootPath: "./src/assets/examples/fonts/",
        },
        files: {
          "./node_modules/pdfmake/build/vfs_fonts.js": ["./src/assets/examples/fonts/*"],
        },
      },
    },
  });
  grunt.loadNpmTasks("grunt-dump-dir");

  /* ... */
};

 

코드를 살펴보자!

 

나는 위에서 다운받은 font들을 "src/assets/example/fonts/" 에 두었다.

아래 코드는 "src/assets/example/fonts/"  *(모든 폰트)를  "node_modules/pdfmake/build/vfs_fonts.js"에 생성하는 코드이다.

아까 위에서 언급한 것 처럼, vfs_fonts.js 파일이 어디에 존재하는지 알았으니 동일한 경로에 만들어준다.

 files: {
          "./node_modules/pdfmake/build/vfs_fonts.js": ["./src/assets/examples/fonts/*"],
        },

 

아래 코드는 vfs_fonts.js를 작성할건데,

"this.pdfMake = this.pdfMake || {}; this.pdfMake.vfs = " 문자열을 가장 앞(pre)에 작성하는 코드이다!

아까 위에서 언급했듯이 vfs_fonts.js 파일의 형식이 this.pdfMake 어쩌구~~로 시작했기 떄문에 동일하게 작성한다!

 options: {
          pre: "this.pdfMake = this.pdfMake || {}; this.pdfMake.vfs = ",
          rootPath: "./src/assets/examples/fonts/",
        }

 

거의 다 왔다..

아래 명령어를 치면, 해당 경로에 vfs_fonts.js 파일이 생성될 것이다!

(테스트를 위해 files 경로를 바꿔서 해보세요!)

grunt dump_dir 

 

3. Grunt 에러..

grunt dump_dir 명령어 실행하니 아래와 같은 에러가 났다.

Local Npm module "grunt-dump-dir" not found. Is it installed?
Warning: Task "dump_dir" not found. Use --force to continue.

 

1. 설치하라는 것 같아서 아래 명령어로 설치

npm install grunt-dump-dir --save-dev

 

또 에러다..

 

2. 버전 충돌인 것 같아 아래 명령어로 다시 설치

npm install grunt-dump-dir --save-dev --legacy-peer-deps 

 

3. grunt dump_dir 명령어 다시 실행했더니 잘 생성되었다!

 

"node_modules/pdfmake/build/vfs_fonts.js" 에 "NanumGothic.ttf"가 추가된 것을 확인할 수 있다.

 

3. 다운받은 font를 정의하여 사용한다!

최종 코드는 아래와 같다!

<template>
  <div class="page">
    <v-btn @click="openPDF">OPEN PDF</v-btn>
  </div>
</template>

<script setup lang="ts">
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";

(<any>pdfMake).vfs = pdfFonts.pdfMake.vfs;
(<any>pdfMake).fonts = { // 추가
  NanumGothic: {
    normal: "NanumGothic.ttf",
    bold: "NanumGothic.ttf",
  },
};

function openPDF() {
  var docDefinition = {
    content: [
      { text: "HYEPPY TISTORY", style: "header" }, // pdf에 들어갈 content 및 스타일 정의
      {
        text: "안녕하세요!! pdf 문서를 만들어봅시다~~~.",
        style: "subheader",
        margin: 30,
      },
    ],
    styles: {
      header: {
        fontSize: 40,
        bold: true,
      },
      subheader: {
        fontSize: 20,
        bold: true,
      },
    },
    defaultStyle: {
      font: "NanumGothic", // NanumGothic 폰트를 디폴트 스타일로 정의
    },
  };
  pdfMake.createPdf(docDefinition).open();
}
</script>

 

결과 화면!!

한글이 출력되었다!! ㅎㅎ

 


제가 사용한 vfs_font.js 를 첨부했어요!

도움이 되었으면 좋겠슴다!!

vfs_fonts.js
17.89MB