Skip to content

PDF Oxide 시작하기 (Clojure)

PDF Oxide는 텍스트 추출 기능을 기본 내장한 가장 빠른 PDF 툴킷으로, 평균 0.8ms에 3,830개 PDF에서 100% 통과율을 기록합니다. Clojure 바인딩은 단일 JNI 네이티브 브리지를 담당하는 성숙한 fyi.oxide:pdf-oxide Java 바인딩 위에 얹은 관용적이고 얇은 래퍼입니다. 네이티브 코드를 전혀 추가하지 않으며, interop를 통해 Java 클래스를 호출하고 Clojure 친화적인 값을 반환합니다 (java.util.List → 벡터, java.util.Optional → 값-또는-nil).

설치

deps.edn에 Java 바인딩을 추가하세요. Clojure 네임스페이스(pdf_oxide.core)는 여러분의 소스 트리에 위치하며 이를 감쌉니다:

{:deps {fyi.oxide/pdf-oxide {:mvn/version "0.3.69"}}}

핸들 타입(Pdf, PdfDocument, DocumentEditor)은 AutoCloseable이므로, 결정적인 정리를 위해 with-open을 사용하세요.

빠른 시작

Markdown에서 PDF를 만들고, 다시 열어, 텍스트를 추출합니다. 각 단계는 평범한 Clojure 값을 반환합니다.

