아마 문서 관련 시스템을 개발하시는 분들이라면 미리보기에 대한 고민을 많이 하셨을 수 있죠.
open source인 pdf.js를 소개합니다. 이 글은 2025년 1월 10일에 작성되었음을 남깁니다. 이 후 영향이 큰 업데이트가 있다면 공식문서를 가서 확인하시는 것이 나을거예요.
pdf.js의 공식문서를 보면서 따라오세요. 공식문서의 링크를 남깁니다.
https://mozilla.github.io/pdf.js/
PDF.js - Home
PDF.js A general-purpose, web standards-based platform for parsing and rendering PDFs. Download Demo GitHub Project
mozilla.github.io
pdf 파일처리에 대해서는 example 예제를 그냥 삽입하시면 보통 잘 나옵니다.그래서 파일부분은 공식 문서의 설명과 크게 다르지 않을 수 있습니다.
다만, example 내에는 미리보기라면 갖춰야할 확대 축소 기능이 없기 때문에 이 기능이 필요하신 분들 또는
base64String으로 불러오는 부분에는 페이징(previous, next 버튼 및 페이지 길이 표기)도 없기 때문에
이 부분이 필요하신 분들은 본문을 계속 따라 와주시면 됩니다.
제반요건 - 인터넷 연결 필요
(없이 가능하도록 만들 수 있습니다. 어려운일은 아니므로 여기서는 다루지 않습니다.
다만 댓글로 문의 주시면 답변은 드리겠습니다.)
1. 링크 접속 후 상단 메뉴의 [Example]을 클릭합니다.
2. example 페이지 내용을 요약해서 순서대로 적어보겠습니다.
먼저 모듈을 선언하여 불러와 줍니다. 그리고 pdfjsLib을 선언하고, 라이브러리의 기본옵션을 불러옵니다. (공통)
<script src="//mozilla.github.io/pdf.js/build/pdf.mjs" type="module"></script>
<script type="module">
var { pdfjsLib } = globalThis;
pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.mjs';
// 여기 위치에 다음내용 입력들어갑니다!
</script>
다음은 미리보기할 문서를 불러와야겠죠.
어떤 문서를 미리보기할지에 따라 다른데, 서버의 파일경로로 존재하는 파일 / 또는 base64String 상태의 파일을 모두 불러 올 수 있습니다.
a. 서버경로의 파일을 불러오는 방법
var pdfFileUrl = 'https://어쩌구/저쩌구/test.pdf'
var loadingTask = pdfjsLib.getDocument(pdfFileUrl);
b. base64String 형식의 데이터를 불러오는법
var pdfFileBase64Data = atob('베이스64스트링')
var loadingTask = pdfjsLib.getDocument({data: pdfFileBase64Data});
a,b에서 보는바와 같이 getDocument는 url 또는 {data: ${atob('base64string')} }를 입력받습니다. 한 번더 강조하는 이유는 이미 고민하고 들어와서 아실 분들도 있을 것이고 아예 처음오신분들은 나중 설명에서 필요하니 기억해두도록 합시다!
데이터로 선언한 loadingTask는 promise 속성을 가지고 있어 resolve로 불러온 pdf파일을 객체로 돌려줍니다.
loadingTask.promise.then(function(pdf) {
// 공식 pdf.js 문서와 같이 이 자리부터 pdf파일을 다룰 수 있습니다.
});
이제 pdf 파일을 다룰 수 있고, 이후 기본적인 pdf.js의 흐름은 다음과 같아요.
페이지 불러오기 -> 불러온 페이지를 렌더링하기
공식페이지 예제 바탕으로 간단하게 써보자면 아래와 같습니다.
// pdf의 페이지를 가져온다.
pdf.getPage(1).then(function(page) {
// 불러온 페이지를 렌더링한다.
var scale = 1.5;
var viewport = page.getViewport({ scale: scale, });
// Support HiDPI-screens.
var outputScale = window.devicePixelRatio || 1;
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.width = Math.floor(viewport.width * outputScale);
canvas.height = Math.floor(viewport.height * outputScale);
canvas.style.width = Math.floor(viewport.width) + "px";
canvas.style.height = Math.floor(viewport.height) + "px";
var transform = outputScale !== 1
? [outputScale, 0, 0, outputScale, 0, 0]
: null;
var renderContext = {
canvasContext: context,
transform: transform,
viewport: viewport
};
page.render(renderContext);
});
앞서 설명드린내용을 모두 이어서 써서 보여드리겠습니다. pdf 파일은 공식문서의 것을 그대로 사용합니다. ( 혹시 저작권 문제가 있다면 즉시 삭제하겠습니다. )
// 모듈 선언 후 불러오기
<script src="//mozilla.github.io/pdf.js/build/pdf.mjs" type="module"></script>
<script type="module">
// 기본 라이브러리 및 옵션 정보 불러오기
var { pdfjsLib } = globalThis;
pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.mjs';
// 파일주소로 페이지를 불러올 task 생성
var pdfFileUrl = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf'
var loadingTask = pdfjsLib.getDocument(pdfFileUrl);
// 프로미스로 리졸브를 pdf 객체로 반환받는다.
loadingTask.promise.then(function(pdf) {
// pdf의 페이지를 가져온다.
pdf.getPage(1).then(function(page) {
// 불러온 페이지를 렌더링한다.
var scale = 1.5;
var viewport = page.getViewport({ scale: scale, });
// Support HiDPI-screens.
var outputScale = window.devicePixelRatio || 1;
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.width = Math.floor(viewport.width * outputScale);
canvas.height = Math.floor(viewport.height * outputScale);
canvas.style.width = Math.floor(viewport.width) + "px";
canvas.style.height = Math.floor(viewport.height) + "px";
var transform = outputScale !== 1
? [outputScale, 0, 0, outputScale, 0, 0]
: null;
var renderContext = {
canvasContext: context,
transform: transform,
viewport: viewport
};
page.render(renderContext);
});
});
</script>
<h1>PDF.js 'Hello, world!' example</h1>
<p>Please use <a href="https://mozilla.github.io/pdf.js/getting_started/#download"><i>official releases</i></a> in production environments.</p>
<canvas id="the-canvas"></canvas>
[위소스의 html 구현완료 부 예제] 구분선 시작
PDF.js 'Hello, world!' example
Please use official releases in production environments.
[위소스의 html 구현완료 부 예제] 구분선 끝
이제 기본은 끝났습니다.
약간의 응용을 시작하겠습니다. 간단하게, previous버튼, next버튼, (문서 길이 + 현재 페이지), 확대 축소를 구현해보겠습니다.

