Skip to content

HWP Authoring Feature Roadmap

작성일: 2026-05-11

목적

이 문서는 현재 openhwpsdk가 실제 한/글 문서 작성 프로그램의 자주 쓰는 기능과 비교해 어디까지 왔고, 무엇을 다음에 구현해야 하는지 정리한다. 목표는 "대부분의 HWP 문서 작성 기능을 한 번에 구현"이 아니라, 실제 문서 작성에서 자주 쓰는 기능을 작은 개발 단위로 나누고 각 단위마다 검증 가능한 fixture와 합격 기준을 두는 것이다.

근거

  • 현재 repo 기능 근거: Program.cs CLI 표면, HwpxFormMap, HwpxTableModel, HwpxPackageImageInserter, HwpxLayoutValidator.
  • 로컬 검증 근거(공개 repo 미포함): 2026-05-11 feature corpus scan에서 HWPX 69개, package/XML parse error 0, 표 3,049개, 셀 70,558개, 병합셀 20,360개, 중첩표 184개, 그림 94개, 필드/양식 492개, header/footer 4개, note 4개, reference 128개, embedded object 5개를 확인했다.
  • 한컴 공식 SDK/도움말 기준:
  • 한글 SDK: HWP/HWPX 문서 뷰잉, 생성, 열기/저장, HTML/PDF 등 포맷 변환, Text/Image/Table 데이터 삽입/편집, 문서 보안, 문서 비교/병합/이력 관리 기능을 SDK 범주로 제시.
  • Hancom SDK 라인업: document editing, automation, comparison, Docs Compare SDK, OCR SDK 등을 별도 SDK 범주로 제시.
  • 입력 탭: 표, 차트, 도형, 그림, 스크린샷, 글맵시, 수식, 동영상, 문단 띠, 양식 개체, 누름틀, 각주/미주, 책갈피, 상호 참조, 하이퍼링크, 문자표, 한자 입력.
  • 표 메뉴: 표 만들기/그리기, 문자열-표 변환, 표/셀 속성, 테두리/배경, 줄/칸 추가/삭제, 셀 나누기/합치기, 표 계산식.
  • 머리말/꼬리말: 쪽마다 반복되는 영역이며, 본문과 별개로 문자, 그림, 표, 그리기 개체와 문단/글자 모양을 가질 수 있음.
  • 누름틀: 안내문, 메모, 필드 이름이 있는 입력 필드.
  • 차례/색인: 제목/표/그림/수식 차례와 색인 자동 생성.
  • 상호 참조: 표, 그림, 수식, 각주/미주, 개요, 책갈피 등을 참조하고 번호/쪽 변화에 대응.
  • 수식 명령어: 분수, 근호, 적분, 행렬 등 스크립트 기반 수식 입력 체계.
  • HWPX 구조: HWPX는 ZIP 기반 XML 패키지이며 BinData, Contents/content.hpf, Contents/header.xml, Contents/section*.xml 등이 핵심.

현재 강한 영역

  1. 기존 제출서식형 HWPX 보존 작성
  2. extract-form-map, probe-form-map, apply-form-map, apply-form-map --package.
  3. package text/image write, style guard, layout/content validation.

  4. 표 중심 템플릿 자동 입력

  5. cellAddr/cellSpan 기반 grid reconstruction.
  6. 병합셀 guard, 중첩표 텍스트 분리, 기존 셀 currentText 검증.

  7. 그림 삽입

  8. COM 기반 그림 삽입.
  9. package 기반 BinData/hp:pic/manifest 삽입.

  10. 제출서식 profile

  11. fill-submission-template --profile r-and-d-startup-2026.
  12. Markdown 표 렌더링, 이미지 anchor queue, 보고서/검증 흐름.

완료 요약

2026-05-11 이후 현재까지 구현/검증된 authoring 축은 다음과 같다.

  1. corpus와 inventory 기반
  2. 로컬 feature corpus 기준으로 scan-hwpx-features가 aggregate counts, authoring coverage, detailed feature groups, missing corpus signals, per-file totals를 출력한다.
  3. header/footer, field/form, reference, note inventory가 파일/part/type/text 단위로 분리되어 report된다.

  4. 제출서식 보존 작성

  5. extract-form-map, probe-form-map, apply-form-map, apply-form-map --package가 기존 HWPX 구조를 보존하면서 text/image/field/form 일부 쓰기를 수행한다.
  6. package text write는 currentText 검증과 sub-7pt charPr guard를 적용한다.
  7. validate-layout, validate-content, scan-hwpx-features, PDF export를 조합한 검증 흐름이 정착됐다.

  8. rich copy/paste 자동화

  9. list-controls, probe-copy-from-doc, copy-from-doc가 추가됐다.
  10. source selector는 all, paragraph-to-end:<text>, table:<index>, image:<index>, control:<ctrlId>:<index>를 지원한다.
  11. target selector는 doc-end, anchor:<text>, cell:<table,rowMove,colMove>, control:<ctrlId>:<index>를 지원한다.
  12. image/gso source를 HWPX control:gso:<index> target에 붙여넣는 경우 copy-from-doc가 output package를 post-verify하고, COM process snapshot과 선택적 --strict-cleanup 진단을 report한다.

  13. 머리말/꼬리말 및 쪽 번호

  14. list-header-footer가 section-aware header/footer inventory를 출력한다.
  15. set-header-footer-text가 기존 header/footer body anchor text를 package-level로 치환한다.
  16. page-number-set은 COM 기반 쪽 번호 삽입 smoke를 통과했다.

  17. 누름틀/필드/양식 일부

  18. list-fields가 package-level field/form item과 선택적 COM field list 결과를 병합한다.
  19. extract-form-map은 field/press marker와 checkbox/radio/combo/edit 같은 form object를 별도 fields section에 출력한다.
  20. apply-form-map --package는 press field text와 checkbox checked/unchecked 값을 제한적으로 쓴다.

  21. 표 package authoring

  22. table-create-package, table-row-package, table-column-package, table-merge-package, table-split-package가 단순 top-level table 범위에서 검증됐다.
  23. table-cell-style-package, table-cell-align-package, table-cell-background-package, table-cell-diagonal-package, table-cell-size-package가 셀 스타일/정렬/배경/대각선/크기 조정 범위에서 검증됐다.
  24. 병합/중첩/sparse/주소 불일치/객체 포함 표는 명시적으로 거부하는 방향으로 안전 범위를 좁혔다.

  25. 이미지 inventory/교체 일부

  26. list-pictures가 COM 없이 picture index, package gso index, binaryItemIDRef, BinData, SHA256, pixel size, 크기/배치/wrap 속성을 보고한다.
  27. package-level replace-image-control이 기존 hp:pic 속성을 유지한 채 단일 picture의 연결 image binary를 교체하고, source/before/after hash, picture/table count, 속성 보존, validate-layout 결과를 보고한다.
  28. InsertPicture의 HWPX hp:sz 단위 오입력은 guard와 docs로 방어한다.
  29. 남은 큰 작업은 COM/editor-backed replacement fallback과 shape/control 속성 재적용이다.

