PDF 파일 크기 줄이기: JavaScript(React)에서 이미지, 글꼴, 콘텐츠 스트림

2026-09-18 08:27:39 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

브라우저에서 Spire.PDF for JavaScript로 PDF의 이미지, 글꼴 및 콘텐츠 스트림 압축

PDF가 그냥 “너무 큰” 경우는 드뭅니다. 특정한 관문—메일 첨부 용량 제한, 업로드 양식, 저장소 할당량—에 비해 너무 큰 것이며, 그 한도를 넘긴 원인은 대개 세 가지 중 하나입니다. 어느 것인지 모른 채 압축하는 것은 추측에 불과하고, 추측은 품질 저하나 또 한 번의 업로드 실패라는 대가를 치릅니다.

Spire.PDF for JavaScript는 이 세 가지 위치 각각에 대한 옵션을 갖춘 압축기를 제공합니다. 이들은 개별적으로 또는 함께 적용할 수 있으며, 각각의 트레이드오프가 상당히 다르기 때문에 결정하기 전에 각각을 이해할 가치가 있습니다. 모든 것이 브라우저의 WebAssembly에서 실행되고 파일은 가상 파일 시스템(VFS)을 통해 이동하므로, 문서를 더 작게 만들기 위해 제3자 서비스에 업로드할 필요가 없습니다.

프로젝트 설정은 React 프로젝트에 Spire.PDF for JavaScript 통합하기를 참조하세요. 아래 예제는 패키지가 설치되어 있고 WebAssembly 모듈이 초기화되었다고 가정합니다.


PDF를 실제로 크게 만드는 요인

PDF의 파일 크기는 세 가지 다른 곳에서 비롯되며, 그 동작 방식은 서로 전혀 다릅니다:

용량이 차지하는 위치 어떻게 보이는지 원인이라는 단서
이미지 자체 해상도로 포함된 비트맵 — 스캔, 사진, 내보낸 스크린샷 페이지 수는 적지만 수십 MB
포함된 글꼴 텍스트가 어디서나 동일하게 렌더링되도록 파일 내부에 저장된 글꼴 프로그램 대부분 텍스트인데도 여전히 몇 MB
콘텐츠 스트림 텍스트와 벡터 그래픽 뒤에 있는 그리기 명령 여러 다른 도구로 파일을 편집하거나 다시 저장한 경우

같은 분량의 두 문서도 이 때문에 크기가 10배까지 차이 날 수 있습니다. 5페이지 분량의 스캔 계약서는 20MB에 달할 수 있지만, 50페이지 텍스트 보고서는 1MB 미만일 수 있습니다. 그래서 “이걸 얼마나 압축할 수 있나요?”에는 하나의 답이 없습니다. 스캔이 많은 파일은 줄일 것이 많고, 이미 대부분 텍스트와 벡터 아트인 문서는 거의 하한에 가깝습니다.

따라서 진단이 먼저입니다. 텍스트가 많은 문서를 이미지 설정으로 압축하면 거의 효과가 없고, 실제 무게가 글꼴에 있는 문서의 이미지를 눌러 압축하면 얻는 것 없이 품질만 낭비합니다.


세 가지 압축 레버

PdfCompressor는 Options를 통해 전략을 노출하며, 각 설정 그룹은 위의 세 가지 원인 중 하나에 대응합니다:

옵션 대상 포기하는 것
ImageCompressionOptions 페이지의 비트맵 이미지 충실도 — 세 가지 중 유일한 손실 압축 수단입니다
TextCompressionOptions 포함된 글꼴 데이터 글꼴 포함을 해제하지 않는 한 없음. 포함을 해제하면 이식성
CompressContents 페이지 콘텐츠 스트림 실질적으로 없음 — 콘텐츠는 버려지지 않고 다시 인코딩됨

다음 세 섹션에서는 각각을 하나씩 다루어 각각의 효과를 개별적으로 확인할 수 있습니다. 그다음 섹션에서는 이들을 결합하며, 이는 일반적으로 프로덕션에서 원하게 될 방식입니다.


