Skip to content

feat: PDF 불러오기 (Phase 2, 텍스트 + 기본 구조화)#16

Open
revfactory wants to merge 5 commits into
mainfrom
feat/issue-5-pdf-import
Open

feat: PDF 불러오기 (Phase 2, 텍스트 + 기본 구조화)#16
revfactory wants to merge 5 commits into
mainfrom
feat/issue-5-pdf-import

Conversation

@revfactory

Copy link
Copy Markdown
Owner

📝 변경 요약

PDF 파일 임포트 기능을 Branch B (텍스트 + 기본 구조화) 범위로 구현합니다.

  • pdfjs-dist (Mozilla, Apache-2.0) 기반 Web Worker 파서
  • 페이지 평균 폰트 크기 휴리스틱으로 H1~H3 추정
  • 줄 앞 마커 (, ·, -, *, 1., 1), ) 인식 → 마크다운 리스트
  • 사이드바 임포트 버튼 영역에 PDF 진입점 추가 (MD / HWP / PDF)

MDVIEW_SPEC.md <future_considerations> 에 PDF 임포트(Phase 2) 항목을 정식 추가했고, CHANGELOG [Unreleased] 에도 등록했습니다.

Closes #5

🔍 원인 · 배경

이슈 트리아지 (_workspace/issues/5/triage.md) 결론:

  • 현재 스펙은 PDF 내보내기만 지원, 임포트는 미정의 (<out_of_scope> 직전).
  • PDF는 의미론적 구조(특히 표)가 없어 자동 변환 정확도에 본질적 한계가 있음.
  • 따라서 4가지 분기 중 B(부분 수락 — 텍스트 + 기본 구조화) 가 비용/가치 균형상 최선이라고 응답 코멘트에서 권장 → 메인테이너 승인.

🧱 변경 파일

파일 역할
MDVIEW_SPEC.md <future_considerations> 에 PDF 임포트 (Phase 2) 한 줄 추가
package.json / package-lock.json pdfjs-dist@^5.7 의존성 추가
src/types/pdf.ts (신규) PdfBlock, PdfImportOptions, PdfParseResult, PdfParsedPage 등 메시지·결과 타입
src/lib/pdf-converter.ts (신규) 페이지 라인 → 마크다운 블록 휴리스틱 변환
src/workers/pdf-parser.worker.ts (신규) pdfjs-dist 동적 import → 페이지별 텍스트/폰트 크기 추출
src/hooks/use-pdf.ts (신규) File → Worker → 진행률/결과/오류 상태 훅
src/components/features/import-export/pdf-import.tsx (신규) 드롭존 + 진행률 + 결과/경고/오류 모달
src/components/layout/sidebar.tsx 사이드바에 PDF 버튼 추가
src/app/page.tsx pdfImportOpen 상태, handlePdfImportComplete, <PdfImport /> 마운트
src/lib/analytics.ts analytics.importPdf 이벤트
CHANGELOG.md [Unreleased] 에 PDF 임포트 항목

❌ 이번 PR에 포함되지 않은 것 (의도적)

  • 표 → 마크다운 테이블 변환 (PDF 좌표 클러스터링 필요, 정확도 낮음)
  • 이미지 추출 / 임베딩
  • OCR (스캔본 지원)tesseract.js 미도입
  • 페이지 번호 · 머리말 · 꼬리말 정규화
  • 다단(컬럼) 레이아웃 인식
  • 줄 끝 하이픈 (word-break) 복원

위 항목들은 pdf-converter.ts 파일 헤더 / TODO 주석에 후속 PR 대상으로 명시했습니다.

🧪 검증

  • npm run lint — 신규 추가 lint 이슈 0건 (베이스라인 29개 문제 동일, 모두 사전 존재)
  • npm run typecheck — 깨끗
  • npm run build — 정적 빌드 성공
  • 수동 시나리오 (메인테이너 확인 권장):
    1. 사이드바 PDF 버튼 클릭 → 모달 열림, 상단에 "텍스트와 기본 구조만 추출" 안내 표시
    2. 일반 PDF 드래그 앤 드롭 → 진행률 0→100% 표시, 변환 완료 후 페이지/제목 표시
    3. 확인 클릭 → 새 문서로 열림, 토스트 "텍스트만 추출되었습니다..." 노출
    4. PDF 가 아닌 파일 → "PDF 파일(.pdf)만 지원합니다." 안내
    5. 스캔본 PDF (텍스트 거의 없음) → 경고 목록에 OCR 미지원 안내
    6. 50MB 초과 PDF → 사전 경고 배지, 200페이지 초과 결과 → 정확도 경고