큰 공백

현재 구현은 "제출서식형 HWPX의 본문/표/병합셀/중첩표/이미지 작성"에 강하다. 반대로 실제 한/글에서 자주 쓰지만 아직 약하거나 없는 축은 다음이다.

  • 기존 HWPX 안의 특정 그림은 package-level로 교체할 수 있지만, COM/editor-backed replacement fallback과 도형까지 포함한 속성 재적용은 아직 남아 있다.
  • 그림 control의 BinData 해시, pixel size, HWPX 표시 속성 inventory는 들어왔고, 도형 control까지 포함한 범용 diff는 아직 남아 있다.
  • 머리말/꼬리말의 신규 영역 생성, COM 기반 편집, 그림/표/도형 포함 반복 영역 작성, 구역별 쪽 설정.
  • 각주/미주, 메모, 덧말.
  • generic field, radio/combo/edit/button form control의 package-level 입력과 검증 contract.
  • 책갈피, 캡션, 상호 참조, 차례/색인.
  • 일반 도형, 글상자, 글맵시, 문단 띠, 그룹, 회전, z-order, wrapping.
  • 수식, 차트, OLE, 동영상/소리.
  • 표 작성의 남은 범위: 표 그리기, 계산식, 병합/중첩/객체 포함 표 같은 unsafe case, 더 넓은 표/셀 style coverage.
  • 일반 Markdown-to-HWP renderer: 제목, 개요 번호, 목록, 인라인 스타일, 표, 그림, 캡션, 링크를 모두 HWP native 구조로 생성.
  • PDF/시각 회귀 검증 자동화.
  • SDK parity 관점의 문서 보안: 문서 비밀번호, 배포용 문서 제한, 개인정보 텍스트 암호화.
  • SDK parity 관점의 문서 비교/병합/이력 관리: diff report, 병합 결과물 생성, 변경 이력 보존/검증.
  • SDK parity 관점의 포맷 변환: PDF 외 HTML/웹페이지/기타 필터 변환과 변환 결과 검증.
  • SDK parity 관점의 페이지/레이아웃 설정: 용지, 여백, 방향, 단, 구역 나누기, 구역별 쪽 번호 정책.

로드맵

Phase 0. Corpus 확장과 기능 재현성

목표: "없다/된다"를 말할 수 있는 최소 fixture를 확보한다.

개발 단위:

  1. 로컬 feature fixture corpus 구성
  2. header-footer.hwpx
  3. footnote-endnote.hwpx
  4. press-field-form.hwpx
  5. caption-crossref-toc.hwpx
  6. equation.hwpx
  7. shape-textbox.hwpx
  8. chart-ole.hwpx
  9. table-authoring.hwpx
  10. simple-table.hwpx

  11. scan-hwpx-features 확장

  12. header/footer 본문 part 감지.
  13. footnote/endnote body 감지.
  14. field/form object 종류별 count.
  15. shape type별 count: line, rect, ellipse, text box, group, container.
  16. equation/chart/OLE/media count.
  17. caption/bookmark/cross reference/TOC/index marker count.

합격 기준:

  • 각 fixture가 최소 하나 이상의 대상 feature를 가진다.
  • scan-hwpx-features report가 feature별 count를 사람이 확인 가능한 표로 출력한다.
  • corpus가 없어서 구현 여부를 판단하지 못하는 항목을 report에서 별도 표시한다.

우선순위: P0

구현 상태(2026-05-11):

  • feature fixture corpus와 생성 스크립트는 공개 repo에서 제외하고 로컬 검증 자산으로만 유지한다.
  • scan-hwpx-features report는 aggregate counts, authoring coverage, detailed feature groups, missing corpus signals, per-file totals를 출력한다.
  • 상세 inventory report는 header/footer, field/form, reference, note 신호를 파일/part/type/text 단위로 보여준다.
  • 이 단계는 corpus inventory이며, 해당 기능의 write/edit 지원을 의미하지 않는다. 실제 작성 기능은 각 phase의 별도 개발 단위에서 검증한다.

복붙 자동화 상태(2026-05-11):

  • HWP COM 기반 list-controls, probe-copy-from-doc, copy-from-doc 명령을 추가했다.
  • 현재 rich copy source는 all, paragraph-to-end:<text>, table:<index>, image:<index>, control:<ctrlId>:<index>를 지원한다.
  • target은 doc-end, anchor:<text>, cell:<table,rowMove,colMove>, control:<ctrlId>:<index>를 지원한다.
  • 실제 제출서식 smoke에서 table:0을 대상 문서 끝에 붙여넣고, 표 48개 -> 49개, changed core tables 0, layout verdict pass를 확인했다.
  • image:<index>list-controls의 전역 index가 아니라 gso 행의 typeIndex 값을 source-only로 복사한다.

Phase 1. 머리말/꼬리말 및 쪽/구역 모델

목표: 실무 문서에서 가장 자주 쓰는 쪽 기반 반복 영역을 안전하게 읽고 쓴다.

개발 단위:

  1. header/footer inventory
  2. section별 header/footer reference 추출.
  3. 홀수/짝수/양쪽 위치 구분.
  4. 텍스트/표/그림/도형 count report.

  5. header/footer text write

  6. 기존 header/footer paragraph anchor에 텍스트 쓰기.
  7. package mode와 COM mode 둘 다 지원하되, 우선 package text write.

  8. page number support

  9. COM command로 쪽 번호 삽입 smoke test.
  10. HWPX package에서는 inventory/보존 검증부터 시작.

