프로젝트에서 PDF 파일의 첫 페이지를 썸네일 이미지로 추출해야 할 때가 있습니다. 이를 위해 PDF.js 라이브러리를 사용하면 간단히 구현할 수 있습니다. 이번 글에서는 PDF 파일의 첫 페이지를 Canvas에 렌더링하고 썸네일 이미지를 생성하는 방법을 설명합니다.
1. 프로젝트 준비
먼저, 프로젝트를 시작하기 위해 다음과 같은 환경을 설정합니다:
- 패키지 매니저: pnpm
- 기술 스택: TypeScript, pdf.js
- 목표: PDF 파일의 첫 페이지를 썸네일로 변환
프로젝트 초기화 및 라이브러리 설치
pnpm install -D pdfjs-dist
pdfjs-dist는 pdf.js의 브라우저 빌드 패키지입니다.
2. PDF 첫 페이지를 이미지로 변환하는 함수
PDF 파일의 첫 페이지를 썸네일로 변환하는 TypeScript 함수를 작성합니다. 주요 작업은 다음과 같습니다:
- PDF 파일 로드
pdfjsLib.getDocument를 사용하여 PDF를 로드합니다. - 첫 페이지 가져오기
pdf.getPage(1)을 호출해 첫 페이지를 가져옵니다. - Canvas에 렌더링
페이지를 Canvas에 렌더링하고 썸네일 크기에 맞게 스케일을 조정합니다. - 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 파일의 첫 페이지를 이미지로 변환하는 방법을 간단히 보여줍니다. 필요에 따라 스케일 조정, 다른 페이지 렌더링 등 기능을 확장해 사용할 수 있습니다.