(require '[pdf-oxide.core :as pdf])

(with-open [p (pdf/from-markdown "# Hello\n\nbody\n")
            d (pdf/open (pdf/save p))]
  (println "pages:   " (pdf/page-count d))
  (println "producer:" (or (pdf/producer d) "(none)"))
  (println (pdf/extract-text d 0)))

PDF 열기

pdf/open은 바이트 배열 또는 파일시스템 경로 문자열을 받으며, 암호화된 문서를 위한 선택적 비밀번호를 받을 수 있습니다.

(require '[pdf-oxide.core :as pdf])

;; 경로에서
(with-open [d (pdf/open "research-paper.pdf")]
  (println "pages:" (pdf/page-count d)))

;; 바이트에서 (예: S3 또는 HTTP에서 다운로드)
(with-open [d (pdf/open pdf-bytes)]
  (println (pdf/extract-text d 0)))

;; 암호화된 문서
(with-open [d (pdf/open "confidential.pdf" "secret")]
  (println (pdf/extract-text d 0)))

연 후에 인증할 수도 있습니다:

(with-open [d (pdf/open "confidential.pdf")]
  (when (pdf/authenticate d "secret")
    (println (pdf/extract-text d 0))))

텍스트 추출

0부터 시작하는 인덱스로 임의의 페이지에서 일반 텍스트를 추출합니다.

(require '[pdf-oxide.core :as pdf])

(with-open [d (pdf/open "report.pdf")]
  ;; 단일 페이지
  (println (pdf/extract-text d 0))

  ;; 모든 페이지
  (doseq [i (range (pdf/page-count d))]
    (println "--- Page" (inc i) "---")
    (println (pdf/extract-text d i))))

페이지 요소

pdf/pagePdfPage를 반환합니다. 이로부터 단어, 줄, 문자, 표, 이미지, 주석을 각각 Clojure 벡터로 가져올 수 있습니다. 단어/줄/문자 객체는 interop를 통해 .text.bbox를 노출합니다.

(require '[pdf-oxide.core :as pdf])

(with-open [d (pdf/open "paper.pdf")]
  (let [pg (pdf/page d 0)]
    (println "page width:" (.width pg))

    ;; 경계 상자와 함께 표시되는 단어들
    (doseq [w (take 8 (pdf/words pg))]
      (println "  " (.text w) "@" (.bbox w)))

    ;; 그 밖의 요소 벡터
    (println "lines:      " (count (pdf/lines pg)))
    (println "chars:      " (count (pdf/chars pg)))
    (println "tables:     " (count (pdf/tables pg)))
    (println "images:     " (count (pdf/images pg)))
    (println "annotations:" (count (pdf/annotations pg)))

    ;; 페이지 전체의 일반 텍스트, 또는 잘라낸 영역(BBox)
    (println (pdf/page-text pg))))

추출을 특정 영역으로 제한하려면 fyi.oxide.pdf.geometry.BBox를 전달하세요:

(import '[fyi.oxide.pdf.geometry BBox])

(with-open [d (pdf/open "paper.pdf")]
  (let [pg (pdf/page d 0)]
    (println (pdf/page-text pg (BBox. 0.0 0.0 1000.0 1000.0)))))

Markdown 및 HTML 변환

문서 전체 또는 단일 페이지를 Markdown이나 HTML로 변환합니다.

(require '[pdf-oxide.core :as pdf])

(with-open [d (pdf/open "paper.pdf")]
  ;; 문서 전체
  (println (pdf/to-markdown d))
  (println (pdf/to-html d))

  ;; 단일 페이지 (0부터 시작)
  (println (pdf/to-markdown d 0))
  (println (pdf/to-html d 0)))

더 풍부한 구조가 필요하면, pdf/extract-structured가 페이지의 구조화된 요소 트리를 반환합니다:

(with-open [d (pdf/open "paper.pdf")]
  (println (pdf/extract-structured d 0)))

검색

pdf/search는 문서 전체를 스캔하여 일치 객체의 벡터를 반환합니다. 각 일치 항목은 interop를 통해 .text를 노출합니다.

(require '[pdf-oxide.core :as pdf])

(with-open [d (pdf/open "manual.pdf")]
  (doseq [m (pdf/search d "configuration")]
    (println (.text m))))

렌더링

페이지를 PNG 바이트 배열로 렌더링하며, 원하는 DPI를 선택할 수도 있습니다.

(require '[pdf-oxide.core :as pdf]
         '[clojure.java.io :as io])

(with-open [d (pdf/open "paper.pdf")]
  ;; 기본 DPI
  (io/copy (pdf/render d 0) (io/file "page-0.png"))

  ;; 명시적 DPI
  (io/copy (pdf/render d 0 150) (io/file "page-0@150.png")))

생성

Pdf 타입은 팩토리 함수를 제공합니다. pdf/save는 빌드된 Pdf를 바이트 배열로 직렬화합니다.

(require '[pdf-oxide.core :as pdf]
         '[clojure.java.io :as io])

;; Markdown에서
(with-open [p (pdf/from-markdown "# Hello World\n\nThis is a PDF.")]
  (io/copy (pdf/save p) (io/file "output.pdf")))

;; HTML에서
(with-open [p (pdf/from-html "<h1>Invoice</h1><p>Amount: $42</p>")]
  (io/copy (pdf/save p) (io/file "invoice.pdf")))

편집 및 교정(Redaction)

pdf/editor는 구조적 편집을 위해 DocumentEditor를 (바이트 배열 또는 경로에서) 엽니다. 메타데이터를 지우고, 교정할 영역을 표시하고, 이를 파괴적으로 적용한 뒤 pdf/editor-save로 직렬화하세요.

(require '[pdf-oxide.core :as pdf]
         '[clojure.java.io :as io])
(import '[fyi.oxide.pdf.geometry BBox])

(with-open [ed (pdf/editor "form.pdf")]
  (pdf/scrub-metadata ed)
  (pdf/add-redaction ed 0 (BBox. 10.0 10.0 50.0 20.0))
  (pdf/apply-redactions ed)
  (io/copy (pdf/editor-save ed) (io/file "redacted.pdf")))

메타데이터 및 수명 주기

pdf/producerpdf/creator는 문서 메타데이터를 값으로 반환하며, 없을 때는 nil을 반환합니다 (java.util.Optional은 알아서 풀어줍니다). with-open을 우선 사용하세요. pdf/closepdf/open?은 수동 수명 주기 관리를 위한 탈출구입니다.

(require '[pdf-oxide.core :as pdf])

(let [d (pdf/open "paper.pdf")]
  (println "open?    " (pdf/open? d))
  (println "producer:" (or (pdf/producer d) "(none)"))
  (println "creator: " (or (pdf/creator d) "(none)"))
  (pdf/close d)
  (println "open?    " (pdf/open? d)))

다음 단계

  • Java 시작하기 – 이 래퍼가 기반으로 삼는 Java 바인딩
  • 텍스트 추출 – 상세한 추출 옵션과 레시피
  • PDF 생성 – 메타데이터와 스타일링을 포함한 고급 생성
  • 편집 – 기존 PDF 수정, 주석, 교정