Skip to content

[Feat] PDF·DOCX 문서 파싱 지원 추가 구현 #103

Description

@Gimini-3

배경

현재 인덱싱 파이프라인은 TXT·Markdown 원본만 엄격한 UTF-8 Text로 파싱한 뒤 고정 크기 Chunk를 생성합니다. DocumentTypedocument_chunks.page_no·section_title 컬럼에는 PDF·DOCX 확장 기반이 있지만, 업로드 검증과 실제 Parser가 연결되지 않아 해당 형식을 처리할 수 없습니다.

이번 작업은 텍스트 기반 PDF와 DOCX를 기존 준비 Transaction → Object Storage 읽기·파싱·Chunk 계산 → 완료 Transaction 구조에 연결합니다. OCR은 포함하지 않고, 텍스트를 추출할 수 없는 PDF는 OCR이 필요한 문서로 명시적으로 분류합니다.

목표

  • PDF·DOCX 업로드 확장자와 Content-Type 검증
  • 문서 형식별 Parser 선택 계약 도입
  • 텍스트 PDF를 페이지별로 추출하고 Chunk의 페이지 번호 보존
  • DOCX 제목·본문·표를 문서 순서대로 추출하고 Section Title 보존
  • TXT·Markdown 기존 파싱·Chunk 결과 회귀 방지
  • 빈 문서·암호화 PDF·손상 문서·스캔 PDF 오류 구분
  • 기존 Worker 자동 Polling과 Batch Embedding 파이프라인 연결
  • 외부 파싱 중 DB Transaction을 유지하지 않는 기존 원자성 보존

핵심 설계

오픈소스 Parser

  • PDF: Apache PDFBox 3.0.8
  • DOCX: Apache POI 5.5.1
  • 두 라이브러리는 Apache License 2.0 기반
  • OCR Engine이나 외부 유료 API는 추가하지 않음

파싱 결과 계약

형식별 Parser는 원본 Byte를 다음 정보가 있는 순서형 Segment 목록으로 변환합니다.

  • Canonical Text
  • PDF Page Number
  • DOCX Section Title
  • 원본 내 전역 Character Offset
  • 형식별 최소 Metadata

TXT·Markdown은 기존 결과와 동일한 단일 Segment로 처리합니다.

PDF

  • 페이지별 Unicode Text 추출
  • CRLF·CR 줄바꿈을 LF로 정규화
  • 검색 가능한 Text가 없는 전체 PDF는 OCR 필요 오류
  • 암호화 또는 Password 보호 PDF는 별도 오류
  • 손상되거나 읽을 수 없는 PDF는 파싱 실패 오류
  • 페이지를 넘나드는 Chunk를 만들지 않고 page_no를 저장

DOCX

  • Paragraph와 Table을 원본 문서 순서대로 처리
  • Heading Style을 현재 Section Title로 사용
  • 표는 Row별, Cell별 경계를 보존한 Text로 직렬화
  • 빈 문단과 검색 가능한 Text가 없는 문서는 거부
  • 손상된 ZIP·OOXML은 파싱 실패 오류
  • 구형 .doc 형식은 제외

Chunking과 원자성

  1. 준비 Transaction에서 Job·Attempt·Worker·Claim Token·Lease·문서 형식을 검증
  2. Transaction 밖에서 Storage 읽기와 형식별 파싱 수행
  3. Segment 경계를 넘지 않는 고정 크기 Chunk 생성
  4. 페이지 번호·Section Title·전역 Character Offset·Hash를 Draft에 기록
  5. 완료 Transaction에서 소유권을 재검증하고 전체 Chunk Set을 원자 저장
  6. 파싱 또는 Chunking 실패 시 Chunk 부분 저장 없음

오류 계약

  • 지원하지 않는 문서 형식
  • 문서 내용 없음
  • UTF-8 Text 해석 실패
  • 암호화 PDF
  • OCR 필요 PDF
  • PDF·DOCX 파싱 실패
  • 문서 원본 참조 누락
  • Chunk 데이터 불일치

오류 메시지에 문서 원문, Object Storage 경로, Stack Trace를 노출하지 않습니다.

변경 대상

  • Gradle PDFBox·POI 의존성
  • PDF·DOCX 업로드 검증
  • 형식별 Parser 계약과 선택기
  • PDF Parser
  • DOCX Parser
  • Segment 기반 Chunker
  • 기존 Document Parsing Orchestration
  • 파싱 실패 Worker 분류
  • 단위·통합·회귀 테스트
  • docs/design/ 상세 설계
  • docs/test-results/ 실행 결과

제외 범위

  • OCR 실행
  • 스캔 PDF 이미지 전처리
  • 구형 .doc
  • HWP·HTML
  • PDF 내 이미지·도형·주석 추출
  • DOCX 이미지 OCR
  • Chunking 알고리즘의 Token 기반 전환
  • Query Vector·검색·RAG·MCP 변경
  • 공식 OpenSQL 원격 검증

검증 계획

  • PDF 페이지별 Text와 Page Number 보존
  • 다중 페이지 PDF에서 페이지 경계를 넘는 Chunk가 없는지 확인
  • 암호화·손상·빈·스캔 PDF 오류
  • DOCX Heading·본문·표 순서와 Section Title 보존
  • 손상·빈 DOCX 오류
  • PDF·DOCX 업로드 확장자·Content-Type 조합
  • TXT·Markdown Parser와 기존 Chunk 결과 회귀
  • 중간 파싱 실패 시 Chunk 0건
  • PostgreSQL 17 + pgvector 환경에서 PDF·DOCX Chunk 저장
  • Chunk 저장 후 기존 Batch Embedding 단계 진입
  • 전체 Gradle 테스트

완료 조건

  • PDF·DOCX 파일을 업로드할 수 있다.
  • 텍스트 PDF가 페이지별로 파싱되고 모든 Chunk에 올바른 Page Number가 저장된다.
  • DOCX 제목·본문·표가 원본 순서대로 추출되고 Section Title이 저장된다.
  • 스캔 PDF는 OCR 필요 오류로 명확히 구분된다.
  • 암호화·손상·빈 문서는 안정적인 오류 코드로 거부된다.
  • TXT·Markdown 기존 동작이 유지된다.
  • 외부 파싱 중 DB Transaction을 유지하지 않는다.
  • 파싱 실패 시 Chunk가 부분 저장되지 않는다.
  • 성공한 Chunk Set이 기존 Batch Embedding 파이프라인으로 전달된다.
  • 단위·통합·전체 회귀 테스트가 통과한다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions