← 모두의 툴

PDF OCR가 페이지마다 다르게 동작하는 원리

가이드 · 2026.08.20 최종 확인

같은 PDF 파일 안에서도 어떤 페이지는 순식간에 텍스트가 추출되고, 어떤 페이지는 한참을 기다려야 결과가 나옵니다. "OCR 도구가 왜 이렇게 들쭉날쭉하지?"라고 생각했다면, 그건 버그가 아니라 설계입니다. PDF 문서는 페이지마다 만들어진 방식이 다를 수 있고, 좋은 OCR 도구는 그 차이를 페이지 단위로 감지해서 필요한 페이지에만 무거운 연산을 씁니다. 이 글은 그 판별이 실제로 어떤 기준으로, 어느 시점에 이루어지는지 코드 레벨에서 짚어봅니다.

1. PDF는 원래 "표지는 디지털, 본문은 스캔"인 경우가 흔하다

계약서, 공문서, 논문 등은 워드프로세서로 작성한 표지·서명란 뒤에 팩스나 스캐너로 받은 본문이 이어 붙는 경우가 매우 흔합니다. 이런 파일에서 첫 페이지 하나만 보고 "이 PDF는 텍스트 PDF다" 또는 "이 PDF는 스캔본이다"라고 문서 전체를 한 번에 판정해버리면, 실제로는 텍스트가 있는데도 불필요하게 전체를 OCR 돌리거나, 반대로 스캔된 본문을 텍스트 추출이라며 빈 문자열을 반환하는 오류가 생깁니다. 그래서 PDF OCR 텍스트 추출기는 문서 단위가 아니라 페이지 단위로 판단을 내리도록 만들어져 있습니다.

2. 판별 기준: "텍스트 항목 5개 초과"라는 문턱값

브라우저에서 PDF를 읽는 PDF.js 라이브러리는 각 페이지 객체에서 getTextContent()를 호출하면 그 페이지에 내장된 텍스트 조각(글자·단어 단위 아이템) 배열을 돌려줍니다. 텍스트 레이어가 있는 정상 PDF라면 문장 하나만 있어도 수십 개의 아이템이 나오지만, 순수 스캔 이미지 PDF는 텍스트 레이어 자체가 없으므로 이 배열이 비어있거나 아주 적은 수(워터마크, 페이지 번호 등 우연히 심어진 텍스트 조각)만 나옵니다. 도구는 이 배열의 길이가 5개를 초과하는지를 기준으로 "이 페이지는 텍스트 레이어가 있다"고 판단합니다.

실제 코드 흐름 (pdf-ocr.html): 페이지 배열을 순회하며 각 페이지마다 const tc = await pg.getTextContent(); if (tc.items.length > 5) 조건으로 분기합니다. 참이면 tc.items.map(item => item.str).join(' ')로 즉시 텍스트를 이어붙이고, 거짓이면 그 페이지만 캔버스에 2배 스케일로 렌더링한 뒤 Tesseract.js에 넘겨 OCR을 수행합니다. 이 판별과 분기가 페이지마다 독립적으로 반복됩니다.

3. 왜 "5개"인가 — 임계값이 하는 역할

임계값을 0으로 두면(즉 텍스트 아이템이 하나라도 있으면 텍스트 PDF로 간주) 스캐너가 삽입한 페이지 번호 도장, OCR 소프트웨어가 자동으로 얹어놓은 숨은 텍스트 레이어 한두 조각 때문에 실제로는 이미지뿐인 페이지가 "텍스트 있음"으로 오판정될 위험이 있습니다. 5개라는 여유값은 이런 노이즈성 텍스트 조각을 걸러내고, 실제 문단·문장이 존재하는 페이지만 "텍스트 레이어 있음"으로 잡아내기 위한 안전장치입니다. 다만 이 값이 고정되어 있으므로, 짧은 제목 한 줄만 있는 표지 페이지는 아이템 수가 5개를 넘지 못해 OCR로 넘어갈 수 있다는 점도 이 구조에서 나오는 자연스러운 한계입니다.

4. 혼합 문서 처리 예시

10페이지짜리 문서에서 1페이지는 워드로 작성한 표지, 2~8페이지는 스캔된 본문, 9~10페이지는 다시 디지털로 작성한 부록이라고 가정하면 처리 흐름은 다음과 같습니다.

페이지getTextContent 아이템 수판정처리 방식
1 (표지)42개텍스트 있음즉시 텍스트 추출
2~8 (스캔 본문)0~2개텍스트 없음2배 렌더링 + Tesseract OCR
9~10 (부록)30개 이상텍스트 있음즉시 텍스트 추출

이 경우 실제 OCR 연산은 2~8페이지 7장에만 발생하고, 나머지 3장은 즉시 처리됩니다. 처리 시간이 페이지 수에 균등 비례하지 않고 "스캔 페이지 수"에만 비례하는 이유가 여기에 있습니다.

5. 사용자 입장에서 기억할 것

자주 묻는 질문

Q. 한 페이지 안에 텍스트와 이미지가 섞여 있으면 어떻게 되나요?

해당 페이지의 getTextContent() 아이템 수가 5개를 넘으면 텍스트 레이어가 있는 것으로 간주해 즉시 추출합니다. 이 경우 이미지 안에 있는 글자(캡션 이미지 등)는 OCR을 거치지 않으므로 추출되지 않을 수 있습니다.

Q. 문서 전체가 스캔본인지 미리 알 수 있는 방법이 있나요?

별도 확인 기능은 없지만, 파일을 열었을 때 PDF 뷰어에서 텍스트를 드래그해 선택할 수 있는지 시험해보면 대략 짐작할 수 있습니다. 선택이 전혀 안 된다면 스캔본일 가능성이 높습니다.

Q. 임계값 5개는 사용자가 바꿀 수 있나요?

현재는 고정값이며 UI에서 조정하는 옵션은 제공하지 않습니다. 표지처럼 텍스트가 극히 적은 페이지가 OCR로 넘어가는 경우가 있다는 점만 참고하세요.

Q. 처리 속도를 높이려면 어떻게 하나요?

페이지 범위를 스캔 구간으로 좁혀서 지정하면 텍스트 페이지를 불필요하게 순회하는 시간을 줄일 수 있고, OCR이 필요한 페이지 수 자체를 줄이는 것이 가장 효과적입니다.