합격 기준:

  • header/footer가 있는 fixture에서 본문 table count/style drift가 변하지 않는다.
  • header/footer 텍스트가 PDF export에서 보인다.
  • 여러 header/footer가 있을 때 section/위치가 report에 명확히 나온다.

우선순위: P0/P1

구현 상태(2026-05-11):

  • list-header-footer 명령으로 HWPX 파일/디렉터리의 section-aware header/footer inventory를 별도 출력한다.
  • report는 section, part, kind, body/reference role, applyPageType, reference attrs, paragraph/table/picture/shape count, text preview를 포함한다.
  • scan-hwpx-features의 Header/Footer Inventory 표도 동일하게 section/applyPageType 컬럼을 포함하도록 확장했다.
  • set-header-footer-text 명령으로 기존 header/footer body 안의 anchor 텍스트를 package-level로 치환한다.
  • header-footer.hwpx fixture에서 header 본문 텍스트 치환 후 content/layout/header-footer inventory smoke를 통과했다.
  • add-header-footer-reference 명령으로 이미 존재하는 header/footer idRef를 재사용해 새 applyPageType reference를 하나 추가한다. 같은 section/kind의 applyPageType 중복은 거부한다.
  • add-header-footer-text 명령으로 section 내 신규 header/footer idRef의 단순 1문단 text body와 reference를 함께 추가한다. 중복 header/footer idRef와 중복 section/kind/applyPageType은 거부한다.
  • page-number-set 명령으로 COM 기반 쪽 번호를 삽입한다. 실제 제출서식 smoke에서 pageNumbers=1, references 2 -> 3, 표 48개 유지, layout verdict pass를 확인했다.
  • rich object 편집, COM 기반 header/footer 쓰기, section page setup은 아직 다음 개발 단위다.

Phase 2. 누름틀/필드/양식 개체

목표: 제안서/공문/계약서 템플릿에서 가장 흔한 "빈칸 채우기"를 named field 기반으로 안정화한다.

개발 단위:

  1. field inventory
  2. COM field-list-raw 결과와 HWPX package scan 결과를 한 report에 병합.
  3. field name, 안내문, 현재 값, 위치, 인쇄 여부를 가능한 범위에서 추출.

  4. extract-form-map field targets 추가

  5. field / press target kind 추가.
  6. 기존 cell/anchor target과 분리.

  7. package-level press field fill

  8. named field currentText 검증.
  9. placeholder style 유지 또는 정상 본문 style override 옵션.

  10. form object inventory

  11. checkbox, radio, combo, edit box는 우선 보존/검증.
  12. 값 쓰기는 COM smoke test 이후 별도.

합격 기준:

  • 같은 안내문이 여러 번 있어도 field name으로 정확히 채운다.
  • 누름틀 안내문 삭제/사용자 입력값 삽입이 HWP에서 열어도 유지된다.
  • global replace 없이 target별 report가 남는다.

우선순위: P0/P1

구현 상태(2026-05-11):

  • list-fields 명령으로 package-level field/form item과 선택적 COM GetFieldList 결과를 한 report에 병합한다.
  • package report는 part, kind, attrs(name/value 등), text preview를 출력한다. COM report는 raw list에서 파싱 가능한 field name, 존재 여부, 현재 text를 출력한다.
  • press-field-form.hwpx fixture에서 field/press/form 6개 package item을 확인했고, 실제 제출서식 smoke에서 checkbox 8개와 COM raw empty 결과를 같은 report에 남겼다.
  • extract-form-map은 이제 field/press marker와 checkBtn, checkbox, radio, combo, edit control 같은 form object를 별도 fields section에 출력한다.
  • apply-form-map --packagekind=press field의 writeText enabled="true" 값을 package-level로 적용하며, currentText mismatch는 실패 처리한다.
  • press-field 개발 단위 smoke에서 press-field-form.hwpxpress-aUpdated press field로 치환했고, content/layout/list-fields 검증을 통과했다. 당시 text 기반 unsupported checkbox write는 skipped_unsafe=1로 막았다.
  • apply-form-map --packagekind=checkBox field의 writeValue enabled="true" 값을 CHECKED/UNCHECKED로 적용하며, value mismatch는 실패 처리한다.
  • 실제 제출서식 smoke에서 CheckBox1UNCHECKED -> CHECKED로 변경했고, layout/list-fields/package XML 검증을 통과했다. mismatch map은 failed=1, unsupported radio value write는 skipped_unsafe=1로 막았다.
  • 인쇄 여부, generic field writing, radio/combo/edit value writing은 다음 개발 단위다.

Phase 3. 표 authoring 전 범위

목표: 기존 표 채우기에서 "표를 새로 만들고 조작하는 기능"으로 확장한다.