먼저 previous 버튼, next 버튼 구현입니다.
구현이라고 말씀드렸으나 이 두 버튼은 공식문서 example 페이지 내에 있습니다.
그러나 굳이 설명드리는 이유, 본문 서두에 말씀드렸지만 base64string의 예제는 없기 때문입니다.

아까 기억하라고 말씀드렸던 getDocument의 변수에는 서버파일의 경로와 base64string을 입력하는 data방식이 있었죠.
getDocument을 호출할때 입력하는 변수 중 파일경로 문자열을 {data: 베이스64스트링 } 으로 교체만 해주면 됩니다!
[Previous/Next example]의 html 소스 내에서 getDocument 부분은 단 한 군데 존재합니다. 이것을 atob(base64string)로 받아온 byteArray-like data로 {data: 'byteArray-like data' } 대체해주면 됩니다. 아래 이미지에 표시해두었으니 참고하시기 바랍니다.

다음 확대 축소 구현입니다. 이 부분을 읽으시면 다른 속성들도 변경할 아이디어를 챙기실 수도 있을 것 같아요.
[Previous/Next example] 예제를 기준으로 설명드리겠습니다. 라이브러리 선언, 라이브러리 옵션이 추가된 다음 줄에 변수를 6개 선언하는데요, 이 중 크기를 나타내는 변수는 scale입니다.
그리고 그 아래 페이지를 랜더링하는 함수가 있죠. 자세히 뜯어 보실 필요는 없으나, 아래 이미지에서 표시한 부분, scale에서 이 부분을 입력 받음을 알 수 있습니다. 따라서 scale 변수를 변경하고, renderPage함수를 호출한다면 사이즈가 조정된다고 판단할 수 있습니다.

일단 확대 축소를 마우스 휠 등의 이벤트로도 하실 수 있겠지만, 저는 간단한 구현을 위해 확대 버튼과 축소 버튼을 구현하겠습니다.
<button id="zoomOut"> - </button>
<button id="zoomIn"> + </button>
scale은 한 페이지 내에서는 전역변수 이기 때문에 renderPage함수를 손대실 필요는 없고 scale만 어떤 이벤트로 변경해주면 되겠죠. 저는 확대 축소 버튼을 구현했으므로, 클릭이벤트를 통해 확대 축소를 하겠습니다.
function onZoonIn() {
if (scale >= 2) {
return;
}
scale += 0.1;
queueRenderPage(pageNum);
}
document.getElementById('zoomIn').addEventListener('click', onZoonIn);
function onZoomOut() {
if (scale <= 0.3) {
return;
}
scale-=0.1;
queueRenderPage(pageNum);
}
document.getElementById('zoomOut').addEventListener('click', onZoomOut);
'language & Framework > JS, TS' 카테고리의 다른 글
[pdf.js] 웹 pdf 뷰어 구현 - 라이브러리 편 pdf.js v4.10.38 (0) | 2025.01.13 |
---|---|
[js ES6] 화살표함수 기초와 forEach, map, filter, reduce, every, some (0) | 2023.04.12 |
[dhtmlx7, 8] sidebar 첫 사용 (0) | 2023.03.11 |