이미지 압축

고해상도 비트맵은 너무 큰 PDF의 가장 흔한 단일 원인이면서, 가장 큰 절감 효과를 볼 수 있는 곳이기도 합니다. Options.ImageCompressionOptions는 세 가지 속성을 통해 크기 조정과 재인코딩을 제어합니다:

속성 기능 설정할 가치가 있을 때
ResizeImages 이미지를 비례적으로 축소한 다음 다시 인코딩합니다 표시되는 해상도보다 훨씬 높은 해상도로 촬영/스캔한 사진이나 문서
CompressImage 이미지에 손실 재인코딩을 적용합니다 이미지 품질을 어느 정도 희생해도 될 때마다
ImageQuality 해당 재인코딩의 품질 등급을 선택합니다 마지막 조정값 — High는 세부 정보를 더 유지하고, Low는 더 작은 파일을 만듭니다
// Compress images in the document: resize, re-compress, and lower the quality
compressor.Options.ImageCompressionOptions.ResizeImages = true;
compressor.Options.ImageCompressionOptions.CompressImage = true;
compressor.Options.ImageCompressionOptions.ImageQuality = pdfModule.ImageQuality.Low;

ImageQuality는 그 자체로는 아무것도 하지 않습니다. 처음 두 속성을 통과하는 이미지가 어떻게 인코딩되는지만 설명하므로, 이것만 설정하면 같은 파일이 그대로 나옵니다. 그리고 이것이 유일한 손실 압축 수단이므로, PDF를 화면에서 읽는 것이 아니라 인쇄할 예정이라면 먼저 High 등급으로 테스트하세요.


글꼴: 압축 또는 포함 해제

원래 서체가 없는 컴퓨터에서도 텍스트가 동일하게 렌더링되도록, PDF는 텍스트에 사용된 글꼴 프로그램을 파일 안에 포함합니다. 하위 집합화되었을 수는 있어도 아예 없는 것은 아니며, 여러 글꼴 패밀리와 여러 굵기가 합쳐져 용량을 차지합니다. Options.TextCompressionOptions는 이를 처리하는 두 가지 매우 다른 방법을 제공합니다:

속성 기능 주의점
CompressFonts 포함된 글꼴 데이터를 압축하고 글꼴은 그대로 둡니다 렌더링에는 영향 없음 — 글리프가 파일에 남아 있습니다
UnembedFonts 글꼴 프로그램을 제거하고 리더가 시스템 글꼴로 대체하도록 합니다 해당 글꼴이 없는 곳에서는 글리프 대체나 자간 이동이 발생함
// Compress font data; UnembedFonts goes further and removes the embedded fonts
compressor.Options.TextCompressionOptions.CompressFonts = true;
compressor.Options.TextCompressionOptions.UnembedFonts = true;

위 조합은 공격적인 방식이며, 정확히 한 가지 조건에서만 안전합니다. 즉, 문서를 무엇이 렌더링할지 아는 경우입니다. 다운로드 링크나 알 수 없는 수신자에게 보내는 이메일은 그 조건에 해당하지 않습니다. 그런 경우에는 글꼴을 포함된 상태로 두고 CompressFonts가 작업하도록 하세요. 글꼴 집합이 고정된 경우, 예를 들어 구성이 알려진 내부 뷰어에서만 포함을 해제하세요.


콘텐츠 스트림 재압축

페이지의 텍스트와 벡터 그리기 명령은 콘텐츠 스트림에 들어 있습니다. PDF가 작성될 때 이들은 압축되지만, 반복적으로 편집되었거나 여러 도구 사이를 거친 문서는 스트림에 중복이 쌓일 수 있습니다. Options.CompressContents는 해당 스트림을 다시 인코딩합니다:

// Re-compress the document content streams
compressor.Options.CompressContents = true;