구현 상태(2026-05-11):

  • table-create-package 명령으로 COM 없이 새 단순 표를 만든다.
  • 기존 HWPX 안의 병합/중첩 없는 top-level 표를 reference style로 복제하고, --rows, --cols, --text, --text-file, --after-anchor, --reference-table, --border-fill-id, --header-border-fill-id, --report를 지원한다. Anchor 삽입은 top-level 문단으로 제한하고, border fill ID는 Contents/header.xml 정의에 존재할 때만 허용한다.
  • 실제 제출서식 smoke에서 top-level 표 44 -> 45, 전체 layout validator 표 48 -> 49, changed core tables 0, leading paragraph style drift 0, content require 통과를 확인했다.
  • 병합/중첩 표만 있는 table-authoring.hwpx fixture에서는 안전한 reference table이 없어서 실패하도록 막았고, 양성 경로 검증용 simple-table.hwpx fixture를 추가했다.
  • table-row-package 명령으로 단순 top-level 텍스트 셀 표의 행 추가/삭제를 지원한다. 병합/중첩/sparse/주소 불일치/객체 포함 표는 거부하고, 행 추가/삭제 후 cellAddr, rowCnt, colCnt, 표 크기를 재정규화한다.
  • 실제 제출서식 smoke에서 top-level table 4에 2행을 추가해 3 -> 5행, 1행을 삭제해 3 -> 2행으로 변경했고, validate-layout --allow-table-row-change 4에서 expected-change/pass를 확인했다.
  • table-column-package 명령으로 같은 안전 범위의 선택한 body section 표에 열 추가/삭제를 지원한다. 열 변경은 표 폭도 함께 바뀌므로 validate-layout --allow-table-column-change 옵션을 추가해 의도된 열/폭 변경을 expected-change로 분류한다.
  • 실제 제출서식 smoke에서 top-level table 4에 1열을 추가해 4 -> 5열, 1열을 삭제해 4 -> 3열로 변경했고, validate-layout --allow-table-column-change 4에서 expected-change/pass를 확인했다.
  • table-merge-package 명령으로 단순 unmerged top-level 텍스트 셀 표의 직사각형 셀 병합을 지원한다. --row/--column은 zero-based top-left 셀이고, --row-span/--col-span은 병합 범위다. 병합 후 표의 row/column count는 유지하고 covered cell만 제거하며 top-left cell에 cellSpan과 병합 영역 크기를 기록한다.
  • --text가 없으면 병합 범위 안의 기존 셀 텍스트를 row-major 순서로 합친다. 병합 입력은 현재 병합/중첩/sparse/주소 불일치/객체 포함 표를 거부한다.
  • table-split-package 명령으로 기존 병합셀을 다시 1x1 셀 grid로 나누는 package writer를 추가했다. 병합된 top-left 셀 주소를 기준으로 covered cell을 다시 만들고, 주변 셀에서 열 너비/행 높이를 샘플링하며, --text matrix가 없으면 기존 병합 텍스트를 top-left 셀에 보존한다.
  • 병합 산출물을 다시 split하는 왕복 smoke에서 physical cell 9 -> 12, row/column 3x4 유지, layout/content pass, 직접 XML 기준 네 셀 cellSpan=1x1 복원을 확인했다.
  • table-cell-style-package 명령으로 기존 Contents/header.xml에 정의된 borderFill ID를 셀 또는 직사각형 범위에 적용한다. 선택 범위와 span이 교차하는 셀을 대상으로 하므로 병합셀 내부 covered coordinate를 선택해도 top-left 병합셀 스타일이 바뀐다.
  • 실제 제출서식 smoke에서 top-level table 4의 row 1/column 1 셀 borderFillIDRef를 16 -> 32로 바꾸고 layout pass와 직접 XML 검증을 확인했다. 존재하지 않는 borderFill ID 9999는 적용 전에 실패한다.
  • table-cell-align-package 명령으로 셀 내부 문단의 가로 정렬과 셀 세로 정렬을 변경한다. 가로 정렬은 공유 paraPr를 직접 수정하지 않고 Contents/header.xml에서 clone을 만들어 해당 셀 문단만 새 paraPrIDRef를 보게 하며, 세로 정렬은 hp:subList@vertAlign을 변경한다.
  • 실제 제출서식 smoke에서 row 1/column 1 셀을 horizontal=RIGHT, vertical=BOTTOM으로 변경했고, 직접 XML에서 새 paraPrIDRef=203, header align RIGHT, paraProperties itemCnt=204, subList vertAlign BOTTOM을 확인했다. 병합셀 covered coordinate 선택도 top-left 병합셀 정렬로 적용된다.
  • table-cell-background-package 명령으로 셀 배경색을 직접 설정하거나 지운다. 선택 셀의 현재 borderFill을 clone하고 hc:fillBrush/hc:winBrush@faceColor만 갱신하거나 --color none일 때 fillBrush를 제거한 뒤 해당 셀만 새 ID로 retarget한다.
  • 실제 제출서식 smoke에서 top-level table 4의 row 1/column 1 셀에 #FFF2CC 배경색을 적용했고, layout pass와 직접 XML 기준 faceColor=#FFF2CC, 기존 leftBorder 유지, cloned borderFill ID 적용을 확인했다. 병합셀 covered coordinate 선택도 top-left 병합셀 배경으로 적용된다.
  • table-cell-diagonal-package 명령으로 셀 대각선을 추가/변경/삭제한다. 기존 borderFill을 직접 바꾸지 않고 선택 셀의 현재 borderFill을 clone한 뒤 hh:slash/hh:backSlashhh:diagonal 폭/색상만 갱신하고 해당 셀만 새 ID로 retarget한다.
  • 실제 제출서식 smoke에서 top-level table 4의 row 1/column 1 셀에 direction=both, width=0.15 mm, color=#000000을 적용했고, layout pass와 직접 XML 기준 slash=CENTER, backSlash=CENTER, cloned borderFill ID 적용을 확인했다. 병합셀 covered coordinate 선택은 top-left 병합셀의 대각선으로 적용된다.
  • table-cell-size-package 명령으로 단순 unmerged top-level 표의 열 너비와 행 높이를 균등화한다. 전체 표 폭/높이는 유지하고 기존 hp:cellSz 값을 열/행 단위로 재분배하며, 병합/중첩/sparse/주소 불일치 표는 거부한다.
  • 실제 제출서식 smoke에서 top-level table 11의 column widths 9788,20451,6361,1051311778,11778,11778,11779로, row heights 2403,1363,13631709,1709,1711로 균등화했고, 표 전체 크기 47113x5129, row/column count 3x4, layout pass를 확인했다.

개발 단위:

  1. table create package writer
  2. 단순 표 rows x cols 생성.
  3. template table style clone 옵션.
  4. cell border/background 기본값 설정.

  5. row/column operations

  6. 줄/칸 추가/삭제.
  7. 셀 높이/너비 균등화. (implemented: table-cell-size-package)
  8. 기존 table model의 cellAddr/cellSpan 재계산.

  9. merge/split operations

  10. 단순 rectangular merge. (implemented: table-merge-package)
  11. split back to grid. (implemented: table-split-package)
  12. overlap validator 강화.

  13. table style operations

  14. border/background. (partially implemented: table-cell-style-package existing borderFill apply, table-cell-background-package direct fill color)
  15. diagonal line. (implemented: table-cell-diagonal-package)
  16. paragraph alignment, vertical alignment. (implemented: table-cell-align-package)

  17. formulas

  18. 쉬운 계산식/블록 계산식은 우선 inventory와 COM smoke test.
  19. package writer는 formula object 구조 파악 후 진행.

합격 기준:

  • 새 표가 HWP에서 실제 표로 열린다.
  • validate-layout가 table grid overlap을 잡는다.
  • merge/split 후 scan-hwpx-features와 PDF export가 일치한다.

