v1.0.0 — Stable Release
Changelog
모든 주요 변경사항이 이 문서에 기록됩니다.
포맷은 Keep a Changelog, 버전은
Semantic Versioning 을 따릅니다.
Unreleased
[2.0.0] — 2026-04-19 — 🚀 Major redesign (dual-layer API + Quarto docs)
v1.0 이후 약 4일간 진행한 전면 재설계. public API break 을 허용한 클린컷
릴리즈로, 구조/퍼사드/문서 파이프라인을 한꺼번에 갈아엎었습니다.
🎯 핵심 변경
- 이중 레이어 API
- 고수준:
hwpapi.App(슬림 퍼사드) +app.doc(Document 모듈) - 저수준:
hwpapi.low.*—actions,parametersets,engine이 공식 escape hatch - 같은 작업에 두 개의 공식 진입점을 남기지 않음 (Principle #1)
- 고수준:
- Collection 일관성 —
Protocol[T]기반 공통 인터페이스app.doc.fields / bookmarks / hyperlinks / images / paragraphs / styles / tables- 모두 dict-like + iterable + filterable 로 동일 멘탈 모델
- Element value objects —
Paragraph,Run,Table,Cell경량 객체
(.style,.charshape,.parashape,.runs,.cell(r, c).text, ...) - Context / IO / Errors 모듈 신설
hwpapi.context.{charshape_scope, parashape_scope, styled_text}hwpapi.io.{open_file, new_document, export_pdf, export_image, export_text}hwpapi.errors— 4단계 예외 계층 +wrap_com_error()컨텍스트 매니저
- Quarto 단일 문서 사이트 —
docs/43페이지, quartodoc 기반 자동 API 레퍼런스- Home / Getting Started / Guide / Recipes / Reference / Design 6-섹션
- 사이트 IA == import tree 1:1 매핑 (Principle #5)
Removed (Breaking)
hwpapi/classes/전체 삭제 (~4,924 LOC) — accessors/controls/convert/debug/
fields/images/lint/selection/shapes/styles/view 모두 제거Apppublic 멤버 82 → ~12 로 축소 (v1 accessor/preset/template/config/... 전면 제거)app.charshape = {...}프로퍼티 →charshape_scope(app, **fmt)컨텍스트로 이전app.preset.*,app.template.*,app.config.*,app.lint(),app.view.*,
app.debug.*,app.convert.*,app.sel.*,app.move.*,app.table.*,
app.cell.*,app.page.*— 모두 제거 (필요 시 Recipes 에서 재조립)hwpapi.parametersets(top-level) →hwpapi.low.parametersets로 이동hwpapi/actions.py→hwpapi/low/actions.pyhwpapi/core/engine.py→hwpapi/low/engine.pynbs/nbdev 기반 문서 파이프라인 폐기 (아카이브)docs/*.md(v1 계획 문서 10개) →docs/archive/이동
Added
hwpapi/collections/패키지 — fields, bookmarks, hyperlinks, images,
paragraphs, styles, tables (각 Collection + Element value object)hwpapi/document.py—Document퍼사드 (cached_property 로 lazy-wire)hwpapi/low/— raw actions / parametersets / engine escape hatchhwpapi/errors.py—HwpApiError,ConnectionError,ActionFailedError,
InvalidArgumentError,FileIOError+wrap_com_error()hwpapi/context/scopes.py—charshape_scope,parashape_scope,styled_texthwpapi/io/—open_file,new_document,export_pdf,export_image,export_textdocs/Quarto 사이트 (43 페이지, 0 warnings) — getting-started / guide /
recipes / reference / design / adr.github/workflows/deploy-docs.yaml— GitHub Pages 자동 배포tests/conftest.py—SetMessageBoxMode(0x111111)로 HWP 다이얼로그 전부 자동 Yes- v1→v2 Migration guide (80+ 매핑 행)
Fixed / Hardened
- pytest 전체 세션에서 HWP 다이얼로그가 더 이상 블로킹하지 않음
- griffe 2.x API drift 대응 —
griffe<1.0핀 ([project.optional-dependencies].docs) - 순환 import 제거 (
low/engine.py의 deadfrom hwpapi.classes import ...제거)
Tests
- 단위 테스트: 1,388 (v1.0) → 1,373 (v2.0, -15: v1 classes/ 테스트 사라짐, +30 새
Element 테스트, +29 새 context/io/errors 테스트). 전체 녹색.
Migration
클린컷이므로 코드 변경 필수입니다.
- 빠른 점검:
https://JunDamin.github.io/hwpapi/getting-started/migration-v1-to-v2.html - v1 에 머무르려면
pip install "hwpapi<2"또는git checkout v1.x.
[1.0.0] — 2026-04-15 — 🎉 Production / Stable release
v0.0.11 부터 v0.0.26 까지 16개의 마이너 릴리즈를 거쳐 도달한 v1.0 Stable.
주요 API 는 안정화되었으며, 버그/매직넘버/문서 블로커가 모두 해결되었습니다.
🎯 v1.0 성취
- 18개 accessor (move, sel, documents, fields, bookmarks, hyperlinks, images,
styles, controls, cell, table, page, convert, view, lint, template, config,
preset, debug) 로 도메인별 API 그룹핑 - 8개 context manager (silenced, suppress_errors, batch_mode, undo_group,
charshape_scope, parashape_scope, use_document, debug.trace) - 11개 preset (striped_rows, title_box, subtitle_bar, summary_box,
table_header, table_footer, toc, page_numbers, page_border, highlight_yellow) - ENUM 시스템 — BORDER_TYPE_MAP, HATCH_STYLE_MAP, CELL_APPLY_TO_MAP,
DIAGONAL_FLAG_MAP + Color 클래스 상수 16개 hwpapi.units모듈 — mm/cm/inch/pt ↔ HWPUNIT 변환- 25개 객체별 API 문서 (
nbs/02_api/디렉토리) - 13개 튜토리얼 — 9개 사용 사례 + 4개 신규 (Accessors, Presets Gallery,
Batch Workflow, Debug Tools) - 1388/1388 단위 테스트 통과
Added (v0.0.26 이후)
hwpapi.functions.cell_addr(app)/navigate_until(app, action)—
HWP 12 의Run()None 반환 회피용 공유 헬퍼Config.apply_defaults()—default_font/default_size실제 적용
메소드 (이전엔 dict 저장만)Color.RED,Color.BLUE, ...,Color.NAVY— 16 색상 클래스 상수resolve_enum(map, value)— 문자열/정수 양방향 helperhwpapi.units모듈 — App 인스턴스 없이도 호출 가능한 단위 변환
Changed
version = 1.0.0+Development Status :: 5 - Production/Stablerequires-python = ">=3.9"(이전 3.7 — EOL)[project.optional-dependencies]추가 —dev,test,docsset_charshape(facename=...)— 단일 인자가 7개 facename 으로 자동 fan-outfind_text(facename=...)— 다국어 fan-outset_cell_border(top="solid", bottom="double")— 문자열 enum 지원set_cell_color(hatch_style="diagonal_cross")— 문자열 지원
Fixed
replace_font(old, new)가old를 무시하던 버그 — HFindReplace pset
으로 재작성,old폰트만 정확히 교체 (replace_all=True로 legacy 동작 opt-in)app.config.default_fontno-op —apply_defaults()메소드 추가App.charshape()method vscharshapeproperty 이름 충돌 — method 완전 제거api.Run()None 반환 11곳 — cell_addr 추적 기반으로 전환app.view.zoom()의PictureScale액션 —ZoomRateproperty 로 교체- CellBorderFill 의 FillAttr 경로 —
SelCellsBorderFill.FillAttr로 수정 _apply_cell_bg가 작동 안 하던 버그 — HParameterSet chain 정확한 경로
Deprecated (v1.1 에서 제거 예정)
Field 관련 10개 — app.fields accessor 로 대체:
| 레거시 | 신규 |
|---|---|
app.create_field(name) |
app.fields.add(name) |
app.set_field(n, v) |
app.fields[n] = v |
app.get_field(n) |
app.fields[n].value |
app.field_exists(n) |
n in app.fields |
app.move_to_field(n) |
app.fields[n].goto() |
app.delete_field(n) |
app.fields.remove(n) |
app.delete_all_fields() |
app.fields.remove_all() |
app.rename_field(o, n) |
app.fields.rename(o, n) |
app.field_names |
list(app.fields) |
app.fields_dict |
app.fields.to_dict() |
Soft deprecation 7개 (docstring 안내만):
app.insert_bookmark→app.bookmarks.addapp.insert_hyperlink→app.hyperlinks.addapp.replace_brackets_with_fields→app.fields.from_bracketsapp.get_charshape/app.set_charshape→app.charshapepropertyapp.get_parashape/app.set_parashape→app.parashapeproperty
마이그레이션 가이드: docs/MIGRATION_v1.md
Removed
App.charshape()deprecated builder method (property 와 이름 충돌, v0.0.7 부터 호출 불가였음)
v1.1 로드맵 (예정)
- legacy field method 10개 완전 제거
- App 클래스 분할 (103 methods → 5 mixins in
core/ops/) HwpError예외 계열 (HwpFieldNotFound, HwpFileLocked 등)python -m hwpapi.migrate <file.py>AST 자동 변환 도구- Context manager 명명 통일 (
using_X패턴) - mypy + ruff + pre-commit
[0.0.26] — 2026-04-15 — v1.0 Phase 4: 객체별 API 문서 페이지
사용자 지적 ("Unit 같은 것도 홈페이지에 설명이 잘 있어야 하지 않을까?
모든 객체를 설명해주는 거지") 반영.
Added
nbs/02_api/ — 객체별 .qmd 페이지 25개 자동 생성:
core/(app, engine, document)navigation/(move, selection)collections/(fields, bookmarks, hyperlinks, images, controls, styles)structure/(cell, table, page)transform/(convert, view)quality/(lint, template, config)presets/(presets — 11 메소드)debug/(debug)data/(shapes — CharShape/ParaShape/PageShape)utilities/(units, enums, functions)index.qmd— 전체 매트릭스
각 페이지: import + 한 줄 요약 + docstring + 메소드/속성 표 (시그니처 + 한 줄 설명) + cross-link.
utilities/units.qmd — 사용자 친화적으로 보강:
- Quick Start 코드 6개 형태
- 함수 매트릭스 (mm/cm/inch/pt + parse)
- 변환표 (1mm = 283 HWPUNIT 등)
- 페이지 크기/폰트/테두리 사용 예
utilities/enums.qmd — Phase 3 ENUM 종합 가이드:
- BORDER_TYPE_MAP 16종 표
- HATCH_STYLE_MAP 13종 표
- CELL_APPLY_TO_MAP, DIAGONAL_FLAG_MAP
- Color 클래스 상수 16개
- resolve_enum 사용법
- 기존 35개 MAP 목록
Changed
nbs/_quarto.yml sidebar 확장: 기존 4 섹션에 "📖 API 레퍼런스" 트리
신설 — 카테고리별 8개 sub-section, 25개 페이지 직접 navigate 가능.
nbs/index.qmd 카드 변경: '익숙한 단위' 카드를 '익숙한 단위 / Enum'
으로 확장 — units, Color 상수, set_cell_border 예제 + 링크 2개.
v1.0 release 준비도
- 모든 P0 bug fix (v0.0.24)
- silent fail 가시화 (v0.0.24)
- BorderType / HatchStyle / Color 등 매직 넘버 enum 전환 (v0.0.25)
- 모든 18 accessor + dataclass + units + presets 02_api/ 페이지 보유 (v0.0.26)
- sidebar 에 "API 레퍼런스" 트리 노출 (v0.0.26)
- units.qmd / enums.qmd 가 homepage 카드에서 1-click 도달 (v0.0.26)
- tests/generate_doc_artifacts.py demo 13+개 실제 HWP 재생성
- CHANGELOG 정리 + v1.0.0 tag
[0.0.25] — 2026-04-15 — v1.0 Phase 3: ENUM 통일 + Color 상수
사용자 지적 ("선 모양도 enum 같은 걸로 되어야 할 거 같은데?") 반영.
매직 넘버 (BorderType=8, hatch_style=6) → 사용자 친화 이름 ("double", "diagonal_cross").
Added
hwpapi/parametersets/mappings.py — 4개 신규 enum/MAP:
BORDER_TYPE_MAP— 16종 선 종류 ("none","solid","dash","dot",
"dash_dot","long_dash","double","wave","thick_3d"등)HATCH_STYLE_MAP— 13종 빗금 패턴 ("horizontal","diagonal_cross",
"dense_horizontal"등)CELL_APPLY_TO_MAP— 셀 적용 범위 ("current"/"selected"/"all")DIAGONAL_FLAG_MAP— 대각선 비트플래그 ("top"/"middle"/"bottom"/"all")resolve_enum(map, value)헬퍼 — 문자열/정수 양방향 해석 (case-insensitive)
Color 클래스 상수 16개 (properties.py):
Color.RED, Color.GREEN, Color.BLUE, Color.BLACK, Color.WHITE,
Color.YELLOW, Color.CYAN, Color.MAGENTA, Color.ORANGE, Color.PURPLE,
Color.PINK, Color.BROWN, Color.GRAY, Color.LIGHT_GRAY,
Color.DARK_GRAY, Color.NAVYget_rgb_tuple named-color 5 → 16개 확장 (functions.py)
Changed
set_cell_border(top="solid", bottom="double", ...)— 문자열 enum
지원. 기존 정수도 그대로 작동.set_cell_color(hatch_style="diagonal_cross", ...)— 문자열 지원.
추가로 FillAttr 위치 버그 fix (SelCellsBorderFill.FillAttr 사용 + ApplyTo=2)
Tests
tests/test_enums.py — 14 신규 테스트 (BORDER_TYPE_MAP / HATCH_STYLE_MAP /
CELL_APPLY_TO_MAP / DIAGONAL_FLAG_MAP / resolve_enum / Color.RED 등 16 상수).
전체 1388/1388 통과.
[0.0.24] — 2026-04-15 — v1.0 Phase 1: P0/P1 버그 fix
v1.0 release 전 분명히 깨진 5개 P0 + P1 버그 수정. 사용자 지적
("폰트 같은 건 잘 모르겠다") 가 정확히 깨진 부분.
Fixed (P0)
P0-1: app.convert.replace_font(old, new) 가 old 인자를 무시
(hwpapi/classes/convert.py)
- 이전: SelectAll → set_charshape(facename_*=new) —
old무시, 문서 전체 덮어씀 - 이후: HFindReplace pset 의 FindCharShape/ReplaceCharShape facename 7개
설정 + AllReplace 액션 —old폰트 영역만 정확히 교체 - legacy 동작은
replace_all=True로 명시적 opt-in
P0-2: app.config.default_font no-op
(hwpapi/classes/lint.py)
- 이전: dict 저장만, 어디서도 적용 안 됨
- 이후:
app.config.apply_defaults()메소드 추가 — 명시 호출 시 charshape- parashape 에 실제 적용 (font 7개 facename fan-out + size + line_spacing)
P0-3: App.charshape() method vs charshape property 이름 충돌
(hwpapi/core/app.py)
- deprecated method 가 property 에 의해 완전히 shadowed — 호출 불가
- 메소드 완전 제거, property 만 유지
P0-4: app.api.Run() None 반환 패턴 11곳
(hwpapi/classes/accessors.py,
hwpapi/core/app.py)
- HWP 12 의 Run() 이 항상 None 반환 —
if not Run(...): break즉시 탈출 hwpapi.functions.cell_addr(app)+navigate_until(app, action)신규
공유 헬퍼 — KeyIndicator()[8] 의 셀 주소로 진행 추적- TableAccessor.header_row/footer_row/clean_excel_paste, App.insert_table
cursor 복귀, Selection.current_word 모두 fix
P0-5: app.view.zoom() 의 PictureScale 액션 잘못됨
(hwpapi/classes/view.py)
- 이전:
CreateAction("PictureScale")— 그림 크기 조절용 액션 (zoom 아님) - 이후:
XHwpDocumentInfo.ZoomRateproperty 직접 설정. fallback 으로
HAction.Execute("ScreenZoom", HZoom)
Fixed (P1)
P1: set_charshape(facename=...) / find_text(facename=...) 다국어 fan-out
- 이전: FaceNameHangul 만 설정 — 영문/일본어 텍스트 매칭 실패
- 이후: 7개 facename (Hangul/Latin/Japanese/Hanja/Other/Symbol/User) 모두에
자동 fan-out. 사용자가facename_hangul등을 명시하면 그 값이 우선
Added
hwpapi.functions.cell_addr(app)— 현재 셀 주소 ("A1" 등) 반환
(hwpapi/functions.py)hwpapi.functions.navigate_until(app, action, max_iters)—
cell_addr 변화로 루프 종료 감지 헬퍼
Tests
tests/test_convert.py— replace_font 가 AllReplace 사용 + replace_all
legacy + empty old 검증 (3개 신규)tests/test_view.py— zoom 이 ZoomRate property 설정 확인 (4개 수정)- 전체 1374/1374 통과
[0.0.22] — 2026-04-15 — 튜토리얼 강화 · 4개 신규 튜토리얼 추가
v0.0.14~21 의 18개 accessor 와 30+ 프리셋이 튜토리얼에 반영이 안 돼 있던
것을 보강. 4개 신규 튜토리얼 추가, 기존 튜토리얼 2개에 discovery 포인터 삽입.
Added
10_accessors_overview.ipynb— 18개 accessor 전체 투어.- 매트릭스 표 + 카테고리별 소개 (Navigation/Collections/Structure/
Transform/Quality/Presets) - 각 accessor 의 대표 메소드 + 예제 1~2개
- 8개 context manager 목록 + 사용법
- 매트릭스 표 + 카테고리별 소개 (Navigation/Collections/Structure/
11_presets_gallery.ipynb— 문서 꾸미기 프리셋 쇼케이스.- 11개 preset 의 before/after 예제
- 조합 레시피: 공공 보고서 / 컬러 보고서
12_batch_and_workflow.ipynb— 대량 처리 + context manager.- silenced / suppress_errors / batch_mode / undo_group /
charshape_scope / use_document - 3개 실전 workflow: 급여명세서 1000장 · 폰트 재귀 교체 · 디렉터리 품질 감사
- silenced / suppress_errors / batch_mode / undo_group /
13_debugging_tools.ipynb— 디버깅 / 품질 / 설정.app.help()/repr(app)discoveryapp.debug.state/print/timing/traceapp.lint()+ CI 대량 품질 감사 예제app.template.save/apply+ 대량 적용app.config+ 팀 공유 json
Changed
_quarto.ymlsidebar 재구성 — 3개 섹션:- 📘 기초 튜토리얼 (10_accessors_overview 추가)
- 📗 사용 사례 (Mail Merge 노출)
- 🎨 v0.0.14+ 신규 기능 (11, 12, 13)
index.qmd랜딩 카드 추가 — 신규 튜토리얼 3개 + 새 기능 미리보기 bullet 10개03_feature_tour.ipynb— 상단에 신규 기능 pointer 섹션 삽입01_app_basics.ipynb—app.help()tip 박스 삽입
Tests
영향 없음 — 튜토리얼은 런타임 테스트 대상 아님. 1362/1362 유지.
[0.0.21] — 2026-04-15 — 테스트 도메인별 재구성
Phase C. 버전별 테스트 파일(test_v014_features.py ~ test_v020_deprecations.py)
를 도메인별 13개 파일 로 재편. 이제 "Selection 관련 테스트" 를 찾으려면
tests/test_selection.py 하나만 열면 된다.
Changed
-
기존 7개 버전별 파일 → 13개 도메인별 파일:
test_selection.py(18) — Selection accessor 전반test_images.py(5) — Images accessortest_presets.py(20) — 모든 Preset 메소드test_table_accessor.py(8) — TableAccessor batch + clean_excel_pastetest_debug.py(12) — Debug (state/trace/timing/print)test_context_managers.py(2) — batch_mode, undo_grouptest_convert.py(6, 14 실행) — Convert + _int_to_korean parametrizetest_view.py(9) — View accessortest_lint.py(10) — Lintertest_template.py(4) — Templatetest_config.py(8) — Configtest_discovery.py(9) — app.help() + reprtest_deprecations.py(12) — 레거시 API DeprecationWarning
-
각 파일은 AST 파싱 기반 자동 재분배. 공통 imports + 관련 fixture 는 여러
파일에 복제되어 독립 실행 가능 (pytest 단일 파일 실행 친화).
Tests
테스트 수는 그대로 유지 (1362/1362 통과) — 재배치만 수행.
[0.0.20] — 2026-04-15 — 레거시 API DeprecationWarning + API_GUIDE.md 재작성
Phase B 중복 제거. 17개 레거시 method 에 DeprecationWarning 부착 (호환
유지). hwpapi.* 패키지 내부에서 호출되면 경고 무시 — accessor 가
레거시 method 를 내부적으로 delegate 해도 사용자에겐 spam 없음.
Added
hwpapi.core.app._warn_legacy(old, new)— 스마트 deprecation 헬퍼.
caller frame 의 모듈이hwpapi.로 시작하면 조용히 통과, 사용자
코드에서 호출되면 DeprecationWarning 발생.
Changed
- 10개 레거시 field 관련 method 에 DeprecationWarning 부착:
app.create_field→app.fields.addapp.set_field→app.fields[n] = vapp.get_field→app.fields[n].valueapp.field_exists→n in app.fieldsapp.move_to_field→app.fields[n].goto()app.delete_field→app.fields.remove(n)app.delete_all_fields→app.fields.remove_all()app.rename_field→app.fields.rename(o, n)app.field_names(property) →list(app.fields)app.fields_dict(property) →app.fields.to_dict()
app.insert_bookmark/app.insert_hyperlink/app.replace_brackets_with_fields:
soft deprecation note in docstring (Fields/Bookmarks/Hyperlinks
accessor 가 현재 이들을 호출하므로 warning 은 생략).docs/API_GUIDE.md재작성 — 18개 accessor 매트릭스 표, context
manager 목록, property 목록, legacy→신규 마이그레이션 표 추가.App.field_names_internal()— warning 없는 내부용 field list (accessor 와 fields_dict 가 사용).
Tests
12 개 신규 단위 테스트 (tests/test_v020_deprecations.py):
_warn_legacy기본 동작hwpapi.*모듈에서 호출 시 silent 확인- 각 레거시 method 가 warning 발생시키는지
- Fields accessor 가 레거시 호출해도 사용자 코드에 warning 안 가는지
전체 1362/1362 통과.
[0.0.19] — 2026-04-15 — Discovery · app.help() + 상태 요약 repr
Phase A 사용자 경험 개선 (18개 accessor 가 97개 method 속에 숨어있던 문제 해결).
Added
app.help()— App 에서 사용 가능한 accessor·context manager·주요
property 를 6개 카테고리로 그룹핑해서 출력. 사용자가app.찍고
혼란스러워하지 않도록 최초 학습 곡선을 대폭 축소.- Navigation & Selection (move, sel)
- Collections (documents, fields, bookmarks, hyperlinks, images, styles, controls)
- Structure (cell, table, page)
- Transform & View (convert, view)
- Quality & Templates (lint, template, config)
- Presets & Debug (preset, debug)
- Context managers (8개)
App.__repr__— 상태 요약을 한 줄로:
App(visible=True, version='13.0.0', docs=2, page=5/20).
예외 완전 안전 (초기화 안 된 인스턴스에도 작동).App._ACCESSOR_MAP— 문서화/help 용도의 공개 가능한 카테고리 매핑.App._CONTEXT_MANAGERS— 동일 패턴으로 context manager 목록.
Changed
__init__accessor 할당부 재구성 — 도메인별로 그룹핑 + 한 줄 주석.
시대순 ("v0.0.12 추가", "v0.0.14 추가") 에서 용도 기반으로 전환.__str__/__repr__분리 — 기존에는__repr__ = __str__으로
파일 경로만 표시됐으나, 이제__str__는 파일 경로,__repr__은
상태 요약. 초기화 안 된 인스턴스에서도 안전하게 작동.
Tests
9 개 신규 단위 테스트 (tests/test_v019_discovery.py).
전체 1350/1350 통과.
[0.0.18] — 2026-04-15 — Linter · Template · Config
Added
app.lint() (classes/lint.py) — 문서 품질 체크:
- callable accessor:
report = app.lint()반환 - 검사 항목:
- 긴 문장 (기본 80자 초과) →
report.long_sentences - 긴 문단 (기본 500자 초과) →
report.long_paragraphs - 빈 문단 →
report.empty_paragraphs - 연속 공백 →
report.double_spaces - 끝 공백 →
report.trailing_whitespace
- 긴 문장 (기본 80자 초과) →
report.has_issues,.issue_count,.summary헬퍼
app.template (classes/lint.py) — 문서 템플릿:
template.save(path)— 현재 charshape/parashape/page 설정을 JSON 으로template.apply(path)— JSON 템플릿을 현재 문서에 적용
app.config (classes/lint.py) — App 선호도:
config.default_font,.default_size,.default_line_spacing,
.default_table_style,.paletteconfig.update(**kw),.reset(),.to_dict()config.save(path="~/.hwpapirc")/.load(path)
Tests
22 개 신규 단위 테스트 (tests/test_v018_features.py).
전체 1341/1341 통과.
[0.0.17] — 2026-04-15 — Convert · View · more presets
Added
app.convert (classes/convert.py):
convert.number_to_korean(text=None)— 숫자 → 한글숫자
("1,234,567" → "일백이십삼만사천오백육십칠").text=None이면
현재 선택 영역 변환. 최대 경(10^16) 까지.convert.wrap_by_word()/.wrap_by_char()— 줄 나눔 방식 전환convert.replace_font(old, new)— 문서 전체 폰트 일괄 교체
app.view (classes/view.py):
view.zoom(percent)— 10~500% 클램프view.zoom_fit_page()/.zoom_fit_width()/.zoom_actual()view.zoom_current— 현재 확대율 read-only propertyview.scroll_to_cursor()view.full_screen()/.exit_full_screen()view.page_mode()/.draft_mode()view.toggle_rulers()
추가 Presets (presets/__init__.py):
preset.page_border(enable, style)— 바탕쪽 테두리 (편집 영역 디버그)preset.highlight_yellow(toggle=True)— 선택 영역 노란 배경 토글preset.summary_box(text, variant, bg_color)— 강조 박스
Tests
30 개 신규 단위 테스트 (tests/test_v017_features.py).
전체 1319/1319 통과.
[0.0.16] — 2026-04-15 — 개발자 생산성 · batch/undo/debug · 표 일괄 서식
Added
Context managers (core/app.py):
with app.batch_mode(hide=True):— 대량 처리 시 화면 숨김 + dialog 억제- ScrollFollow off. 종료 시 자동 복원. 일반 대비 5~10배 빠름.
with app.undo_group("설명"):— 블록 내 모든 편집을 단일 undo 경계로 묶음.
app.debug (classes/debug.py) — 디버깅 accessor:
debug.state()— 커서, 페이지, 선택, charshape, in_table, 열린 문서 수,
visible, version, filepath 를 dict 로 덤프debug.print()— state 를 예쁘게 출력debug.timing(fn, *args)— 함수 호출 시간 측정 (ms)with debug.trace():— 블록 내 모든Run()호출 로그
표 일괄 서식 (classes/accessors.py TableAccessor):
table.header_row(bold, bg, text_color)— 첫 행 서식 일괄table.footer_row(bold, bg, text_color)— 마지막 행 서식 일괄table.current_row(bold, bg, text_color)— 현재 행 서식table.align(horz, vert, scope)— 정렬 일괄 적용
(scope:"current_cell" | "current_row" | "current_col" | "all")
Tests
23 개 신규 단위 테스트 (tests/test_v016_features.py).
전체 1289/1289 통과.
[0.0.15] — 2026-04-15 — Preset Phase 1 · structure + TOC + spacing
Added
Structure presets (승승아빠 매크로 Alt+1, Alt+2 이식):
app.preset.title_box(text, subtitle, bg_color, font_size)app.preset.subtitle_bar(text, bg_color)
Table header/footer (Alt+4, Alt+5, Alt+Shift+4, Alt+Shift+5):
app.preset.table_header(color="sky", text_color="#FFFFFF", rows=1)app.preset.table_footer(color="gray", rows=1)- 색상 preset:
"gray" | "sky" | "dark_blue" | "green" | "red"또는 hex
Navigation (Alt+3, 쪽번호 매크로):
app.preset.toc(with_bookmarks=True, dot_leader=True, levels=3)— 점끌기탭 TOCapp.preset.page_numbers(position, format, header_filename)
Selection — 자간/장평 (Alt+Shift+8, Alt+Shift+9):
app.sel.compress(step=1)— 자간/장평 동시 축소app.sel.expand(step=1)— 자간/장평 동시 확대
Fixed
while app.api.Run(...)패턴을for _ in range(500)으로 교체 —
병든 표(500행 이상)나 mock 테스트에서 무한 루프 방지 (clean_excel_paste,
striped_rows, table_header, table_footer 모두).
Tests
16 개 신규 단위 테스트 (tests/test_v015_features.py).
전체 1266/1266 통과.
[0.0.14] — 2026-04-15 — Presets · Images · Selection accessors
DOCUMENT_PRESETS_PLAN.md 의 Phase 1 착수. 승승아빠 매크로에서 범용성
높은 기능을 추려 Python API 로 이식.
Added
app.preset(Presets) — 문서 꾸미기 프리셋 accessor.preset.striped_rows(colors=[...], header_color=None)— 줄무늬 표 (zebra).
app.images(Images) — 이미지 control 컬렉션.- iter / len /
images[i]— 이미지 순회 images.resize_all(width="100mm", keep_ratio=True)— 일괄 크기 조정images.grayscale_all()— 흑백 변환
- iter / len /
app.sel(Selection) — 선택 동작 accessor.
(app.selection은 str property 로 그대로 유지,app.sel은app.move와 대칭인 accessor.)sel.current_word()/.current_line()/.current_paragraph()/.current_sentence()sel.to_paragraph_end()/.to_paragraph_begin()/.to_line_end()/.to_line_begin()sel.to_document_end()/.to_document_begin()sel.expand_char(n)/.expand_word(n)sel.clear()/sel.text/sel.is_empty
app.table.clean_excel_paste()— 엑셀→HWP 붙여넣은 표의 빈 행/열/공백 정돈
(승승아빠 매크로엑셀_복사표_숫자_빈칸지우기의 Python 포팅).
Tests
19 개의 새 단위 테스트 (tests/test_v014_features.py).
전체 1250/1250 통과 (regression 0).
[0.0.13] — 2026-04-15 — V1 Phase 1 · Fluent API
Changed
V1.0 청사진의 "모든 set 메소드에 return self 추가" 항목 이행.
기존 None 반환처에 영향 없음 — 반환값을 쓰지 않는 코드는 그대로
작동, 반환값을 체이닝에 쓰는 새 코드도 자연스럽게 작성 가능:
app.insert_text(...)→selfapp.styled_text(...)→selfapp.insert_heading(...)→selfapp.insert_table(...)→selfapp.insert_hyperlink(...)→selfapp.insert_bookmark(...)→selfapp.insert_paragraph_break()→selfapp.insert_page_break()→selfapp.insert_line_break()→selfapp.insert_tab()→self
값을 반환해야 하는 메소드 (save → 경로, open → 경로,
find_text → bool, replace_all → count, page_count 등)
는 그대로 유지. 이는 V1.0 청사진의 "prefix 기반 분류" 원칙에 부합.
Added
-
Fluent chain 사용 예:
(app .insert_heading("보고서", level=1) .insert_text("1. 개요\n") .insert_paragraph_break() .insert_table(rows=3, cols=4) .insert_text("서명: ") .styled_text("대표이사", bold=True) .insert_paragraph_break())
-
9개의 Fluent API 단위 테스트 (
tests/test_fluent_api.py).
[0.0.12] — 2026-04-15 — V1 Phase 1 · Fields/Bookmarks/Hyperlinks accessors + charshape/parashape properties
Added
app.fields컬렉션 accessor (Fields) —
v1.0 청사진 Phase 1. 하위 호환: iteration /in/len()은
여전히 필드 이름 (str) 으로 동작. 추가로 dict-style + collection 메소드:app.fields["name"]→Field객체 (값 객체 —.value,.goto(),.remove())app.fields["name"] = "값"→ 자동 생성 + 값 주입app.fields.add(name, memo, direction)app.fields.remove(name)/remove_all()app.fields.find(name)→ Optional[Field]app.fields.rename(old, new)app.fields.update({...})/update(**kw)— 일괄 주입app.fields.to_dict()app.fields.from_brackets(pattern)—{{tag}}→ 필드 변환
app.bookmarks(Bookmarks) —
add(name),remove(name),goto(name),"name" in app.bookmarks.app.hyperlinks(Hyperlinks) —
add(text, url)→Hyperlink값 객체.app.charshape/app.parashapeproperties — read 는 현재 커서의
스냅샷 반환, write 는 전체 교체 (또는 dict 로 partial). 기존
:meth:get_charshape/ :meth:set_charshape는 그대로 유지.- 28개의 신규 단위 테스트 (
tests/test_fields_accessor.py).
Changed
app.fields가 단순 list 가 아닌Fields컬렉션 반환. 단,
for n in app.fields:/"x" in app.fields/len(app.fields)
같은 기존 사용 패턴은 그대로 작동 (deprecation warning 없음).app.field_names— 기존 list 반환 property 의 새 이름. 명시적 list
가 필요한 경우 권장 (app.fields도list(app.fields)로 동일).
Deprecated
app.fields[0](정수 인덱싱) →DeprecationWarning. 대신
list(app.fields)[0]또는app.fields["name"]사용.
[0.0.11] — 2026-04-15 — silenced() context manager · v1.0 청사진
Added
SILENCE_NO_SAVE = 0x00100000— hwp-mcp 호환 alias ("저장 안함" 자동 선택).silenced()의 풍부한 string preset —"ok","save","save_yes",
"save_no","no_save","okcancel_ok","okcancel_no"(단일 카테고리
세밀 제어). 기존"yes"/"no"/"reset"와 공존.docs/V1_CONSISTENCY_PLAN.md— 하위 호환을 포기한 v1.0 일관성
로드맵. 6대 원칙(Pythonic state vs action, domain accessor, Fluent
return, 동사 어휘 통일, context manager 명명, 명시적 에러 정책),
전체 API 청사진, 10주 마이그레이션 일정 포함.
Changed
silenced()docstring 명확화 — context manager 임을 강조. 영구
적용은set_message_box_mode(), scoped 적용은silenced()로 분리.- smoke 테스트 (smoke_scenarios.py / smoke_features.py) — 영구
set_message_box_mode()호출 대신with app.silenced("yes"):context
manager 로 감싸 자동 복원. 백그라운드 dismisser 는 fallback 으로 유지.
[0.0.10] — 2026-04-15 — silenced() 6 dialog categories
Added
silenced()6-카테고리 비트필드 지원 — 0xF/0xF0/0xF00/0xF000/0xF0000/0xF00000
6개 dialog 카테고리 모두 한 번에 자동응답.SILENCE_ALL_YES = 0x111111,
SILENCE_ALL_NO = 0x222222,SILENCE_RESET = 0등 상수 추가.suppress_errors()context manager — 에러 dialog 자동 ABORT + Python
예외 swallowing. 대량 자동화에서 일부 실패에도 루프 계속 진행.register_security_module()— 보안 dialog 차단을 위한 외부 모듈 등록.
[0.0.9] — 2026-04-15 — Styles parser · MoveAccessor sub-groups
Added
- MoveAccessor sub-grouping — 38개의 flat 메소드를 의미 단위로 묶은
sub-accessor 도입 (기존 flat API 는 호환 유지):app.move.doc.top() / bottom()app.move.line.start() / end() / next() / prev()app.move.word.start() / end() / next() / prev()app.move.para.start() / end() / next() / prev()app.move.char.next() / prev()app.move.page.top() / bottom() / next() / prev()app.move.cell.left() / right() / up() / down() / start() / end() / top() / bottom()
Fixed
app.stylesparser 완전 작동 — pyhwpx 의FileSaveBlock_S+
HFileOpenSavepset 패턴을 채용해 HWPML2X export 후<STYLE Name>
태그 파싱. 22개 기본 스타일 (바탕글, 본문, 개요 1~8 등) 정확히 인식.- SaveBlockAs/SaveBlockAction 존재 가정 제거 (HWP COM 에 없음).
- SelectionMode 검증 추가 — 선택 없이 호출해도 안전하게 실패.
[0.0.8] — 2026-04-15 — Phase D · E
Added
app.styles(StylesAccessor) — 문단
스타일 조회/적용/삭제/import/export.app.controls(ControlsAccessor) —
문서 내 컨트롤 (표·그림·구역·하이퍼링크 등) linked-list 순회·검색.Control,Style값 객체 —ctrl.select(),style.apply()등.
[0.0.7] — 2026-04-15 — 내부 중복 감사
Deprecated
App.charshape()legacy 빌더 —DeprecationWarning추가. v0.1.0 에서 제거 예정.
Changed
- 6개 public member 의 docstring cross-reference 추가 (selection / visible /
new_document / rgb_color / set_visible / 단위 변환).
[0.0.6] — 2026-04-15 — Phase C
Added
app.goto_page(n),app.highlight(color),
app.save_page_image(n, path),app.save_all_page_images(dir)app.mm_to_hwpunit,point_to_hwpunit,hwpunit_to_mm,
hwpunit_to_point,rgb_colorapp.statusproperty,Color.from_rgb,Color.from_hex
Fixed
app.current_page가 section 번호를 반환하던 버그 (KeyIndicator[5] 로 수정)
[0.0.5] — 2026-04-15 — Phase A · B
Added
- Field API (Mail Merge) —
create_field,set_field,get_field,
fields,fields_dict,field_exists,move_to_field,
delete_field,delete_all_fields,rename_field,
replace_brackets_with_fields - pandas 연동 —
insert_table(data=df),read_table(to=...) app.silenced()context manager — 대화상자 자동 응답- Mail Merge 튜토리얼 추가
[0.0.4] — 2026-04-15 — Phase 1 refactor (_Action + Color/UNSET)
Added
hwpapi/core/document.py— Document/Documents 클래스를 별도 모듈로 분리
(app.py 2,322줄 → 1,930줄)Color클래스 +UNSET센티넬 —hwpapi.parametersets에서 import- 21개 새 단위 테스트 (
tests/test_color_semantics.py) CHANGELOG.md도입docs/REFACTORING_PLAN.md— 전체 리팩토링 로드맵 (524줄)
Changed
- P0-1 버그 수정:
_Action이 문서별 lazy-cache 로 동작
(@property act,@property pset로 재설계). 이제
app.actions.X.run()이 여러 문서에서 올바르게 각 문서에 적용됩니다. - P0-2: 28개 Color 관련 PropertyDescriptor 를
ColorProperty로 승격.
TextColor / ShadeColor / UnderlineColor / ShadowColor / DiagonalColor /
Border*Color 등. ColorProperty쓰기 의미론 명시화:prop = UNSET→ 변경 없음 (no-op)prop = None→ 필드 제거prop = "#FF0000" / Color / int→ 정규화 후 저장
ColorProperty읽기는 이제 항상Color인스턴스 반환
(__str__,__eq__로 기존 문자열 비교 호환)App.insert_text→_Action수정 후 캐시된 action 경로로 복귀
Removed
hwpapi/core/app.py내 Document/Documents 정의 (document.py 로 이동)
0.0.3 — 2026-04-15
Added — 다중 문서 관리 API
Document클래스 (IXHwpDocument 래퍼)Documents컬렉션 (app.documents)app.use_document(...)context manager- xlwings-style Document proxy —
Document.__getattr__로 App 의
모든 메소드/속성을 자동 프록시 (활성화 → 호출 → 복원)
Added — 서식 자동 리셋 헬퍼
app.styled_text(text, **fmt)— 단일 구 스타일app.charshape_scope(**fmt)— CharShape 블록app.parashape_scope(**fmt)— ParaShape 블록- 모두 snapshot + restore 패턴 — shade_color 같은 까다로운 속성도 정확히 복원
Added — 표준 word-processor 메소드
- Properties:
text(get/set),visible,version,page_count,
current_page,selection,saved,name - Clipboard:
select_all,clear,undo,redo,copy,paste,cut,delete - Breaks:
insert_page_break,insert_line_break,
insert_paragraph_break,insert_tab - High-level:
insert_heading,insert_table,insert_hyperlink,
insert_bookmark,new_document
Added — 문서 웹사이트
- Quarto 기반 완전 재설계 (
https://jundamin.github.io/hwpapi) - 8개 튜토리얼 (기초 4 + 사용사례 4)
- 전체 API 레퍼런스 (6,676줄 자동생성)
Added — CI/CD
- PyPI Trusted Publisher — GitHub Release 발행 시 자동 배포
- Modern GitHub Pages deploy (Node 24 호환, 기존 fastai 워크플로우 실패 해결)
Added — E2E 테스트 (31개 시나리오)
tests/smoke_scenarios.py(13개)tests/smoke_features.py(18개)- 모두 read-back assertion 으로 실제 결과 검증
Changed
parametersets.py(4,198줄) 를 15파일 패키지로 분할core.py→core/engine.py+core/app.pyclasses.py→classes/accessors.py+classes/shapes.py- 기본 로그 레벨
INFO→WARNING(production 친화적)
Fixed
- HTML 튜토리얼 preview 를 실제 HWP → PDF → PNG 렌더링으로 교체
app.get_text()기본 범위가 현재 줄뿐 → scan 매개변수로 전체 문서 가능
[0.0.2.5] 및 이전
초기 nbdev-based 구조에서 출발한 버전. 상세 기록은
REFACTORING_SUMMARY.md 및 PSET_MIGRATION_SUMMARY.md 참고.
버전 관리 정책
- v0.0.x — 초기 베타, 구조 정립 단계
- v0.1.x — Phase 2 구조 재편 (app.py 분할, CharShape 중복 제거,
accessor 재그룹) - v1.0 — 호환성 깨는 API 표준화 (Fluent 반환, deprecated 제거).
Migration guide 제공.
마이그레이션 전략은 docs/REFACTORING_PLAN.md
참고.