단독으로 보면 세 가지 중 가장 극적인 효과는 없습니다. 사진이 많은 문서를 구해 주리라 기대하지 마세요. 복잡한 레이아웃의 텍스트 밀도가 높은 문서에서 제 역할을 하며, 스트림을 다시 인코딩해도 그리는 내용이 바뀌지 않으므로 켜 두기에 가장 안전한 수단입니다.


세 가지 모두 한 번에

세 가지 차원은 세 번의 별도 실행이 아닙니다. 하나의 PdfCompressor를 파일에 지정하고, 필요한 만큼 옵션을 설정한 다음, CompressToFile로 결과를 한 번에 기록합니다.

아래 예제는 고해상도 이미지와 본문 텍스트가 모두 포함된 문서에서 High 등급의 이미지 크기 조정 및 재압축, 글꼴 포함 해제를 동반한 글꼴 압축, 콘텐츠 스트림 재압축을 활성화합니다:

function App() {
  const compressPdfDocument = async () => {
    // Get the Spire.PDF WASM module
    const pdfModule = window.wasmModule?.spirepdf;

    // Check that the module is ready
    if (!pdfModule) {
      alert('Spire.PDF is not ready yet');
      return;
    }

    // Load the PDF to be compressed into the VFS
    const inputFileName = 'ImageDocument.pdf';
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);

    // Create a PdfCompressor and point it at the PDF to compress
    let compressor = new pdfModule.PdfCompressor({ filePath: inputFileName });

    // 1. Image compression: resize and re-compress images, with a higher quality tier
    compressor.Options.ImageCompressionOptions.ResizeImages = true;
    compressor.Options.ImageCompressionOptions.CompressImage = true;
    compressor.Options.ImageCompressionOptions.ImageQuality = pdfModule.ImageQuality.High;

    // 2. Font compression: compress font data and remove embedded fonts
    compressor.Options.TextCompressionOptions.CompressFonts = true;
    compressor.Options.TextCompressionOptions.UnembedFonts = true;

    // 3. Content compression: re-compress the document content streams
    compressor.Options.CompressContents = true;

    // Define the output file name and compress to it
    const outputFileName = 'CompressedDocument.pdf';
    compressor.CompressToFile(outputFileName);

    // Read the generated file from the VFS and trigger the download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/pdf' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Compress PDF Document</h1>
      <button onClick={compressPdfDocument}>
        Generate
      </button>
    </div>
  );
}

export default App;

세 가지 접근 방식을 모두 결합하여 압축한 PDF 문서

세 가지 접근 방식을 모두 결합하여 압축한 PDF 문서

이 코드의 형태에 관해 두 가지가 있습니다. 원본은 VFS에 그대로 남습니다. CompressToFile은 새 문서를 작성하므로 전후 비교 선택이 가능합니다. 또한 압축기는 렌더링된 페이지가 아니라 문서의 리소스에서 작동하므로 텍스트는 실제 텍스트로 남습니다. 여전히 선택 가능하고 검색 가능합니다. 이미지만 다시 인코딩됩니다.


변경 사항 확인

두 파일 모두 VFS에 있으므로, 설정이 효과가 있었는지 추측하는 대신 사용자에게 결과를 전달하기 전에 비교할 수 있습니다:

// Both the original and the compressed copy are in the VFS
const originalBytes = window.dotnetRuntime.Module.FS.readFile(inputFileName).length;
const compressedBytes = window.dotnetRuntime.Module.FS.readFile(outputFileName).length;

다운로드 옆에 차이를 백분율로 표시하고 빈 버튼만 제공하지 마세요. 그러면 파일이 목적지에 보내기에 충분히 작아졌는지 사용자에게 즉시 알려 줍니다. 두 숫자가 거의 같다면, 압축한 위치에 용량이 있었던 것이 아닙니다.


문서에 맞게 설정 조정