우선순위: P1

Phase 3.5. 이미지/개체 교체 안정화

목표: 기존 문서 안의 특정 그림 개체를 "새 그림 삽입"이 아니라 "기존 개체 교체"로 다룬다. 기존 control의 위치, 크기, wrap, anchor, z-order, treatAsChar, margin/crop 계열 속성을 보존하고, 저장 후 실제 BinDatahp:pic 속성을 검증한다.

배경:

  • copy-from-doc는 COM select/copy/paste 호출이 모두 성공해도 실제 target 그림 바이너리가 바뀌지 않는 경우가 있었다.
  • InsertPicture는 새 PNG를 넣을 수 있지만 width/height 단위가 HWPX 내부 hp:sz와 직접 호환되지 않아 표시 크기와 배치 속성이 깨질 수 있다.
  • validate-layoutvalidate-content는 표/문단 구조 안정성을 보지만, 특정 그림의 바이너리 교체 성공과 표시 속성 보존까지 증명하지 않는다.

개발 단위:

  1. picture/control inventory
  2. list-pictures 또는 inspect-pictures 명령을 추가한다.
  3. report에는 section part, picture index, gso typeIndex, binaryItemIDRef, BinData path, SHA256, pixel size, byte size, hp:sz, hp:pos, orgSz, curSz, imgClip, outMargin, textWrap, textFlow, zOrder, treatAsChar, anchor/position 관련 vertRelTo/horzRelTo/offset 속성을 출력한다.
  4. list-controls의 gso typeIndex와 package-level hp:pic을 연결해 사람이 target을 고를 수 있게 한다.

  5. package-level replace-image-control

  6. 우선 COM 없이 HWPX package를 직접 수정한다.
  7. --target control:gso:<index> 또는 --target image:<binaryItemIDRef>로 기존 hp:pic을 찾는다.
  8. 기존 hp:pic/hp:pos/hp:sz/wrap 속성은 보존하고, 연결된 BinData entry와 Contents/header.xml image entry만 새 이미지에 맞게 갱신한다.
  9. 새 확장자와 mime type, manifest item, package entry 이름 충돌을 안전하게 처리한다.

  10. COM/editor-backed replacement fallback

  11. package-level 교체가 target 문서 구조상 안전하지 않거나 HWP editor reflow가 필요한 경우의 fallback으로 둔다.
  12. 대상 control 선택, 기존 ShapeObjDialog/shape properties 읽기, 기존 그림 삭제, 새 그림 삽입, 새 그림 재선택, 기존 속성 재적용 순서로 구현한다.
  13. 이 경로는 COM 상태와 HWP 버전에 민감하므로 Phase 3.5 v1의 기본 경로는 package-level이고, COM fallback은 별도 smoke와 cleanup/report 기준을 만족할 때 implemented로 표시한다.

  14. 교체 결과 검증

  15. source image path, pixel size, SHA256.
  16. target control id/typeIndex.
  17. before/after image id, BinData path, pixel size, SHA256.
  18. picture count/table count before/after.
  19. preserved object properties diff: hp:sz, hp:pos, orgSz, curSz, imgClip, outMargin, textWrap, textFlow, zOrder, treatAsChar, anchor/position offset 속성.
  20. input/output path가 모두 있는 replace operation은 validate-layout 결과를 report에 연결한다. 실행 환경상 layout validation을 건너뛰면 skipped reason을 report에 남긴다.
  21. target image hash가 source와 다르면 실패 exit code를 반환한다.

  22. copy-from-doc post-verify

  23. image/control target이 들어온 경우 output 저장 후 package-level before/after 검증을 수행한다.
  24. 호출 성공과 실제 문서 변경 성공을 구분해 report와 exit code에 반영한다.
  25. 검증 불가 상태는 applied가 아니라 review-needed 또는 failed로 분류한다.

  26. InsertPicture 단위 명확화와 방어

  27. InsertPicture width/height가 HWPX 내부 hp:sz 단위가 아님을 CLI usage와 docs에 명시한다.
  28. 비정상적으로 큰 width/height가 들어오면 경고 또는 실패 처리한다.
  29. HWPX 내부 단위로 기존 object 크기를 재사용하려는 경우 replace-image-control을 사용하도록 안내한다.

  30. COM cleanup/report 강화

  31. COM-backed 명령 시작/종료 시 running_hwp_processes 요약을 report에 남긴다.
  32. --strict-cleanup 또는 후속 진단 모드로 "이번 명령 이후 새로 남은 제목 없는 Hwp 프로세스"를 감지한다.
  33. 사용자 소유 HWP 창을 강제 종료하지 않고, 잔류/잠금 가능성을 명확히 보고한다.

합격 기준:

  • 기존 그림이 있는 fixture에서 replace-image-control 실행 후 picture count와 table count가 유지된다.
  • target BinData SHA256이 source image와 일치한다.
  • target hp:pichp:sz, hp:pos, orgSz, curSz, imgClip, outMargin, textWrap, textFlow, zOrder, treatAsChar, anchor/position offset 속성 보존 여부가 report에 명시된다.
  • replace operation report는 validate-layout 결과를 포함하거나, 검증을 건너뛴 이유를 명시한다.
  • copy-from-doc는 실제 binary/object 교체 실패를 verdict: applied로 보고하지 않는다.
  • InsertPicture 문서/usage만 보고는 HWPX 내부 단위를 그대로 넣는 실수를 피할 수 있다.

우선순위: P0/P1

Phase 4. 캡션, 책갈피, 상호 참조, 차례/색인

목표: 보고서/논문/제안서에서 그림/표 번호와 차례를 자동화한다.

개발 단위:

  1. caption inventory
  2. 표/그림/수식 caption 추출.
  3. caption 없는 object report.

  4. caption insert

  5. COM path로 표/그림 caption 삽입.
  6. package path는 보존 검증부터.

  7. bookmark and cross-reference inventory

  8. 대상 종류: 표, 그림, 수식, 각주/미주, 개요, 책갈피.
  9. reference text와 target id 매핑.

  10. TOC/index generation workflow

  11. COM command smoke test.
  12. package writer는 직접 생성보다 "기존 차례 새로고침/검증" 중심.

