Files
PDFToMD/docs/ADR.md
T
김경종 7e985ae94a add files
2026-04-30 17:05:19 +09:00

5.6 KiB

Architecture Decision Records

철학

프로젝트의 핵심 가치관:

  • 정확한 수식 변환
  • 로컬 작동
  • 메모리 최적 사용
  • AI Agent가 탐색하기 쉬운 deterministic Markdown bundle
  • 원문 구조와 참조 관계 보존

ADR-001: Marker-first document parsing

결정: Marker를 기본 PDF parser로 사용한다.

이유:

  • Marker는 layout, OCR, reading order, table, figure, caption, heading을 포함한 문서 구조 추적에 적합하다.
  • 프로젝트 목표는 단순 텍스트 추출이 아니라 원문 논리 구조를 Markdown으로 재구성하는 것이다.

트레이드오프:

  • Marker 의존성 및 model weight 관리가 필요하다.
  • 배포 가능성이 생기면 GPL 및 model license 검토가 필요하다.

ADR-002: Nougat as formula-only parser

결정: Nougat은 전체 PDF parser가 아니라 수식 및 수학적 표현 parser로만 사용한다.

이유:

  • Nougat은 학술 문서의 수식/LaTeX 변환에 강점이 있다.
  • 전체 문서 구조는 Marker가 담당해야 reading order, 표, 그림, caption 경로가 일관된다.

트레이드오프:

  • Marker block과 Nougat 결과를 연결하는 handoff/fallback 계층이 필요하다.
  • Nougat 실패 시 Marker 원문 문자열을 fallback으로 사용해야 한다.

ADR-003: PyMuPDF page pre-analysis and chunk planning

결정: PyMuPDF를 페이지 수, 텍스트 레이어 품질, OCR 필요 여부, chunk 계획, 저수준 PDF 작업에 사용한다.

이유:

  • 무거운 parser 실행 전에 빠른 page-level 분석이 필요하다.
  • 혼합 PDF는 페이지별 OCR 개입 여부를 판단해야 한다.
  • 긴 PDF는 20페이지 목표 chunk로 나누되 논리 block 경계를 고려해야 한다.

트레이드오프:

  • PyMuPDF 분석 결과와 Marker layout 결과를 조정하는 adapter가 필요하다.

ADR-004: Single Python 3.11 environment

결정: repo-local 단일 Python 3.11 venv를 사용한다.

이유:

  • 개발과 실행 경로를 단순화한다.
  • Marker와 Nougat은 명시적 dependency pin을 두면 하나의 환경에서 함께 동작한다.

검증된 주요 pin:

  • torch==2.7.1+cu126
  • torchvision==0.22.1+cu126
  • marker-pdf==1.10.2
  • nougat-ocr==0.1.17
  • transformers==4.57.6
  • albumentations==1.3.1
  • pypdfium2==4.30.0
  • opencv-python-headless==4.11.0.86
  • Pillow==10.4.0
  • fsspec==2026.2.0

트레이드오프:

  • Nougat의 느슨한 dependency bounds 때문에 requirements pin을 엄격히 유지해야 한다.
  • 최신 PyTorch를 무조건 사용할 수 없다. GTX 1070 Ti sm_61 지원 때문에 torch==2.7.1+cu126을 사용한다.

ADR-005: Markdown bundle output without document sidecars by default

결정: 기본 출력은 chunk Markdown 파일과 asset directory로 제한한다.

이유:

  • AI Agent가 읽고 탐색하기 쉬운 산출물을 우선한다.
  • 별도 sidecar 산출물은 사용자가 명시적으로 요청하기 전까지 범위를 넓히지 않는다.

트레이드오프:

  • 변환 diagnostics를 문서 출력과 분리해야 한다.
  • runtime log/state/cache는 허용하되 문서 output contract와 구분해야 한다.

ADR-006: Focused quality assertions over full snapshots

결정: 전체 Markdown snapshot 비교보다 focused assertions를 우선한다.

이유:

  • PDF 변환 결과는 줄바꿈, spacing, parser version에 민감하다.
  • 품질 핵심은 heading, 수식, 표, 이미지, caption, 링크, chunk integrity, 예외 여부다.

트레이드오프:

  • 테스트 설계가 더 세분화된다.
  • sample metadata mapping이 필요하다.

ADR-007: Runtime fallback policy

결정:

  • explicit --runtime cuda 또는 --device cuda는 CUDA 실패 시 fail-fast.
  • --runtime auto는 경고 후 CPU fallback 허용.
  • GPU OOM은 가능한 경우 batch/page 단위를 줄여 재시도.

이유:

  • 사용자가 CUDA를 명시한 경우 조용한 CPU 전환은 예측 불가능한 지연을 만든다.
  • auto mode는 유연한 실행을 제공해야 한다.

트레이드오프:

  • runtime state와 오류 reporting이 필요하다.

ADR-008: Future PyQt UI as thin client

결정: PyQt UI는 변환 엔진을 직접 구현하지 않고 CLI/라이브러리 API를 호출하는 thin client로 둔다.

이유:

  • 1차 목표는 CLI/library 엔진 안정화다.
  • UI와 core engine의 책임을 분리해야 테스트와 유지보수가 쉽다.

트레이드오프:

  • UI 설계 전에 core API contract를 안정화해야 한다.

ADR-009: File-based planner/generator/evaluator Harness

결정: 장기 작업은 planner -> generator -> evaluator 역할 분리와 파일 기반 handoff를 사용하는 Harness workflow로 관리한다.

이유:

  • PDF 변환 엔진은 parser, OCR, 수식, 표, 그림, runtime, 테스트가 얽힌 장기 작업이므로 단일 대화에서 일관성을 유지하기 어렵다.
  • 작은 self-contained phase step은 새 agent가 fresh context로 작업을 이어받기 쉽게 한다.
  • 구현 agent와 평가 agent를 분리하면 자기 평가 편향을 줄이고, hard threshold 기반 검증을 강제할 수 있다.
  • PLAN.md, PROGRESS.md, phases/ 파일을 통한 handoff는 대화 밖에서도 현재 상태를 재구성할 수 있게 한다.

트레이드오프:

  • 각 step마다 Sprint Contract와 검증 기준을 작성하는 비용이 생긴다.
  • 너무 많은 agent, hook, command를 추가하면 Harness 자체가 유지보수 대상이 될 수 있으므로 docs/HARNESS.md의 단순화 규칙을 따른다.
  • Hook은 보조 장치일 뿐이며, evaluator 검토와 acceptance criteria를 대체하지 않는다.