서론: PDF 파싱의 고충
개발자라면 PDF 문서 처리는 피할 수 없는 요구사항입니다 — 청구서 파싱, 계약서 추출, 논문 크롤링, 데이터 아카이빙 등 거의 모든 백엔드 프로젝트에서 마주치게 되죠. 하지만 PDF 파싱은 오랫동안 골칫거리였습니다:
- OCR 서비스 비용 부담: 클라우드 OCR API 호출 시 페이지당 수백 원,량이 많아지면 비용이 급증합니다
- 오픈소스 솔루션 느림: PyMuPDF4LLM은 문서 200건을 17초나 처리하고, MarkItDown은 16초가 소요됩니다
- 포맷 손실: 기존 추출 도구는 순수 텍스트만 내보내서 제목 계층, 표 구조, 코드 블록이 모두 사라집니다
- 스마트 라우팅 부재: 스캔본과 원본 텍스트 PDF를 자동으로 구분하지 못해 OCR이 필요 없는 문서에도 OCR을 거치게 됩니다
2026년 7월, 유명 웹 크롤링 플랫폼 Firecrawl이 Rust 기반 PDF 파싱 라이브러리 pdf-inspector를 오픈소스로 공개했고, 출시 몇 주 만에 7,900개 이상의 Star를 획득하며 GitHub Trending 일간 순위 3위에 올랐습니다. 이 라이브러리는 200ms 이내에 로컬 PDF 분류와 텍스트 추출을 완료하고, OCR이나 외부 서비스 없이 자동으로 포맷이 preserved 된 마크다운을 출력해 줍니다.
오늘은 이 프로젝트를 직접 깊이 살펴보면서, 어떻게 주류 솔루션들을 성능 면에서 압도하는지 확인해 보겠습니다.
pdf-inspector란?
pdf-inspector는 Firecrawl 팀이 Rust로 작성한 PDF 분류 및 텍스트 추출 라이브러리로, 핵심 기능은 다음과 같습니다:
- 스마트 분류 — 10-50ms 안에 PDF 유형 감지: 원본 텍스트(TextBased), 스캔본(Scanned), 이미지형(ImageBased) 또는 혼합형(Mixed). 신뢰도와 페이지별 OCR 라우팅 제안을 반환합니다
- 텍스트 추출 — 위치 인식 텍스트 추출. 폰트 정보, X/Y 좌표, 자동 멀티컬럼 읽기 순서 포함
- 마크다운 변환 — H1-H4 제목, 목록, 코드 블록(등폭 폰트 감지), 표, 볼드/이탤릭, URL 링크, 페이지 구분선을 자동 인식
- 표 감지 — 듀얼 모드 표 감지(PDF 드로잉 명령 기반 사각형 감지 + 텍스트 정렬 기반 휴리스틱 감지). 재무제표와 페이지 넘나드는 표를 완벽하게 처리
- CID 폰트 지원 — ToUnicode CMap 디코딩, Type0/Identity-H 폰트, UTF-16BE, UTF-8 및 Latin-1 인코딩 지원
- 다중 언어 바인딩 — Python, Node.js, 브라우저 WebAssembly 바인딩 제공
왜 Rust일까? Rust의 제로 코스트 추상화와 메모리 안전성 덕분에 pdf-inspector는 ML 모델이나 외부 서비스 의존 없이 극한의 파싱 속도를 실현했습니다. 외부 의존은 단 하나뿐입니다: lopdf(Rust PDF 파싱 라이브러리).
성능 비교
Apple M4 Pro 기준 공식 벤치마크 결과입니다(200개 문서, opendataloader-bench 코퍼스):
| 엔진 | 종합 점수 | 읽기 순서 | 표 인식 | 제목 인식 | 200문서 소요 시간 |
|---|---|---|---|---|---|
| pdf-inspector | 0.875 | 0.915 | 0.814 | 0.788 | 0.470초 |
| LiteParse | 0.873 | 0.913 | 0.693 | 0.811 | 0.750초 |
| OpenDataLoader | 0.831 | 0.902 | 0.489 | 0.739 | 2.569초 |
| PyMuPDF4LLM | 0.735 | 0.886 | 0.401 | 0.424 | 17.169초 |
| MarkItDown | 0.589 | 0.844 | 0.273 | 0.000 | 16.117초 |
pdf-inspector는 종합 점수, 읽기 순서, 표 인식, 속도에서 모두압도적 1위이며, 소요 시간은 PyMuPDF4LLM의 1/36, MarkItDown의 1/34에 불과합니다.
설치
pdf-inspector는 Rust, Python, Node.js, 브라우저 환경까지 다양한 설치 방법을 지원합니다.
Rust(네이티브)
Cargo.toml에 의존성 추가:
[dependencies]
pdf-inspector = "0.2"
또는 cargo CLI로 설치:
cargo add pdf-inspector
Python
pdf-inspector는 maturin을 통해 Python 바인딩을 제공합니다:
pip install maturin
git clone https://github.com/firecrawl/pdf-inspector.git
cd pdf-inspector
maturin develop --release
💡 참고: 현재 PDF-inspector는 아직 PyPI에 등록되지 않았습니다. 소스 코드 컴파일을 통해 설치해야 합니다. Firecrawl 팀은 안정화 이후 PyPI 패키지 배포를 계획 중입니다.
Node.js
npm install @firecrawl/pdf-inspector
브라우저 WebAssembly
npm install @firecrawl/pdf-inspector-wasm
Wasm 버전은 완전한 Rust 파서를 브라우저에 내장하여, 서버 왕복 없이 Web Worker에서 실행할 수 있습니다.
빠르게 시작하기
Python 예시
설치 완료 후 사용법은 매우 간단합니다 — 함수 하나만 호출하면 됩니다:
import pdf_inspector
# 단일 PDF 파일 처리
result = pdf_inspector.process_pdf("document.pdf")
# PDF 유형 분류 확인
print(f"PDF 유형: {result.pdf_type}")
# 출력: "text_based", "scanned", "image_based", 또는 "mixed"
# 마크다운 출력 확인
if result.markdown:
print(result.markdown)
이게 끝입니다. 코드 한 줄로 분류 + 추출 + 마크다운 변환이 한 번에 완료됩니다.
Node.js 예시
const { processPdf } = require('@firecrawl/pdf-inspector');
const fs = require('fs');
async function analyzePdf(filePath) {
const pdfBuffer = fs.readFileSync(filePath);
const result = await processPdf(pdfBuffer);
console.log('PDF 유형:', result.pdfType);
console.log('신뢰도:', result.confidence);
console.log('--- 마크다운 출력 ---');
console.log(result.markdown);
}
analyzePdf('report.pdf');
Rust 네이티브 예시
use pdf_inspector::{PdfInspector, ProcessPdfResult};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let inspector = PdfInspector::new();
let result: ProcessPdfResult = inspector.process_pdf_path("document.pdf")?;
println!("PDF 유형: {:?}", result.pdf_type);
println!("신뢰도: {:.2}", result.confidence);
if let Some(markdown) = result.markdown {
println!("Markdown:\n{}", markdown);
}
Ok(())
}
핵심 기능 상세
1. 스마트 분류: 불필요한 OCR 오버헤드 방지
pdf-inspector의 가장 실용적인 기능 중 하나는자동 분류입니다. PDF 콘텐츠 스트림을 샘플링하여 10-50ms 안에 문서 유형을 판별합니다:
| 유형 | 설명 | 권장 처리 전략 |
|---|---|---|
text_based |
원본 텍스트 PDF, 추출 가능한 텍스트 콘텐츠 스트림 포함 | pdf-inspector로 직접 추출, OCR 스킵 |
scanned |
스캔본(이미지형 페이지) | OCR 서비스 필요 |
image_based |
이미지 중심 PDF(스크린샷 모음 등) | OCR 또는 이미지 처리 필요 |
mixed |
혼합형(일부 페이지는 텍스트, 일부는 스캔본) | 페이지별 결정: 텍스트 페이지는 직접 추출, 스캔 페이지는 OCR 호출 |
실전 시나리오: 스마트 PDF 처리 파이프라인 구축
import pdf_inspector
# 자체 OCR 함수가 있다고 가정
def smart_pdf_pipeline(pdf_path, ocr_function):
result = pdf_inspector.process_pdf(pdf_path)
if result.pdf_type == "text_based":
# 원본 텍스트, 직접 추출 — 빠르고, 무료이며, 정확함
print("✅ 원본 텍스트 PDF, 직접 추출")
return result.markdown
elif result.pdf_type == "scanned":
# 스캔본, OCR 호출
print("🔍 스캔본 PDF, OCR 호출")
return ocr_function(pdf_path)
elif result.pdf_type == "mixed":
# 혼합형 — 페이지별 처리
print("📄 혼합형 PDF, 페이지별 라우팅")
pages = []
for page_info in result.page_results:
if page_info.needs_ocr:
pages.append(ocr_function_for_page(pdf_path, page_info.page_number))
else:
pages.append(page_info.markdown)
return "\n\n".join(pages)
else:
# 순수 이미지형, 텍스트 추출 불가
print("❌ 이미지형 PDF, 텍스트 추출 불가")
return None
이 파이프라인은 약 54%의 PDF(원본 텍스트형)에서 OCR을 완전히 생략할 수 있어, 처리 비용과 지연 시간을 크게 줄여줍니다.
2. 마크다운 변환: 문서 구조 보존
pdf-inspector의 마크다운 출력은 단순한 텍스트가 아닙니다 — 문서의 구조 정보를 지능적으로 인식하고 보존합니다:
- 제목 계층(H1-H4): 폰트 크기 비율로 자동 추론
- 목록: 글머리 기호 목록, 번호 목록, 알파벳 번호 목록 자동 인식
- 코드 블록: 등폭 폰트 감지를 통해 코드 블록으로 자동 마크업
- 표: 사각형 감지와 휴리스틱 감지 지원, 재무제표와 페이지 넘나드는 표 처리
- 볼드/이탤릭: 볼드와 이탤릭 포맷 보존
- URL 링크: 자동 인식하여 마크다운 링크 형식으로 변환
- 페이지 구분선:
---로 페이지 구분
실제 효과를 확인해 봅시다. 학술 논문 PDF가 있다고 가정해 보겠습니다:
# Deep Learning Approaches for Natural Language Processing
## 1. Introduction
Natural language processing (NLP) has seen remarkable progress in recent years...
### 1.1 Background
The transformer architecture, introduced by Vaswani et al., has become...
## 2. Methodology
| Model | BLEU Score | Training Time |
|-------|-----------|---------------|
| Transformer | 38.2 | 12 hours |
| BERT | 41.0 | 24 hours |
| GPT-4 | 45.7 | 72 hours |
## 3. Results
The experimental results demonstrate...
> **Note:** All experiments were conducted on...
제목 계층, 표, 인용 블록이 모두 그대로 보존되었습니다. 순수 텍스트만 내보내는 기존 PDF 추출 도구와는 차원이 다릅니다.
3. 멀티컬럼 및 읽기 순서 감지
많은 PDF(논문, 신문, 잡지 등)가 멀티컬럼 레이아웃을 사용합니다. pdf-inspector는 컬럼 구조를 자동 감지하고 올바른 읽기 순서로 추출합니다:
result = pdf_inspector.process_pdf("newspaper.pdf")
# pdf-inspector가 자동으로 2컬럼/3컬럼 레이아웃 감지
# 위에서 아래로, 왼쪽에서 오른쪽으로 올바른 순서로 출력
print(result.markdown)
동시에 RTL(오른쪽에서 왼쪽으로) 텍스트도 지원하여 아랍어, 히브리어 문서에 적합합니다.
4. CID 폰트 및 인코딩 문제 감지
중국어, 일본어, 한국어 PDF를 다룰 때 폰트 인코딩 문제가 자주 발생합니다. pdf-inspector는 ToUnicode CMap 디코딩을 지원하여 다음을 올바르게 처리합니다:
- Type0 / Identity-H 폰트
- UTF-16BE, UTF-8 및 Latin-1 인코딩
- 손상된 폰트 인코딩 자동 마킹
즉, 중일한 PDF를 처리할 때 어떤 페이지에 글자 깨짐 위험이 있는지 알려주므로, OCR 대체 여부를 미리 결정할 수 있습니다.
심화 실전: PDF 처리 서비스 구축
이제 pdf-inspector의 스마트 분류 기능을 통합한 완전한 PDF 처리 마이크로서비스를 구축해 보겠습니다.
시나리오: 문서 아카이빙 시스템
사내 기업 문서 아카이빙 시스템을 구축 중이고, 매일 수백 건의 PDF(계약서, 청구서, 보고서 등)를 처리해야 한다고 가정해 봅시다:
# pdf_service.py
import os
import json
from datetime import datetime
import pdf_inspector
class PdfProcessingService:
def __init__(self, output_dir="./processed"):
self.output_dir = output_dir
os.makedirs(output_dir, exist_ok=True)
def process_batch(self, pdf_files):
"""PDF 파일 배치 처리"""
results = []
for pdf_path in pdf_files:
result = self.process_single(pdf_path)
results.append(result)
return results
def process_single(self, pdf_path):
"""단일 PDF 파일 처리"""
filename = os.path.basename(pdf_path)
pdf_result = pdf_inspector.process_pdf(pdf_path)
# 메타정보 추출
metadata = {
"filename": filename,
"pdf_type": pdf_result.pdf_type,
"confidence": pdf_result.confidence,
"processed_at": datetime.now().isoformat(),
"pages_count": len(pdf_result.page_results) if hasattr(pdf_result, 'page_results') else 0,
"needs_ocr": pdf_result.pdf_type in ("scanned", "image_based"),
}
# 마크다운 출력 저장
if pdf_result.markdown:
md_filename = filename.replace(".pdf", ".md")
md_path = os.path.join(self.output_dir, md_filename)
with open(md_path, "w", encoding="utf-8") as f:
f.write(pdf_result.markdown)
metadata["markdown_path"] = md_path
# 메타정보 저장
meta_path = os.path.join(
self.output_dir,
filename.replace(".pdf", ".meta.json")
)
with open(meta_path, "w", encoding="utf-8") as f:
json.dump(metadata, f, ensure_ascii=False, indent=2)
return metadata
# 사용 예시
service = PdfProcessingService(output_dir="./output")
# 배치 처리
pdf_files = [
"contracts/contract_2026_001.pdf",
"invoices/invoice_aug_2026.pdf",
"reports/q2_financial_report.pdf",
]
results = service.process_batch(pdf_files)
for r in results:
status = "OCR 필요" if r["needs_ocr"] else "직접 추출 완료"
print(f"{r['filename']}: {r['pdf_type']} ({status})")
시나리오: LLM 문서 분석 파이프라인과 통합
pdf-inspector가 출력하는 고품질 마크다운은 LLM 분석에 바로 투입할 수 있습니다:
import pdf_inspector
# OpenAI 호환 API 사용 가정
from openai import OpenAI
def analyze_pdf_with_llm(pdf_path, prompt="이 문서의 주요 내용을 요약해 주세요"):
"""LLM으로 PDF 분석"""
# 1. pdf-inspector로 마크다운 추출
result = pdf_inspector.process_pdf(pdf_path)
if not result.markdown:
return "텍스트 콘텐츠를 추출할 수 없습니다. OCR이 필요할 수 있습니다."
# 2. 문서가 너무 길면 앞 8000자로 자르기
markdown_content = result.markdown[:8000]
# 3. LLM 호출 분석
client = OpenAI(api_key="YOUR_API_KEY")
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "당신은 문서 분석 도우미입니다."},
{"role": "user", "content": f"다음 문서 내용을 바탕으로 {prompt}:\n\n{markdown_content}"}
]
)
return response.choices[0].message.content
# 사용
summary = analyze_pdf_with_llm("annual_report.pdf", "핵심 재무 지표를 추출해 주세요")
print(summary)
이런 파이프라인은 RAG(검색 증강 생성) 시스템에서 특히 유용합니다 — pdf-inspector로 빠르게 구조화된 텍스트를 추출한 뒤, 벡터화하여 지식 베이스에 저장하면 됩니다.
다른 솔루션과의 비교
pdf-inspector vs PyMuPDF4LLM
| 항목 | pdf-inspector | PyMuPDF4LLM |
|---|---|---|
| 언어 | Rust | Python(C 바인딩) |
| 종합 점수 | 0.875 | 0.735 |
| 표 인식 | 0.814 | 0.401 |
| 속도(200문서) | 0.47초 | 17.169초 |
| 마크다운 구조 | ✅ 완벽 보존 | ⚠️ 부분 손실 |
| 스마트 분류 | ✅ 내장 | ❌ 없음 |
| 브라우저 Wasm | ✅ 지원 | ❌ 미지원 |
pdf-inspector vs MarkItDown(Microsoft)
| 항목 | pdf-inspector | MarkItDown |
|---|---|---|
| 종합 점수 | 0.875 | 0.589 |
| 제목 인식 | 0.788 | 0.000 |
| 속도(200문서) | 0.47초 | 16.117초 |
| 다중 언어 바인딩 | Python/Node/Wasm | Python |
| 전문성 | PDF 파싱 전문 | 범용 문서 변환 |
언제 pdf-inspector를 쓰고, 언제 OCR을 쓸까?
- pdf-inspector 사용: 원본 텍스트 PDF, 보고서, 논문, 계약서, 청구서 등 텍스트 콘텐츠 스트림이 있는 문서
- OCR 사용: 스캔본, 순수 이미지 PDF, 손글씨 문서
- 혼합 사용: 먼저 pdf-inspector로 분류 후, text_based는 직접 추출, scanned/image_based는 OCR 경로로 — 이것이 바로 pdf-inspector가 설계한 라우팅 전략입니다.
프로젝트 정보 및 커뮤니티
- GitHub: firecrawl/pdf-inspector
- Stars: 7,900+ (2026년 7월 출시, 급성장 중)
- License: Apache-2.0 (상업적 사용 가능)
- 언어: Rust
- 생태계: Firecrawl 제작(유명 웹 크롤링 플랫폼, firecrawl 크롤링 엔진도 오픈소스 공개)
설치 채널
| 플랫폼 | 설치 방법 |
|---|---|
| Rust | crates.io/crates/pdf-inspector |
| Python | 소스 컴파일(maturin develop --release) |
| Node.js | npm install @firecrawl/pdf-inspector |
| 브라우저 | npm install @firecrawl/pdf-inspector-wasm |
요약
pdf-inspector의 등장은 중요한 공백을 메웠습니다 — 가볍고, 빠르며, 로컬에서 동작하는 PDF 파싱 솔루션. ML 모델이 필요 없고, 외부 서비스가 필요 없으며, 순수 Rust 구현으로 높은 정확도를 유지하면서 동급 도구들을 훨씬 앞서는 속도를 실현했습니다.
핵심 장점 요약:
- 🚀 극한의 속도 — 200ms급 파싱, PyMuPDF4LLM 대비 36배 빠름
- 🧠 스마트 분류 — 텍스트/스캔/이미지형 PDF 자동 구분, OCR 라우팅 최적화
- 📐 구조 보존 — 제목, 표, 코드 블록, 목록을 마크다운으로 완벽 보존
- 🔒 순수 로컬 — 외부 의존 없음, API 호출 없음, 데이터가 머신 밖으로 나가지 않음
- 🌐 멀티 플랫폼 — Rust/Python/Node.js/브라우저 Wasm 전체 커버
문서 처리 파이프라인, RAG 시스템 또는 PDF 파싱이 필요한 애플리케이션을 구축 중이라면, pdf-inspector를 기술 스택에 추가해 볼 만한 가치가 있습니다. 특히 원본 텍스트 PDF 중심의 시나리오에서는 OCR 비용과 지연 시간을 대폭 절감할 수 있습니다.
🔗 관련 링크 - GitHub: firecrawl/pdf-inspector - Python 문서: docs/python.md - 벤치마크: opendataloader-bench - Firecrawl: firecrawl.dev