합격 기준:

  • 표/그림 번호가 삽입 후 PDF에서 보인다.
  • 앞쪽에 새 그림/표를 추가해도 COM refresh 후 reference가 업데이트된다.
  • 차례/색인은 직접 생성보다 HWP COM 새로고침을 기본 경로로 둔다.

우선순위: P1/P2

Phase 5. 각주/미주/메모/덧말

목표: 학술 문서와 법률/계약서 문서에서 필요한 주석 계층을 지원한다.

개발 단위:

  1. note inventory
  2. footnote/endnote part 감지.
  3. 본문 note marker와 note body 연결 report.

  4. note insert via COM

  5. 각주/미주 삽입 smoke test.
  6. note body text 입력.

  7. package-level note preservation

  8. 기존 note가 있는 문서에 package text write를 해도 note marker/body가 유지되는지 검증.

  9. memo/comment inventory

  10. 검토 메모는 우선 보존/검증.

합격 기준:

  • 본문 marker와 note body가 양쪽 모두 보존된다.
  • PDF export에서 각주/미주 위치가 정상이다.
  • package text write가 note 구조를 손상하지 않는다.

우선순위: P1/P2

Phase 6. 도형/글상자/글맵시/문단 띠

목표: 실제 문서에서 자주 쓰는 비본문 개체를 최소한 보존하고, 이후 생성/편집으로 확장한다.

개발 단위:

  1. shape inventory diff
  2. type, id, zOrder, anchor paragraph, size, position, wrapping.
  3. validate-layout에 shape/control inventory diff 추가.

  4. text box read/write

  5. 글상자 내부 텍스트 추출.
  6. existing text box content replacement.

  7. simple shape create

  8. line/rect/ellipse 기본 생성.
  9. explicit HWPX unit size/position.

  10. object transform

  11. rotate, group, z-order, wrap은 inventory/보존 검증 후 단계적으로.

합격 기준:

  • shape가 있는 fixture에서 package write 후 shape count/id/type/position이 유지된다.
  • 글상자 텍스트 replacement가 HWP에서 보인다.
  • 새 line/rect가 PDF에서 보인다.

우선순위: P2

Phase 7. 수식

목표: 수식이 있는 문서의 보존부터 시작하고, 스크립트 기반 삽입을 제공한다.

개발 단위:

  1. equation inventory
  2. equation object count, anchor, caption 여부, raw script 가능 여부.

  3. equation insert via COM

  4. 한컴 수식 스크립트 문자열 입력 smoke test.
  5. 예: 1 over 2, sqrt 2, matrix.

  6. package preservation validator

  7. equation이 있는 문서에 text/image/table write 후 equation object 보존.

  8. package-level equation writer

  9. HWPX 구조 확인 후 별도 진행.

합격 기준:

  • 수식 fixture에서 object count가 보존된다.
  • COM 삽입 수식이 HWP/PDF에서 보인다.
  • caption/cross reference와 연결될 수 있는 식별자를 report한다.

우선순위: P2

Phase 8. 차트/OLE/동영상/소리

목표: 작성보다는 손상 방지와 inventory를 먼저 한다.

개발 단위:

  1. binary object inventory
  2. BinData의 image/OLE/media 구분.
  3. manifest entry와 object reference 연결.

  4. preservation validator

  5. package write 후 binary entry, manifest item, object reference가 유지되는지 검사.

  6. chart inventory

  7. chart object count, source data 가능 여부.

  8. COM-based insert smoke tests

  9. 차트/OLE/동영상/소리는 직접 package writer보다 COM 경로 우선.

합격 기준:

  • OLE/chart/media가 있는 문서를 text write해도 열림/보존된다.
  • binary object 손상 시 validate가 blocking으로 잡는다.

우선순위: P2/P3

Phase 9. 일반 Markdown-to-HWP renderer

목표: 기존 template fill이 아닌 새 문서/일반 문서 생성에서 HWP native 구조를 만든다.

개발 단위:

  1. Markdown AST 도입
  2. heading, paragraph, list, table, image, link, code, bold/italic.
  3. string manipulation 금지, parser 기반.

  4. style profile

  5. 제목/본문/목록/캡션 style mapping.
  6. 기본 HWPX template에서 style clone.

  7. native object rendering

  8. heading as paragraph style.
  9. list as paraHead/numbering.
  10. table as tbl/tr/tc.
  11. image as hp:pic.
  12. link as hyperlink field/control.

  13. round-trip tests

  14. Markdown -> HWPX -> read-text/scan/PDF.

합격 기준:

  • raw Markdown artifact가 문서에 남지 않는다.
  • 표/그림/목록이 실제 HWP 구조다.
  • PDF 대표 페이지가 비어 있지 않고 layout 검증을 통과한다.

우선순위: P3

Phase 10. 시각 회귀 검증

목표: "검증 report는 pass인데 한글에서 보면 깨짐"을 줄인다.

개발 단위:

  1. export-pdf batch
  2. template/candidate 자동 PDF export.

  3. PDF render

  4. 대표 페이지 PNG render.
  5. page count와 key page thumbnails.

  6. visual metrics

  7. blank page detection.
  8. image/object count mismatch.
  9. text overflow heuristic.
  10. table boundary shift heuristic.

  11. golden fixture review

  12. corpus별 expected report.

합격 기준:

  • HWP COM/PDF export가 가능한 환경에서 대표 페이지 이미지가 생성된다.
  • 레이아웃 깨짐이 있으면 markdown report에 페이지/대상 단위로 표시된다.

우선순위: P1/P2

Phase 11. SDK parity backlog

목표: 공식 한글 SDK가 제품 범주로 내세우지만 현재 CLI가 직접 지원하지 않는 기능을 명시적으로 추적하고, 가능한 것은 HWP COM/패키지 래퍼로, 별도 SDK가 필요한 것은 unsupported 상태로 구분한다. 공개 추적 표는 SDK parity matrix에 둔다.

