클라이언트 측 PDF 처리: 브라우저 로컬 PDF 도구의 작동 방식
클라이언트 측 PDF 도구는 서버가 할 일을 사용자의 브라우저에서 수행합니다. 이 페이지는 아키텍처를 이해하려는 개발자 및 IT 관리자를 대상으로 합니다: 어떤 브라우저 API가 관여되는지, 어떤 라이브러리가 무거운 작업을 수행하는지, 파일이 실제로 어디로 가는지, 그리고 정직한 한계는 무엇인지. IXPDF를 진행 중인 예로 사용하지만, 이 모델은 모든 브라우저 로컬 PDF 도구에 적용됩니다.
파이프라인
파일 입력에서 다운로드까지, 서버 없이
클라이언트 측 PDF 작업의 엔드투엔드 흐름은 다음과 같습니다:
- 파일 입력. 사용자가 파일을 드롭존에 올려놓습니다. 브라우저는 페이지에
File객체(디스크의 파일에 대한 포인터, 바이트 자체가 아님)를 줍니다. - 메모리로 읽기. 페이지는
file.arrayBuffer()를 호출하여 바이트를 페이지 메모리의ArrayBuffer로 읽습니다. 파일의 바이트가 페이지에 존재하는 유일한 순간입니다; 아직 worker에는 없습니다. - 검증. 페이지는 무엇보다 먼저 파일 형식(매직 바이트, 확장자)과 크기를 확인합니다. 잘못된 파일은 메인 스레드에서 빠르게 실패하며 worker에 도달하지 않습니다.
- Web Worker로 전송. 페이지는
ArrayBuffer를 worker에 보내며, transferable 전송을 사용하여 바이트가 worker의 힙으로 (복사 없이) 이동합니다. 메인 스레드는 더 이상 버퍼에 접근할 수 없습니다. - worker에서 처리. worker는 PDF 라이브러리(pdf-lib, PDF.js 또는 WASM으로 컴파일된 qpdf/mupdf)를 호출하여 PDF를 분석하고 수정합니다. 이것이 무거운 작업이며 UI가 멈추지 않도록 메인 스레드 외부에서 실행됩니다.
- 결과 반환. worker는 새
ArrayBuffer(또는Blob)를 생성하고 다시 transferable로 메인 스레드에 반환합니다. - 다운로드 제공. 메인 스레드는 결과를
Blob으로 감싸고,URL.createObjectURL(blob)을 호출하여<a download>요소로 다운로드를 제공합니다. 메모리 누수를 방지하기 위해 다운로드 시작 후 객체 URL은 폐기됩니다.
이 흐름의 어느 순간에도 파일은 기기를 떠나지 않습니다. 파일 내용을 담은 fetch, XMLHttpRequest,sendBeacon은 없습니다. 페이지가 수행하는 유일한 네트워크 요청은 페이지 첫 로드 시 정적 자산(HTML, JS, CSS, 글꼴)에 대한 것입니다.
구성 요소
관여된 브라우저 API 및 라이브러리
클라이언트 측 PDF 도구는 작은 브라우저 API 집합과 작은 JavaScript 라이브러리 집합에 의존합니다. 각각 한 가지 일을 합니다.
- File API —
File및Blob인터페이스.file.arrayBuffer()는 바이트를 메모리로 읽습니다;new Blob([bytes], { type: 'application/pdf' })는 바이트를 다운로드용으로 감쌉니다. - Web Workers — 자체 힙을 가진 백그라운드 스레드, DOM 접근 불가. PDF 분석이 메인 스레드를 반응형으로 유지하기 위해 여기서 실행됩니다. 통신은
postMessage로;ArrayBuffer는 두 번째 인수를 통해 전송(이동, 복사 아님)될 수 있습니다. - URL.createObjectURL / URL.revokeObjectURL — 메모리의 결과를 가리키는 임시
blob:URL을 생성하여<a download>요소가 다운로드를 제공할 수 있게 합니다. URL은 폐기되지 않으면 누수됩니다. - pdf-lib — PDF를 생성, 수정, 재저장할 수 있는 순수 JavaScript PDF 라이브러리. 병합, 분할, 회전, 워터마크, 페이지 작업 및 메타데이터 편집에 사용됩니다. 암호화는 지원하지 않습니다 (알려진 한계 — 아래 참조).
- PDF.js — Mozilla의 PDF 렌더러, 페이지를 캔버스에 렌더링하는 데(PDF→이미지 변환) 사용되며 pdf-lib가 읽을 수 없는 PDF를 분석하는 데에도 사용됩니다.
- WASM (선택적) — 네이티브 코드를 WASM으로 컴파일하여 브라우저에서 준-네이티브 속도로 실행하는 라이브러리용. qpdf와 mupdf는 WASM으로 컴파일할 수 있습니다; IXPDF는 pdf-lib가 할 수 없는 작업에 선택적으로 이 경로를 사용합니다.
- CompressionStream — 스트림 압축(gzip, deflate)용 네이티브 브라우저 API. JavaScript 압축 라이브러리를 내장하지 않고 일부 크기 감소 경로에 유용합니다.
worker를 쓰는 이유
PDF 분석이 메인 스레드에서 실행되지 않는 이유
PDF 분석은 CPU 집약적이며 동기적 형태입니다 — 바이트를 읽고, 객체를 디코딩하고, 교차 참조를 따라가며, 메모리에 트리를 구축합니다. 50MB PDF는 수백 밀리초가 걸릴 수 있으며, 200MB PDF는 수 초가 걸릴 수 있습니다. 이 작업이 메인 스레드에서 실행되면 페이지는 그 시간 동안 멈춥니다: 애니메이션, 스크롤, 입력 모두. 브라우저가 "페이지가 응답하지 않습니다" 대화상자를 표시할 수 있습니다.
작업을 Web Worker로 옮기면 이것이 해결됩니다. 메인 스레드는 반응형을 유지하고; worker는 백그라운드에서 PDF를 처리하며; 페이지는 진행 표시기를 표시하고 worker가 결과를 반환할 때 UI를 업데이트합니다. 대가로 worker는 DOM에 접근할 수 없으므로, 모든 UI 작업은 결과 반환 후 메인 스레드에서 수행되어야 합니다.
worker는 또한 자체 메모리 예산을 가집니다. worker에 전송된 큰 PDF는 페이지의 힙이 아닌 worker의 힙에 존재합니다. 이것은 매우 큰 파일에 중요합니다: 페이지는 가볍게 유지되고 worker가 무거운 버퍼를 보유하며, worker가 끝나면 버퍼는 해제됩니다.
transferable 객체
바이트를 복사하지 않고 이동
ArrayBuffer가 전송 없이 worker에 보내지면 바이트는 복사됩니다 — worker는 자체 사본을 얻고, 메인 스레드는 원본을 유지합니다. 100MB PDF의 경우, 200MB 메모리가 사용되며 복사 시간이 인지됩니다.
해결책은 전송 목록입니다: postMessage의 두 번째 인수. 전송 목록에 버퍼를 나열하면 바이트가 worker로 이동합니다 — 메인 스레드의 참조는 분리되고(길이 0), worker가 소유권을 갖습니다. 복사 없음, 메모리 두 배 없음. 결과를 반환할 때도 같은 것이 사용됩니다.
이것은 규모에서 중요한 작은 세부 사항입니다. transferable이 없다면 큰 파일의 클라이언트 측 PDF 처리는 실용적이지 않을 것입니다.
정직한 한계
브라우저가 잘 할 수 없는 것
클라이언트 측 처리는 은탄환이 아닙니다. 일부 작업은 오늘날 브라우저에서 잘 하기 어렵거나 불가능하며, 정직한 도구는 이를 위장하는 대신 밝힙니다.
- OCR. 스캔된 PDF의 광학 문자 인식은 훈련된 모델과 많은 CPU가 필요합니다. 브라우저 OCR(Tesseract.js)이 존재하지만 품질이 데스크톱 Tesseract나 클라우드 OCR에 크게 미치지 못합니다. IXPDF는 OCR을 "연구 필요"로 표시합니다.
- PDF 암호화(비밀번호 보호). pdf-lib는 아직 암호화된 PDF 쓰기를 지원하지 않습니다. 추가하려면 다른 라이브러리 또는 WASM으로 컴파일된 qpdf가 필요합니다. IXPDF의 PDF 보호 도구는 "연구 필요"입니다.
- PDF → Word/Excel/PowerPoint. PDF를 편집 가능한 Office 파일로 변환하는 것은 백엔드가 필요한 레이아웃 재구축 문제입니다. 이를 시도하는 브라우저 라이브러리는 낮은 충실도의 결과를 생성합니다. IXPDF는 이러한 변환을 제공하지 않습니다.
- AI 요약 / 질문-응답. 모델과 백엔드가 필요합니다. 2026년에 허용 가능한 품질로 클라이언트 측에서 수행할 수 없습니다. IXPDF는 AI 기능을 제공하지 않습니다.
- 매우 큰 파일. 브라우저 탭에는 메모리 예산(보통 수 GB)이 있습니다. 2GB PDF는 대부분의 브라우저에서 OOM을 일으킬 것입니다. 서버 측 도구는 스트리밍으로 처리합니다; 브라우저 도구는 같은 방식으로 PDF를 스트림할 수 없습니다.
정직한 접근 방식은 이러한 기능을 UI에서 Planned,Research Required 또는 Future Backend Candidate로 표시하고, 빈 결과를 반환하며 성공했다고 거짓말하는 가짜 도구를 내보내지 않는 것입니다. 이것이 local-first 도구와 콘텐츠 농장의 "tool" 페이지 사이의 선입니다.
중요한 이유
개인정보 보호 속성은 구조적이며, 약속이 아닙니다
클라이언트 측 처리가 의미 있는 개인정보 보호 속성 — 단지 마케팅 주장이 아닌 — 인 이유는 비업로드 보증이 정책이 아닌 코드 구조에 의해 강제되기 때문입니다. 업로드할 서버가 없습니다. 페이지에는 파일 내용을 전송하는 fetch 호출이 없습니다. 사용자는 DevTools를 열고 Network 탭으로 가서 작업을 실행하고 어떤 요청도 파일을 전송하지 않는지 확인할 수 있습니다. 보증은 감사 가능합니다.
이는 24시간 후 파일을 삭제하겠다고 약속하는 서버 측 도구와 다릅니다. 그 약속은 정책과 볼 수 없는 인프라에 의해 강제됩니다. 클라이언트 측 처리는 서버가 없음에 의해 강제됩니다. 민감한 파일의 경우, 이것이 중요한 차이입니다.
자세한 내용은 IXPDF 개인정보 보호 페이지 및 IXPDF 소개에서 확인하세요.
다음에 읽을 것