문서 활성화 주의할 점
스캔한 페이지, 사진, 스크린샷 ResizeImages, CompressImage, 화면 또는 인쇄에 맞게 조정한 ImageQuality 스캔 내부의 미세한 디테일이 가장 먼저 흐려짐 — 배포 전에 High에서 확인하세요
대부분 텍스트와 벡터 아트 CompressFonts, CompressContents 본질적으로 절감 효과는 크지 않음. 이미지 설정으로 이를 쫓지 마세요
혼합 콘텐츠 세 가지 모두, ImageQuality.High에서 가장 안전한 범용 프로필이며, 대개 시작하기 가장 좋은 지점
이미 배포용으로 최적화됨 CompressContents만 얻을 것이 거의 없음. 공격적인 이미지 재인코딩은 거의 이득 없이 품질만 잃을 수 있음

일반적인 문제

파일이 거의 줄지 않았고 PDF에 이미지가 거의 없습니다. 크기는 글꼴이나 콘텐츠 스트림에서 비롯됩니다. TextCompressionOptions를 켜고 — 보기 환경을 아는 경우에만 UnembedFonts를 사용 — CompressContents를 추가하세요. 텍스트 밀도가 높은 문서는 이 두 가지에만 반응하고 다른 것에는 반응하지 않습니다.

압축 후 텍스트가 다르게 렌더링됩니다. 그것은 UnembedFonts가 말 그대로 하는 일입니다. false로 되돌리고 CompressFonts = true를 유지하세요. 글꼴 데이터는 여전히 압축되지만 글리프는 파일에 남아 있습니다.

출력에서 이미지가 흐리거나 각져 보입니다. ImageQuality 등급이 너무 낮거나, ResizeImages가 인쇄를 위해 해상도가 필요한 이미지를 축소했기 때문입니다. 인쇄할 항목은 High에서 시작하세요.

압축된 파일이 원본과 같은 크기입니다. 일부 문서는 이미 최적화되어 의미 있게 줄일 것이 남아 있지 않습니다. 설정이 실패했다고 가정하지 말고 위의 바이트 비교로 확인하세요.

첫 클릭에 아무 일도 일어나지 않습니다. WebAssembly 모듈은 비동기적으로 로드됩니다. if (!pdfModule) return; 가드가 바로 그 용도입니다. 실제 애플리케이션에서는 경고를 표시하는 대신 모듈이 준비되었다고 보고할 때까지 버튼을 비활성화하세요.


자주 묻는 질문

어떤 수단을 먼저 사용해야 하나요?

이미지가 원인이라고 가정한다면 이미지부터 — 하지만 확인하세요. 문서가 텍스트 위주이고 페이지 수에 비해 용량이 과도하다면 글꼴과 콘텐츠 스트림부터 시작하고 이미지 설정은 건드리지 마세요.

PDF를 압축하면 텍스트를 읽을 수 없거나 선택할 수 없게 되나요?

아니요. 그리고 여기에서 API 기반 압축기가 모든 페이지를 JPEG로 래스터화하는 온라인 도구와 다릅니다. 텍스트는 텍스트로 남고, 벡터 아트는 벡터로 남으며, 비트맵만 처리됩니다. 따라서 압축된 복사본도 여전히 선택, 검색, 인쇄가 가능합니다.

문서의 일부만 압축할 수 있나요?

압축기는 문서 전체에 작동합니다. 파일의 일부는 줄이고 일부는 그대로 두어야 한다면, 먼저 문서를 분할하고, 필요한 부분을 압축한 다음, 다시 병합하세요.

원본을 유지하고 압축된 복사본을 선택지로 제공할 수 있나요?

예. CompressToFile은 새 파일 이름에 기록하고 입력 파일은 VFS에 남겨 두므로, 같은 세션에서 두 버전을 모두 사용할 수 있습니다. 사용자가 품질을 얼마나 희생할지 결정할 때 유용합니다.

서버가 필요한가요, 아니면 전적으로 브라우저에서 실행할 수 있나요?

전적으로 브라우저에서 실행됩니다. PDF 엔진은 WebAssembly로 컴파일되고 파일은 VFS를 통해 이동하므로 문서는 기기를 떠나지 않습니다. 이는 사람들이 보통 줄이고 싶어 하는 문서 — 계약서, 명세서, 기록 — 에 가장 중요합니다.


함께 보기