개발 단위:

  1. official SDK gap ledger
  2. 문서 보안: 문서 비밀번호, 배포용/읽기전용 문서 제한, 개인정보 텍스트 암호화가 현재 이름 있는 CLI command와 검증 fixture로 지원되지 않음을 추적한다.
  3. 문서 비교/병합/이력 관리: 표 셀 병합과 구분되는 문서 단위 compare/merge/history 기능이 현재 없으며, 별도 Hancom Docs Compare SDK가 필요한 영역과 HWP COM/패키지 기반 report로 가능한 최소 범위를 분리한다.
  4. 일반 HWP authoring: 캡션, 책갈피, 상호 참조, 차례/색인, 각주/미주/메모, 도형/글상자/글맵시, 수식, 차트/OLE/동영상/소리는 inventory/보존/COM 삽입/패키지 작성 단계를 각각 별도 상태로 둔다.
  5. page/section layout: 용지, 여백, 방향, 단, 구역 나누기, 구역별 쪽 번호 정책은 현재 일반 writer가 없으므로 inventory, COM smoke, package writer 가능성을 순서대로 검증한다.
  6. form control completeness: press field와 checkbox 일부 write를 기준선으로 삼고, radio/combo/edit/button은 control type별 값 의미와 전후 검증 contract가 생기기 전까지 unsupported 또는 skipped_unsafe로 둔다.

  7. SDK parity matrix

  8. 공식 한글 SDK 범주를 view/create/open/save/convert/extract-edit/security/compare-merge-history로 나눈다.
  9. 각 범주에 현재 CLI command, 구현 방식(COM/package), 검증 command, 남은 gap을 매핑한다.
  10. 별도 SDK가 필요한 기능은 CLI backlog와 외부 dependency backlog로 분리한다.

  11. format conversion expansion

  12. 현재 export-pdf 외 HTML/웹페이지/문서 필터 변환 가능성을 HWP COM action 또는 SDK 경로로 조사한다.
  13. 변환 결과는 파일 존재만 보지 않고 text extraction, page/image presence, 기본 링크/표 보존 여부로 검증한다.

  14. document security operations

  15. document password, distribution/read-only document, private-text encryption의 COM action/API 존재 여부를 먼저 확인한다.
  16. 구현 전에는 fixture와 reversible smoke test를 만든다.
  17. 보안 기능은 원본 파일을 직접 덮어쓰지 않고 output-only workflow로 제한한다.

  18. document comparison, merge, and history

  19. Hancom SDK 라인업의 comparison 기능과 HWP product 기능을 분리해서 조사한다.
  20. 현재 repo에서 가능한 최소 범위는 text/table/style-aware report인지, 실제 merge output인지 구분한다.
  21. 별도 SDK 없이는 구현할 수 없는 부분은 명확히 unsupported로 표시한다.

  22. page setup and section layout

  23. paper size, margin, orientation, columns, section break, section-specific numbering을 inventory/write 대상으로 분리한다.
  24. package writer로 가능한 구조 보존과 HWP COM reflow가 필요한 영역을 구분한다.

  25. object placement and form-control completeness

  26. image/shape/form control의 wrap, z-order, anchor, size, crop, rotate, group, lock 속성을 inventory diff 대상으로 추가한다.
  27. radio/combo/edit/button form controls는 checkbox와 별도 write contract를 둔다.

합격 기준:

  • docs/hwp-authoring-feature-roadmap.md 또는 별도 parity report에서 공식 SDK 범주별 current support/gap/verification command가 한눈에 보인다.
  • official SDK gap ledger의 각 항목이 unsupported, inventory-only, COM-smoke, package-writer, verified 중 하나의 상태를 가진다.
  • 보안/비교/병합/변환 기능은 실제 HWP/SDK에서 열리는 fixture와 output-only smoke test 없이는 implemented로 표시하지 않는다.
  • 별도 Hancom SDK가 필요한 기능은 repo 내부 구현 예정 항목과 외부 라이선스/SDK 의존 항목으로 분리한다.
  • 변환/비교/보안 결과물은 원본 파일을 보존하고, 실패 시 partial output을 명시적으로 report한다.

우선순위: P1/P3

추천 개발 순서

  1. 완료: Phase 3.5 일부: picture/control inventory.
  2. 완료: Phase 3.5 일부: package-level replace-image-control.
  3. 완료: Phase 3.5 일부: copy-from-doc image target post-verify.
  4. 완료: Phase 3.5 일부: InsertPicture 단위/usage 방어.
  5. 다음: Phase 3.5 일부: COM/editor-backed replacement fallback과 cleanup diagnostics.
  6. Phase 0 완료분 유지보수: real-world fixture를 계속 추가하고 expected report를 고정한다.
  7. Phase 10 일부: PDF visual smoke harness.
  8. Phase 1: header/footer 신규 영역 생성, COM 기반 편집, rich object support, section page setup.
  9. Phase 2: field/누름틀 named fill.
  10. Phase 3: table authoring 미완료 항목과 formulas inventory.
  11. Phase 4: caption/cross-reference COM insert/refresh workflow.
  12. Phase 5: footnote/endnote preservation과 COM insert.
  13. Phase 6: shape inventory diff와 text box write.
  14. Phase 7: equation inventory와 COM insert.
  15. Phase 8: chart/OLE/media preservation.
  16. Phase 9: 일반 Markdown-to-HWP renderer.
  17. Phase 11 일부: official SDK gap ledger와 SDK parity matrix를 먼저 작성해 문서 보안, 문서 비교/병합/이력, 일반 authoring, page/section layout, form control completeness의 현재 상태를 고정한다.
  18. Phase 11 일부: PDF 외 변환 가능성 조사, 보안/비교/병합 unsupported 범위 확정, 별도 Hancom SDK 의존 항목 분리.

바로 다음 커밋 후보

후보 A: Picture/control inventory

상태: 완료. list-pictures 명령으로 구현됐다.

  • list-pictures 또는 inspect-pictures 명령을 추가한다.
  • gso typeIndex와 package-level hp:pic/BinData/hash/size/position/wrap 속성을 한 report에 연결한다.
  • 실제 HWPX의 특정 그림이 어떤 binary와 속성을 갖는지 COM 없이 확인 가능하게 한다.

이유: 이미지 교체는 target 식별과 before/after 증명이 먼저 안정화되어야 한다.

후보 B: Package-level replace-image-control

상태: 완료. package-level replace-image-control 명령으로 구현됐다.

  • 기존 hp:pic 속성을 보존하면서 연결된 BinData image만 교체한다.
  • source/target before/after hash, pixel size, object property diff를 report에 남긴다.
  • 실패 시 partial output과 검증 실패 이유를 명확히 남긴다.

이유: copy-from-doc/InsertPicture 조합은 특정 기존 그림 교체 요구에 충분히 안정적이지 않다.

