Skip to content

[Feature] HWP/HWPX 실제 페이지 경계 파싱 및 정확한 pageNumber 지원 #66

Description

@sorbetsharkroundhand

문제

현재 parse({ pages }) 및 MCP parse_pages는 PDF에서는 실제 페이지 단위로 동작하지만, HWP/HWPX에서는 section을 페이지처럼 취급하는 근사 방식으로 동작하는 것으로 보입니다.

현재 소스에서는 다음과 같이 처리됩니다.

HWP 5.x

src/hwp5/parser.ts

metadata.pageCount = sections.length

// 페이지 범위 필터링 (섹션 단위 근사치)
const pageFilter = options?.pages
  ? parsePageRange(options.pages, sections.length)
  : null

IRBlock의 pageNumber 역시 실제 쪽 번호가 아니라 sectionNum이 사용됩니다.

pageNumber: ctx.sectionNum

HWPX

src/hwpx/parser.ts

metadata.pageCount = sectionPaths.length

// 페이지 범위 필터링 (섹션 단위 근사치)
const pageFilter = options?.pages
  ? parsePageRange(options.pages, sectionPaths.length)
  : null

HWPX 파싱 결과의 pageNumber 역시 sectionNum을 사용합니다.

MCP

src/mcp.tsparse_pages 설명에도 현재 동작이 명시되어 있습니다.

PDF는 정확한 페이지, HWP/HWPX는 섹션 단위 근사치입니다.

발생하는 문제

한글 문서는 하나의 section 안에 여러 실제 페이지가 존재할 수 있습니다.

예를 들어 실제 문서가:

section 1
 ├─ page 1
 ├─ page 2
 ├─ page 3
 └─ page 4

구조라면 현재 파싱 결과에서는 다음처럼 표현될 수 있습니다.

pageCount = 1

모든 IRBlock:
pageNumber = 1

이 경우 다음 작업이 어렵습니다.

  • 실제 페이지별 Markdown 추출
  • 특정 쪽만 RAG에 전달
  • 원본 HWP/HWPX와 PDF의 페이지 단위 대응
  • 페이지 단위 citation 생성
  • 문서 Viewer와 파싱 결과 간 위치 동기화
  • parse_pages("3-5")를 실제 한글 페이지 기준으로 사용

HWPX에는 이미 활용 가능한 구현이 있는 것으로 보임

src/render/svg-render.ts에는 HWPX의 실제 페이지 경계를 추정하는 로직이 이미 존재합니다.

한컴이 저장한 linesegarray에서 최상위 lineseg.vertpos가 페이지마다 로컬 좌표로 다시 시작하는 특성을 이용하여 페이지 경계를 판별합니다.

현재 renderer에서는 다음과 같은 경우까지 고려하고 있습니다.

  • vertpos 역행 → 새로운 페이지 후보
  • 다단 문서에서 horzpos를 함께 확인하여 단 이동과 페이지 이동 구분
  • 다음 페이지의 vertpos가 이전 페이지와 동일한 경우
  • 페이지 전체가 표 하나인 형태의 문서

따라서 HWPX parser에서도 renderer의 페이지 경계 판별 로직을 공통 유틸리티로 분리하여 활용할 수 있을 것 같습니다.

예:

section.xml
   ↓
linesegarray
   ↓
detectPageBoundaries()
   ↓
paragraph / table / image
   ↓
IRBlock.pageNumber = 실제 페이지

HWP 5.x

HWP 5.x도 현재는 Section 단위로만 pageNumber를 설정하고 있습니다.

HWP 바이너리의 조판 관련 레코드(PARA_LINE_SEG 등)를 이용해서 HWPX의 linesegarray와 유사한 방식으로 실제 페이지 경계를 복원할 수 있는지 검토가 필요해 보입니다.

HWP5에 대해서는 구현 가능 여부와 정확도를 먼저 조사하는 방식도 괜찮을 것 같습니다.

COM fallback

현재 Windows + 한컴오피스 환경의 COM fallback에서는 이미:

$pc = $hwp.PageCount

for ($p = 1; $p -le $pc; $p++) {
    $t = $hwp.GetPageText($p, 0)
}

방식으로 실제 페이지 단위 추출이 가능합니다.

다만 이 방식은 Windows 및 한컴오피스 설치가 필요하기 때문에, 일반 parser에서도 가능한 범위에서 페이지 경계를 복원할 수 있으면 활용도가 높을 것 같습니다.

제안

가능하다면 다음과 같은 형태를 제안합니다.

1. 실제 페이지 정보가 존재하는 경우 사용

const result = await parse(buffer)

result.pageCount

result.blocks[i].pageNumber

를 실제 한컴 페이지 기준으로 설정합니다.

2. HWPX 페이지 경계 감지 로직 공통화

현재 renderer 내부의 페이지 감지 로직을 예를 들어:

detectHwpxPageBoundaries(...)

같은 공통 모듈로 분리하여 parser와 renderer가 함께 사용할 수 있으면 좋겠습니다.

3. 실제 페이지 판별이 불가능한 경우 fallback

페이지 정보를 확실하게 판별할 수 없는 문서는 기존처럼 section 기반 결과를 반환하되, 이를 구분할 수 있는 정보가 있으면 좋겠습니다.

예:

metadata.pageMode = "layout" | "section"

또는 warning:

PAGE_BOUNDARY_APPROXIMATE

4. parse_pages 동작 개선

실제 페이지 정보가 존재하는 HWP/HWPX에서는:

parse(buffer, { pages: "3-5" })

가 section 35가 아니라 **실제 문서의 35쪽**을 반환하도록 개선되면 좋겠습니다.

기대 결과

예를 들어 실제 10쪽짜리 HWPX가 section 하나로 구성되어 있더라도:

result.pageCount === 10

result.blocks[0].pageNumber === 1
result.blocks[...].pageNumber === 2
...
result.blocks[...].pageNumber === 10

처럼 실제 페이지 기준 정보를 얻을 수 있으면 좋겠습니다.

특히 kordoc을 RAG, 문서 Viewer, 페이지 citation 등에 사용하는 경우 실제 페이지 번호가 상당히 유용할 것 같습니다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions