핵심 요약: 수만 건의 스캔 PDF에 OCR을 적용할 때 병목은 거의 항상 「어떤 OCR 엔진을 쓰느냐」만이 아닙니다. 사전 분류·라우팅, 병렬 처리, 재개 가능한 작업 큐가 갖춰졌는지가 관건입니다. GUI로 파일을 하나씩 처리하면 1만 건에 몇 주가 걸리지만, 본문의 파이프라인을 8~16코어 VPS나 GPU 워커에서 돌리면 같은 규모를 몇 시간~하루 이틀로 압축할 수 있습니다——「빠른 선별 → 정밀 OCR → 불량 페이지 격리」라는 엔지니어링 트레이드오프를 받아들이는 전제입니다.
이 글은 아카이브 디지털화, 법무 서류, 의료 보고서, 역사 논문, 기업 계약 스캔 등 1만~10만 건 이상의 파일을 다루는 시나리오를 대상으로 합니다. 키워드: 배치 OCR, 스캔 PDF 인식, ocrmypdf, PaddleOCR. 인식 결과를 RAG에 넣을 예정이라면 RAG PDF 파싱 모범 사례에서 가져오기 전 품질 게이트를 확인하세요——OCR은 파이프라인의 첫 단계일 뿐입니다.
2026년 8월 8일 기준 OCRmyPDF 문서, Tesseract, PaddleOCR 확인.
대량 스캔 PDF OCR이 끔찍하게 느린 이유
흔한 실패 패턴: 폴더를 데스크톱 도구에 넣고 CPU 15%, 팬 조용, 하룻밤에 200건. 원인은 다음이 겹칩니다:
- 직렬 처리——한 프로세스가 순서대로, 멀티코어는 놀고 있음.
- 사전 검사 없음——30%는 이미 텍스트 레이어가 있는데 전체 OCR 실행.
- 파일 단위 병렬만——800페이지 묶음이 워커 하나를 점유, 소형 파일은 시작 비용만 반복.
- 무거운 출력——매 페이지 이미지 재압축·폰트 임베딩.
- 체크포인트 없음——9,000번째에서 크래시, 처음부터 재시작.
수만 건 규모에서는 파이프라인 설계가 엔진 튜닝보다 한 자릿수 더 중요합니다. 가장 빠른 구현 경로부터, 확장 아키텍처 순으로 설명합니다.
0단계: 사전 라우팅——OCR이 필요 없는 파일은 건드리지 마세요
OCR 전에 디렉터리를 일괄 스캔(Python 멀티프로세싱 또는 find | parallel):
- PyMuPDF /
pdfinfo로 페이지별get_text()집계. 약 80자 이상 읽을 수 있는 페이지는text_layer로 태그, 출력에 복사하고 OCR 생략. - 암호화·손상 PDF는
quarantine/으로——큐 전체를 막지 않음. - 혼합 PDF는 페이지 단위 라우팅——대규모에서 가장 큰 시간 절약.
법무 프로젝트 사례: 4.2만 PDF 중 38%는 이미 텍스트 레이어, 12% 암호화——실제 OCR이 필요한 것은 약 50%. 엔진 선택 전에 총 시간이 절반으로 줄었습니다.
팁: CSV 매니페스트(경로, 페이지 수, 유형, 예상 OCR 페이지)를 출력하세요. 일정은 파일 수가 아니라 OCR 페이지 수로 잡으세요.
오늘 바로 돌릴 최단 경로(1천~5천 건)
8코어 Linux 또는 클라우드 VPS가 있다면:
ocrmypdf+ Tesseract 설치(중국어는chi_sim/chi_tra).GNU parallel또는xargs -P로 파일별 병렬. 동시성 ≈ CPU 코어 수 − 1.- 플래그:
--skip-text, 낮은--optimize, 각 ocrmypdf 내부는--jobs 1로 중첩 과부하 방지. - 로컬 SSD 임시 디렉터리에 쓰고, 배치 후
rsync로 객체 스토리지에——네트워크 마운트는 처리량을 죽입니다.
cat scan_only.txt | parallel -j 8 \
'ocrmypdf --skip-text --optimize 0 --language chi_sim+eng \
{} /data/ocr_out/{/.}.pdf'
Tesseract는 몇 분 안에 배포 가능. PaddleOCR은 복잡한 중국어에서 유리한 경우가 많음——저신뢰도 페이지 2차 패스에 쓰고 전체 재실행은 피하세요.
1만 건 이상 아키텍처: 큐, 워커, 재개
- 큐: Redis+RQ, Celery, 또는 클라우드 Batch. 작업 = PDF 하나 또는 페이지 범위.
- 상태 DB: SQLite/Postgres에
file_hash, 상태, 재시도, 엔진 버전. - 스케일 아웃: CPU 바운드 OCR에서는 여러 중형 VPS가 거대 단일 머신보다 나은 경우가 많음.
- 페이지 단위 병렬:
pdftoppm→ 페이지 큐 → 200페이지 이상 묶음은 텍스트 레이어 병합. - GPU 풀: PaddleOCR/Surya를 별도 워커에. 언어·레이아웃별 라우팅.
처음부터 Kubernetes는 필요 없습니다. 많은 팀이 2~4대 VPS 워커에서 Docker Compose + Redis를 운영합니다: 한 대는 큐·메타데이터, 나머지는 OCR 전용.
도구 비교: 속도, 중국어, 검색 가능 PDF
| 스택 | 적합 | 처리량 | 주의 |
|---|---|---|---|
| OCRmyPDF + Tesseract | 라틴 문자 위주, 검색 가능 PDF | CPU 친화적 | 복잡한 중국어 레이아웃에 약함 |
| PaddleOCR 자체 호스팅 | 중국어/혼합 문서, 표 | GPU에서 페이지당 빠름 | PDF 텍스트 레이어 병합은 직접 |
| 상용 API | 컴플라이언스, 운영 부담 없음 | 탄력적 | 10만 페이지 비용 |
가장 빠름 ≠ 가장 저렴: 대표 200건으로 정확도 × 초/페이지 × 가격을 벤치마크한 뒤 결정하세요.
추가 30~50% 속도: 실전 팁
- 600 DPI 원본이면 300 DPI 렌더링 시도——계약서에는 종종 충분.
- OpenCV로 노이즈 제거·이진화(깨끗한 흑백 스캔).
- 최소 언어 팩만 로드.
- 픽셀 분산으로 빈 페이지·도장 페이지 건너뛰기.
- 검색만 필요하면
.txt/.jsonl보내기. PDF/A는 아카이브 계층만. - 클라우드 VM에서
TMPDIR을 로컬 NVMe로.
속도와 품질을 함께 잡기
배치 후: 0.5% 샘플링으로 사람이 읽거나 CER 확인. ID 밀집 페이지는 정규식 검증. 저신뢰도 페이지 재큐잉. 검색 인덱스에 나쁜 OCR을 넣는 비용이 2차 엔진 패스보다 큽니다. 아카이브 프로젝트는 감사 로그(누가, 언제, 어떤 엔진 버전)를 남기세요.
대략 계산: 5만 OCR 페이지
Tesseract 중간값 약 5초/페이지: 단일 스레드 약 69시간. 8코어 약 8~12시간. 8코어 워커 2대 약 4~6시간. GPU PaddleOCR 1~3초/페이지——카드 수에 거의 선형. 100페이지 자체 샘플로 pages_per_hour를 측정하세요.
복사 가능한 체크리스트
- 재귀 인벤토리 + SHA256 중복 제거 매니페스트.
- 사전 검사:
text_layer/scan/mixed/encrypted. - 큐 등록(OCR 페이지 수로 균형).
--skip-text또는 페이지 라우팅으로 병렬 OCR.- 검색 가능 PDF 또는 사이드카 텍스트 + JSON 메타데이터.
- 샘플 QA + 저신뢰도 2차 처리.
ocr_engine_version과 함께 아카이브(향후 재실행용).
RAG 하류에서는 페이지 유형을 메타데이터에 유지하세요. 긴 컨텍스트 비용은 Context Caching 비용 가이드도 참고하세요.
마지막 한 줄
수만 건 스캔에 만능 해법은 없지만 반복 가능한 최단 경로는 있습니다: 사전 검사로 불필요 OCR 절반 감소 → 큐로 크래시 복구 → 워커로 CPU/GPU 포화 → QA로 불량 페이지 차단. 파이프라인을 먼저 안정화하고, 엔진은 그다음에 조정하세요.
배치 OCR이 CPU를 포화시키나요? 클라우드에서 워커를 돌리세요
수만 페이지는 전형적인 배치 연산——노트북은 72시간 풀로드를 싫어하지만, Linux VPS나 GPU 워커에서는 수평 확장과 재개가 가능합니다. Cloud Mac에서 스크립트를 디버그하고, 무거운 OCR은 큐 뒤 노드에 맡기세요. VPSSpark는 디지털화·지식베이스 구축용 클라우드 개발 환경과 VPS를 제공합니다.