후보 C: copy-from-doc image target post-verify

상태: 완료. image/gso source를 HWPX control:gso:<index> target에 붙여넣은 경우 output package를 post-verify한다.

  • copy-from-doc report를 COM 호출 성공과 실제 package 변경 성공으로 분리한다.
  • source image hash와 output target image hash, target picture count 보존 여부를 검증한다.
  • 검증 실패 시 post_verify=failed를 출력하고 명령을 nonzero로 종료한다.

이유: "붙여넣기 호출 성공"과 "원하는 그림이 바뀜"은 다르다.

후보 D: InsertPicture unit guard and docs

상태: 완료. HWP COM InsertPicture width/height guard와 usage/docs 경고가 추가됐다.

  • CLI usage와 docs에 width/height 단위 주의사항을 추가한다.
  • 1000을 넘는 width/height 값은 HWPX hp:sz를 잘못 넣은 것으로 보고 거부한다.
  • 기존 object 크기 보존은 replace-image-control로 유도한다.

이유: HWPX 내부 hp:sz 값을 COM InsertPicture width/height로 착각하면 문서가 크게 깨진다.

후보 E: COM cleanup diagnostics

상태: 일부 완료. probe-copy-from-doccopy-from-doc report에 COM 작업 전후 HWP process snapshot이 추가됐고, 새 HWP process가 남으면 실패시키는 --strict-cleanup 진단 옵션이 들어갔다.

  • COM-backed 명령 report에 시작/종료 HWP process summary를 남긴다.
  • 사용자 HWP 창을 강제 종료하지 않는 strict cleanup 진단 옵션을 검토한다.

이유: 제목 없는 HWP 프로세스 잔류는 파일 잠금과 다음 작업 지연의 반복 원인이다.

후보 F: PDF visual smoke harness

상태: 구현 2차. visual-smoke-corpus 명령으로 feature corpus scan report와 PDF export 결과를 한 report 묶음으로 남긴다. HWP COM이 건강한 환경에서 PDF가 실제 생성돼야 pass이며, known failure는 fileNameOrPath=exitCode[:reasonFragment] exact xfail contract로만 허용한다. PDF page/content-stream/text/image/drawing metrics와 blank 의심 review-needed 신호를 report에 남긴다. PNG render와 page thumbnails는 아직 다음 개발 단위다.

  • 로컬 feature fixture corpus의 대표 fixture를 PDF로 export하는 smoke command 정리.
  • scan report와 PDF export 결과를 같은 report 묶음으로 남긴다.
  • HWP COM이 불안정하면 diagnose-com과 visible export를 우선 실행한다.

이유: scanner inventory는 구조 신호만 보므로, 실제 한글/PDF 표시 여부를 별도 검증해야 한다.

후보 G: Header/footer rich authoring

상태: 구현 3차. set-header-footer-apply-page-type 명령으로 기존 header/footer reference의 applyPageTypeBOTH|EVEN|ODD 중 하나로 package-level 변경한다. add-header-footer-reference 명령은 이미 존재하는 idRef를 재사용해 새 reference만 추가하며, 같은 section/kind의 applyPageType 중복은 거부한다. add-header-footer-text 명령은 section 내 신규 header/footer idRef의 단순 1문단 text body와 reference를 함께 추가한다. rich object 편집은 아직 별도 단위다.

  • header/footer 내부 그림/표/도형 포함 rich object 작성과 보존 검증.
  • section별 page setup과 COM-backed header/footer editing smoke test.

이유: 기본 inventory/text write/page-number smoke, 기존 body reference 재사용, 단순 text body 생성은 들어왔고, 남은 실무 gap은 rich object 편집과 section setup이다.

후보 H: Field/form write contracts

상태: 구현 1차. list-fields report가 package field/form item별 write contract를 표시한다. press-field text는 package-text, checkbox value는 package-value로 지원하고, radio/combo/edit/button/generic field는 inventory-onlyskipped_unsafe로 남긴다.

  • generic field, radio, combo, edit, button control의 write contract를 field type별로 분리한다.
  • 값 쓰기 전후 package value/currentText mismatch 정책을 정한다.
  • unsupported control은 skipped_unsafe로 남기고 implemented로 표시하지 않는다.

이유: field inventory와 press/checkbox 일부 쓰기는 들어왔고, 남은 위험은 form control별 의미가 다른 값을 한 방식으로 처리하는 것이다.

후보 I: SDK parity matrix

상태: 구현 1차. SDK parity matrix에서 공식 Hwp SDK 범주를 현재 CLI command, 검증 command, 남은 gap, unsupported/needs-SDK 상태로 매핑한다.

  • 공식 한글 SDK 범주와 현재 CLI command를 표로 매핑한다.
  • export-pdf, scan-hwpx-features, list-fields, list-controls, table/header/footer commands의 검증 command를 같이 적는다.
  • 문서 보안, 비교/병합/이력 관리, HTML 변환처럼 현재 래퍼가 없는 기능은 unsupported 또는 needs-SDK로 표시한다.
  • 일반 HWP authoring 공백은 캡션/책갈피/상호 참조/차례/색인/각주/미주/메모/도형/글상자/글맵시/수식/차트/OLE/동영상/소리 단위로 나누고, 각 항목의 현재 상태를 inventory-only와 writer 없음으로 분리한다.
  • page/section layout은 용지/여백/방향/단/구역 나누기/구역별 쪽 번호 정책으로 쪼개고, form control은 press/checkbox/radio/combo/edit/button별 write contract 상태를 표기한다.

이유: "한글 SDK에는 있는데 우리 프로젝트에는 없는 기능"을 일회성 점검이 아니라 추적 가능한 backlog로 바꿔야 한다.

당장 하지 말아야 할 것

  • package XML로 차트/OLE/수식/복잡한 도형을 바로 생성하기.
  • header/footer/각주/누름틀 fixture 없이 구현 완료라고 주장하기.
  • 전체 Markdown 문서를 replace-markdown 류로 밀어 넣고 HWP native 구조라고 부르기.
  • HWP COM으로 한 번 열렸다는 사실만으로 package 구조 보존을 생략하기.
  • 별도 Hancom SDK가 필요한 비교/병합/보안 기능을 COM action 추정만으로 supported라고 표시하기.