본문 바로가기
FrontEnd

PDF에서 첫 페이지 썸네일 추출하기

by E_van 2025. 1. 22.

프로젝트에서 PDF 파일의 첫 페이지를 썸네일 이미지로 추출해야 할 때가 있습니다. 이를 위해 PDF.js 라이브러리를 사용하면 간단히 구현할 수 있습니다. 이번 글에서는 PDF 파일의 첫 페이지를 Canvas에 렌더링하고 썸네일 이미지를 생성하는 방법을 설명합니다.


1. 프로젝트 준비

먼저, 프로젝트를 시작하기 위해 다음과 같은 환경을 설정합니다:

  • 패키지 매니저: pnpm
  • 기술 스택: TypeScript, pdf.js
  • 목표: PDF 파일의 첫 페이지를 썸네일로 변환

프로젝트 초기화 및 라이브러리 설치

pnpm install -D pdfjs-dist

pdfjs-dist는 pdf.js의 브라우저 빌드 패키지입니다.


2. PDF 첫 페이지를 이미지로 변환하는 함수

PDF 파일의 첫 페이지를 썸네일로 변환하는 TypeScript 함수를 작성합니다. 주요 작업은 다음과 같습니다:

  1. PDF 파일 로드
    pdfjsLib.getDocument를 사용하여 PDF를 로드합니다.
  2. 첫 페이지 가져오기
    pdf.getPage(1)을 호출해 첫 페이지를 가져옵니다.
  3. Canvas에 렌더링
    페이지를 Canvas에 렌더링하고 썸네일 크기에 맞게 스케일을 조정합니다.
  4. Canvas를 Blob으로 변환
    렌더링된 Canvas를 Blob으로 변환하고 URL을 생성합니다.

코드 구현

import * as pdfjsLib from 'pdfjs-dist';

// pdf.worker.js 경로 설정
pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdfjs/pdf.worker.min.js';

export const pdfToImage = async (file: File): Promise<string> => {
  // PDF 파일 URL 생성
  const fileURL = URL.createObjectURL(file);

  // PDF 문서 로드
  const pdf = await pdfjsLib.getDocument({ url: fileURL }).promise;
  URL.revokeObjectURL(fileURL); // 메모리 누수를 방지하기 위해 URL 해제

  // 첫 번째 페이지 가져오기
  const page = await pdf.getPage(1);

  // 페이지 크기 정보
  const viewport = page.getViewport({ scale: 1 });
  const originalWidth = viewport.width;
  const originalHeight = viewport.height;

  // 페이지 방향에 따라 최대 크기 설정
  const isLandscape = originalWidth > originalHeight;
  const maxWidth = isLandscape ? 558 : 320;
  const maxHeight = isLandscape ? 320 : 558;

  // 스케일 계산
  const widthRatio = maxWidth / originalWidth;
  const heightRatio = maxHeight / originalHeight;
  const scale = Math.min(widthRatio, heightRatio);

  // Canvas 크기 설정
  const canvasWidth = originalWidth * scale;
  const canvasHeight = originalHeight * scale;

  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  canvas.width = canvasWidth;
  canvas.height = canvasHeight;

  if (!context) {
    throw new Error('Canvas 2D 컨텍스트를 가져오지 못했습니다.');
  }

  // 스케일 적용된 뷰포트
  const adjustedViewport = page.getViewport({ scale });

  // 페이지를 Canvas에 렌더링
  await page.render({
    canvasContext: context,
    viewport: adjustedViewport,
  }).promise;

  const blob = await new Promise<Blob>((resolve, reject) => {
    canvas.toBlob((blob) => {
      if (!blob) {
        reject(new Error('Canvas를 Blob으로 변환하는 데 실패했습니다.'));
      }
      resolve(blob as Blob);
    });
  });

  return URL.createObjectURL(blob);
};

3. 사용 예제

const image = await pdfToImage(e.target.files[0])
dispatch(formData.assign({ image: image }))​

4. 주요 포인트

  • pdf.worker.js 경로 설정
    pdfjsLib.GlobalWorkerOptions.workerSrc에 pdf.js 워커 파일 경로를 지정해야 합니다.
    프로젝트 구조에 맞게 Vite 설정 변경 혹은 public 과같은 경로를 설정하세요.
  • 메모리 관리
    PDF 파일의 URL과 Canvas Blob URL을 생성한 후, 사용이 끝나면 반드시 URL.revokeObjectURL을 호출해 메모리를 해제해야 합니다.
  • 오류 처리
    Canvas 2D 컨텍스트를 가져오지 못하거나, Blob 변환이 실패할 경우를 대비해 예외 처리를 구현해야 합니다.

이 코드는 브라우저에서 동작하며, TypeScript와 pdf.js를 활용해 PDF 파일의 첫 페이지를 이미지로 변환하는 방법을 간단히 보여줍니다. 필요에 따라 스케일 조정, 다른 페이지 렌더링 등 기능을 확장해 사용할 수 있습니다.