---
title: "엡스타인 아카이브 PDF에서 base64를 CNN으로 복원한 삽질기 — OCR은 쓸모없었음"
published: 2026-02-07T21:57:16.000Z
canonical: https://jeff.news/article/556
---
# 엡스타인 아카이브 PDF에서 base64를 CNN으로 복원한 삽질기 — OCR은 쓸모없었음

DOJ 엡스타인 아카이브 PDF 이미지에 남아있는 base64 텍스트를 복원해 원본 PDF를 추출한 기술적 여정. OCR, KMeans 클러스터링 모두 실패하고 CNN으로 해결했지만 최종 보스는 'l' vs '1' 구분이었음.

## PDF에서 base64를 추출하라

- 미국 법무부(DOJ)의 엡스타인 아카이브 PDF에서 **검열되지 않은 평문 base64 데이터**가 이미지 안에 남아있는 걸 발견한 저자가, 이걸 실제로 복원해서 원본 PDF 파일(DBC12)을 추출하는 데 성공함
- 결과물 자체는 "대단한 폭로"는 아니고, 엡스타인과 동료들의 금융 유착 관계를 보여주는 문서 하나. 하지만 기술적 과정이 진짜 볼만함

## OCR은 base64에 쓸모없음

- OCR이 LLM처럼 환각(hallucination)은 안 하지만, **바이트 단위 정확도가 필요한 작업에는 완전히 부적합**함. 인식한 문자를 "의미 있는 단어"로 조합하려는 휴리스틱이 base64 같은 무의미한 문자열에서는 오히려 독이 됨
- Tesseract에 휴리스틱 끄는 옵션이 있다고는 하는데 실측 효과 없었음. **Adobe Acrobat OCR은 그냥 끔찍함** (저자 원문 그대로)
- 아이러니하게도 모든 OCR 엔진이 고정폭(monospace) 폰트보다 **가변폭(proportional) 폰트**를 더 잘 인식함. 대부분의 학습 데이터가 가변폭이라서

## KMeans 클러스터링 시도 → 실패

- base64 알파벳이 64개(+패딩 =)니까 k=64로 KMeans 클러스터링하면 되지 않을까? 이론적으로는 맞는데, **입력 이미지에서 문자를 정확하게 잘라내는 게 불가능**에 가까웠음
- 직접 Courier New로 시드 버킷을 만들어서 매칭하는 것도 시도. 하지만 모노스페이스 폰트인데도 해상도 때문에 인접 문자 픽셀이 침범하는 문제 발생. O에서 오른쪽 1픽셀만 잘리면 C가 되는 수준

## CNN이 진짜 마법이었음

- 결국 **CNN(합성곱 신경망)**을 학습시킴. base64 데이터 2줄만 수동 타이핑해서 ground truth로 쓰고 학습시켰더니, 대부분의 문자를 정확히 인식함
- 페이지별 정렬 그리드 드리프트 문제는, "이 이미지들은 스캔이 아니라 디지털 렌더링이니까 첫 페이지 그리드를 그냥 재사용하면 된다"는 깨달음으로 해결

> [!IMPORTANT]
> 최종 보스는 **'l'(소문자 L) vs '1'(숫자 1)** 구분. 차이가 2~3픽셀에 불과하고, ClearType 서브픽셀 힌팅이 OpenCV 렌더링과 달라서 CNN도 계속 혼동함. 결국 학습 데이터에서 저자 자신이 1과 l을 잘못 라벨링한 걸 발견하고 수정하니까 복원 성공

- 같은 base64 내용이 다른 아카이브 문서(EFTA02154109)에도 있었는데, 미묘하게 다른 렌더링 덕분에 교차 검증이 가능했음
- 코드는 GitHub에 공개했지만, fish 셸 스크립트 + parallel + WSL 의존성이 섞여있어서 이식성은... 저자도 인정하는 부분
- 다음 목표는 더 많은 base64 첨부파일 추출이지만, 나머지는 전부 **가변폭 폰트**라서 이 방법을 그대로 쓸 수 없다는 게 함정

## 핵심 포인트

- OCR은 base64 같은 무의미한 문자열에 부적합 — 단어 조합 휴리스틱이 방해
- KMeans 클러스터링은 문자 경계 슬라이싱 불완전으로 실패
- CNN이 2줄의 ground truth만으로 대부분 문자를 인식
- 최종 문제: 저자 자신이 'l'과 '1'을 잘못 라벨링한 학습 데이터

## 인사이트

기술적 삽질기의 정석. OCR→데이터사이언스→딥러닝으로 점진적으로 접근하는 과정과, 결국 인간 에러가 마지막 장벽이었다는 반전이 교훈적임.