⚙️ 구현 메모

  • pdfjs-dist 는 워커 내부에서 disableFontFace: true + 빈 workerSrc 로 fake-worker 모드 사용 → 중첩 Worker 회피.
  • 파일 ArrayBuffer 는 postMessage transferable 로 전달 → 메인 ↔ 워커 메모리 복사 제거.
  • 변환 결과가 300KB 초과면 기존 chunkDocument 파이프라인을 그대로 재사용해 페이지네이션 편집기로 자동 전환.

📌 비고 / 후속

  • 메인테이너 피드백 수렴 후 v2 (표 추출 / 페이지 번호 정규화) 별도 PR 예정.
  • OCR 은 사용자 요구가 강할 때만 도입 (번들 +10MB 부담).

issue #5 (B 분기: 텍스트 + 기본 구조화) 작업의 사전 정비.

- MDVIEW_SPEC.md: future_considerations 에 "PDF 임포트 — 텍스트
  + 기본 구조화(제목/문단/목록)만 (Phase 2)" 항목을 DOCX 임포트
  옆에 추가.
- package.json: pdfjs-dist@^5.7 (Mozilla, Apache-2.0) 추가.
  동적 import + Web Worker 패턴으로 사용해 메인 번들 영향 최소화.

Refs #5
issue #5 B 분기 — 텍스트와 기본 구조화만 추출하는 1차 구현.

추가 파일:
- src/types/pdf.ts: PdfBlock / PdfImportOptions / PdfParseResult /
  PdfParsedPage 등 워커-UI 간 메시지·결과 타입 정의.
- src/lib/pdf-converter.ts: pdfjs 페이지 라인 → 마크다운 블록
  변환 휴리스틱.
  - 제목: 페이지 평균 폰트 1.2배 이상인 줄을 H1~H3 으로 매핑.
  - 목록: •/·/-/*/1./1)/① 등 마커 인식 → 순서·비순서 리스트.
  - 문단: 동일 단락 라인은 공백으로 이어 붙여 단일 블록화.
  - 페이지 사이: 빈 줄만 삽입 (페이지 번호·머리말·꼬리말 제거,
    줄끝 하이픈 복원은 후속 PR — TODO 주석으로 명시).
- src/workers/pdf-parser.worker.ts: pdfjs-dist 를 동적 import 한 뒤
  중첩 워커 없이(fake-worker 모드) 페이지별 텍스트와 폰트 크기를
  추출. 진행률 메시지 + %PDF 매직 검증 + 스캔본 추정 경고 포함.

Refs #5
issue #5 B 분기 — use-hwp.ts / hwp-import.tsx 패턴을 그대로
복제해 UI 톤을 통일.

- src/hooks/use-pdf.ts: usePdfImport — File → Worker → 진행률/
  결과/에러 상태 관리. transferable ArrayBuffer 로 복사 비용 제거.
- src/components/features/import-export/pdf-import.tsx: 드롭존
  + 파일 선택 + 진행률 + 결과·경고·오류 모달. 상단에 "텍스트와
  기본 구조만 추출, 표·이미지·OCR 미지원" 안내를 상시 노출.
  50MB 초과 시 시간 경고, 200페이지 초과 시 정확도 경고.

Refs #5
issue #5 B 분기 — UI 진입점을 기존 MD/HWP 임포트 옆에 추가.

- src/components/layout/sidebar.tsx: 사이드바 임포트 버튼 영역에
  PDF 버튼 추가. 한 줄에 3개가 들어가도록 라벨을 MD/HWP/PDF 로
  축약. onImportPdf prop 추가.
- src/app/page.tsx: pdfImportOpen 상태 + handlePdfImportComplete
  핸들러 추가. 변환 완료 후 "텍스트만 추출되었습니다. 표·이미지·
  OCR 미지원" 토스트 노출. 대용량 결과는 기존 청크 분할 파이프
  라인 재사용. PdfImport 모달을 page tree 에 마운트.
- src/lib/analytics.ts: analytics.importPdf 이벤트 추가.

Closes #5
@vercel

vercel Bot commented May 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mdview Ready Ready Preview May 28, 2026 11:42am

Request Review

Comment thread src/lib/pdf-converter.ts
Comment on lines +184 to +188
return text
// Escape leading characters that would be parsed as block syntax
.replace(/^(\s*)([#>|])/, '$1\\$2')
// Escape backticks to avoid accidental inline code spans
.replace(/`/g, '\\`');

// ---------- Message handler ----------

self.onmessage = async (e: MessageEvent<PdfParseMessage>) => {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] PDF 불러오기 기능 추가해주세요

2 participants