본문 바로가기
FrontEnd

PDF 이미지 추출 기능 구현

by E_van 2025. 2. 27.

웹 애플리케이션에서 PDF 파일의 썸네일을 생성하는 기능은 사용자 경험을 향상하는 데 중요한 요소입니다. 특히, PDF 파일을 업로드할 때 미리보기를 제공하면 사용자가 보다 직관적으로 파일을 확인할 수 있습니다. 이번 글에서는 PDF 파일을 이미지로 변환하여 추출하는 방법을 소개합니다.

📌 PDF를 이미지로 변환하는 과정

1. pdfjs-dist 설정

PDF 파일을 다루기 위해 pdfjs-dist 라이브러리를 사용합니다. 먼저, GlobalWorkerOptions.workerSrc를 설정해야 합니다.

 
import * as pdfjsLib from 'pdfjs-dist'

pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdfjs/pdf.worker.min.js'

이 설정을 통해 PDF.js가 PDF를 분석하는 작업을 백그라운드에서 수행할 수 있게합니다.

2. PDF를 이미지로 변환하는 함수 구현

아래는 PDF 파일을 받아서 첫 번째 페이지를 WebP 이미지 파일로 변환하는 함수입니다.

interface ExtractImageFromPdf {
  file: File;
  pageNumber?: number;
  width?: number;
  height?: number;
  extension?: 'webp' | 'png' | 'jpeg' | 'jpg';
}

export const extractImageFromPdf = async ({
  file,
  pageNumber = 1,
  width = 600,
  height = 400,
  extension = 'webp',
}: ExtractImageFromPdf): Promise<File> => {
  const fileURL = URL.createObjectURL(file);
  const pdf = await pdfjsLib.getDocument({ url: fileURL }).promise;
  URL.revokeObjectURL(fileURL); // 메모리 누수 방지를 위해 URL 해제

  // 페이지 가져오기
  const page = await pdf.getPage(pageNumber);
  const viewport = page.getViewport({ scale: 1 });
  const { width: originalWidth, height: originalHeight } = viewport;

  // 가로/세로 비율에 따른 최대 크기 설정
  const isLandscape = originalWidth > originalHeight;
  const maxWidth = isLandscape ? width : height;
  const maxHeight = isLandscape ? height : width;

  const scale = Math.min(maxWidth / originalWidth, maxHeight / originalHeight);
  const canvasWidth = originalWidth * scale;
  const canvasHeight = originalHeight * scale;

  // 캔버스 생성 및 설정
  const canvas = document.createElement('canvas');
  canvas.width = canvasWidth;
  canvas.height = canvasHeight;

  const context = canvas.getContext('2d');
  if (!context) throw new Error('Failed to get canvas context');

  // PDF 페이지를 캔버스에 렌더링
  const adjustedViewport = page.getViewport({ scale });
  await page.render({ canvasContext: context, viewport: adjustedViewport })
    .promise;

  // 캔버스를 이미지 Blob으로 변환
  const blob = await new Promise<Blob>((resolve) => {
    canvas.toBlob((blob) => {
      if (!blob) throw new Error('Failed to convert canvas to blob');
      resolve(blob);
    }, `image/${extension}`);
  });

  // Blob을 File 객체로 변환
  const fileOriginalName = file.name.split('.').slice(0, -1).join('.');
  return new File([blob], `${fileOriginalName}.${extension}}`, {
    type: `image/${extension}`,
  });
};

✅ 코드 설명

  • PDF 파일을 객체 URL로 변환
    • URL.createObjectURL(file)을 사용해 PDF를 로드할 수 있도록 만듭니다.
    • 이후 pdfjsLib.getDocument({ url: fileURL })를 이용해 PDF 문서를 가져옵니다.
    • URL.revokeObjectURL(fileURL)을 호출해 메모리 누수를 방지합니다.
  • PDF의 첫 번째 페이지를 캔버스에 렌더링
    • pdf.getPage(1)을 호출해 첫 번째 페이지를 가져옵니다.
    • 페이지의 원래 크기를 구한 후, 최대 크기(558px × 400px)에 맞춰 비율을 유지한 채 축소합니다.
    • canvas.getContext('2d')를 이용해 2D 컨텍스트를 가져온 후 page.render()를 사용해 렌더링합니다.
  • 렌더링된 이미지를 Blob 및 File 객체로 변환
    • canvas.toBlob()을 사용해 WebP 이미지로 변환합니다.
    • 이를 File 객체로 변환해 파일 업로드 등에 활용할 수 있도록 합니다.

마무리

위 코드를 활용하면 PDF 파일을 업로드할 때 자동으로 썸네일 이미지를 생성할 수 있습니다.
특히, WebP 포맷을 사용하면 파일 크기를 줄이면서도 고품질 이미지를 유지할 수 있습니다.

이제 이 기능을 React, Next.js 등과 함께 활용해 PDF 파일 업로드 시 미리보기를 제공하는 UI를 구현해 보세요!