hwpx
HWPX 문서 생성·편집·분석 스킬
개요
HWPX는 한컴오피스 한글의 개방형 문서 포맷으로, OWPML(Open Word-Processor Markup Language, KS X 6101) 표준을 따른다. 구조적으로 ZIP 아카이브 안에 XML 파일들이 들어있어, docx와 유사한 방식으로 프로그래밍적 조작이 가능하다.
파일 포맷 비교
| 포맷 | 확장자 | 특징 |
|---|---|---|
| HWP (레거시) | .hwp | 바이너리 포맷, 직접 생성 어려움 |
| HWPX (개방형) | .hwpx | ZIP + XML, 프로그래밍 생성 가능 |
이 스킬은 HWPX 포맷을 기본으로 사용한다. 사용자가 .hwp를 요청해도 HWPX로 생성하며, HWPX는 한컴오피스 2018 이상에서 기본 지원한다.
Quick Reference
| 작업 | 방법 |
|---|---|
| 간단한 문서 생성 | hwpx-ts 라이브러리 (npm) |
| 스타일 포함 문서 생성 | OWPML XML 직접 작성 + ZIP 패키징 |
| 기존 HWPX 읽기 | @ssabrojs/hwpxjs 또는 unzip + XML 파싱 |
| 기존 HWPX 편집 | unzip → XML 편집 → repack |
| HWP → HWPX 변환 | hwpxjs convert:hwp 또는 LibreOffice |
설치
# 방법 1: hwpx-ts (생성/읽기)
npm install -g hwpx-ts
# 방법 2: hwpxjs (읽기/변환/간단한 쓰기)
npm install -g @ssabrojs/hwpxjs
두 라이브러리 모두 설치하는 것을 권장한다.
방법 1: hwpx-ts로 간단한 문서 생성
텍스트, 제목, 테이블로 구성된 기본 문서를 빠르게 생성할 때 사용한다. 스타일링(글꼴 크기, 볼드, 색상 등)은 제한적이다.
const { HwpxExporter } = require('hwpx-ts');
const exporter = new HwpxExporter();
exporter.addHeading('문서 제목', 1); // 레벨 1 제목
exporter.addHeading('하위 제목', 2); // 레벨 2 제목
exporter.addParagraph('본문 텍스트입니다.'); // 일반 문단
exporter.addTable([ // 테이블
['열1', '열2', '열3'],
['값1', '값2', '값3'],
]);
await exporter.saveToFile('./output.hwpx');
제한사항: 글꼴 크기/색상/볼드 등 세밀한 스타일 제어 불가. 정형화된 문서가 필요하면 방법 2를 사용한다.
방법 2: OWPML XML 직접 작성 (권장 - 고품질 문서)
연구노트, 보고서 등 스타일이 중요한 문서는 OWPML XML을 직접 작성하고 ZIP으로 패키징한다.
HWPX 파일 구조
document.hwpx (ZIP)
├── mimetype ← "application/hwpx" (비압축)
├── version.xml ← HWPX 버전 정보
├── settings.xml ← 앱 설정
├── META-INF/
│ ├── container.xml ← 루트 파일 참조
│ └── manifest.xml ← 파일 목록
└── Contents/
├── header.xml ← 글꼴, 스타일, 페이지 설정
├── content.hpf ← 패키지 파일 목록
└── section0.xml ← 본문 내용
핵심 XML 파일별 역할
header.xml — 문서의 모든 스타일을 정의한다:
faceNameMap: 글꼴 정의 (HANGUL, LATIN 등 언어별)charPrMap: 글자 속성 (크기, 볼드, 색상 등) →charPr id="N"paraPrMap: 문단 속성 (줄간격, 정렬, 여백 등) →paraPr id="N"secPr: 페이지 크기, 여백
section0.xml — 실제 본문 내용:
<hp:p>: 문단 (paragraph)<hp:run>: 텍스트 런 (charPrIDRef로 스타일 참조)<hp:t>: 실제 텍스트<hp:tbl>: 테이블
단위 체계
OWPML은 HWP 단위(HU) 를 사용한다:
- 1 HU = 1/7200 인치
- A4: width=59528, height=84188
- 1cm = 2835 HU
- 1pt = 100 HU (글자 크기: 10pt = 1000, 12pt = 1200)
charSz에서는 val × 1/100 pt 방식 사용:
- 10pt →
val="2000"(hwpx-ts 방식) 또는val="1000"(일부 구현) - 실제 동작은 구현에 따라 다르므로 테스트 후 조정
스타일 정의 예시 (header.xml)
상세한 header.xml 작성법은 references/owpml-reference.md를 참조한다.
본문 작성 패턴 (section0.xml)
<!-- 기본 문단 -->
<hp:p id="0" paraPrIDRef="0" styleIDRef="0">
<hp:run charPrIDRef="0">
<hp:t>본문 텍스트입니다.</hp:t>
</hp:run>
</hp:p>
<!-- 볼드 제목 (charPr 1번 = Bold 18pt 등으로 정의한 경우) -->
<hp:p id="0" paraPrIDRef="1" styleIDRef="0">
<hp:run charPrIDRef="1">
<hp:t>문서 제목</hp:t>
</hp:run>
</hp:p>
<!-- 한 문단에 여러 스타일 -->
<hp:p id="0" paraPrIDRef="0" styleIDRef="0">
<hp:run charPrIDRef="3"><hp:t>볼드 텍스트</hp:t></hp:run>
<hp:run charPrIDRef="0"><hp:t> 일반 텍스트</hp:t></hp:run>
</hp:p>
<!-- 테이블 -->
<hp:p id="0" paraPrIDRef="0" styleIDRef="0">
<hp:tbl rowCnt="2" colCnt="3">
<hp:tr>
<hp:tc rowSpan="1" colSpan="1">
<hp:p id="0" paraPrIDRef="0" styleIDRef="0">
<hp:run charPrIDRef="3"><hp:t>헤더 셀</hp:t></hp:run>
</hp:p>
</hp:tc>
<!-- 나머지 셀들... -->
</hp:tr>
</hp:tbl>
</hp:p>
ZIP 패키징
mimetype 파일은 반드시 비압축(-0)으로 먼저 넣고, 나머지를 추가한다:
cd /path/to/hwpx_build
zip -0 -X output.hwpx mimetype
zip -r -X output.hwpx . -x mimetype
JavaScript에서:
const { execSync } = require('child_process');
execSync(`cd "${buildDir}" && zip -0 -X "${outputPath}" mimetype && zip -r -X "${outputPath}" . -x mimetype`);
HWPX 읽기
// 방법 1: hwpx-ts
const { readHwpxFile } = require('hwpx-ts');
const reader = await readHwpxFile('./document.hwpx');
console.log(reader.getText());
console.log(reader.getInfo());
// 방법 2: hwpxjs
const HwpxReader = require('@ssabrojs/hwpxjs').default;
const reader = new HwpxReader();
await reader.loadFromFile('./document.hwpx');
const text = await reader.extractText();
const html = await reader.extractHtml();
HWPX 편집
기존 HWPX 파일을 수정할 때는 unpack → edit → repack 패턴을 따른다.
Step 1: Unpack
mkdir unpacked && cd unpacked && unzip ../document.hwpx
Step 2: Edit XML
Contents/section0.xml을 직접 편집- 중요:
linesegarray요소가 있으면 제거해야 한다 (레이아웃 캐시로, 내용 변경 시 꼬임)
# linesegarray 제거 예시
sed -i '/<hp:linesegarray>/,/<\/hp:linesegarray>/d' Contents/section0.xml
Step 3: Repack
cd unpacked
rm -f ../edited.hwpx
zip -0 -X ../edited.hwpx mimetype
zip -r -X ../edited.hwpx . -x mimetype
HWP ↔ HWPX 변환
# HWP → HWPX (hwpxjs, 순수 TypeScript)
npx hwpxjs convert:hwp document.hwp output.hwpx
# HWPX → HWP (LibreOffice 필요)
python scripts/office/soffice.py --headless --convert-to hwp document.hwpx
# HWPX → PDF (LibreOffice)
python scripts/office/soffice.py --headless --convert-to pdf document.hwpx
다른 스킬과의 연동
k-research-note 스킬과 연동
연구노트 스킬이 HWPX 출력을 요청받으면:
- 연구노트 스킬의 데이터 구조 및 작성 원칙을 따름
- 이 스킬의 OWPML XML 방식으로 문서를 생성함
- 연구노트 스킬의 문서 구조(기본정보 → 목적 → 방법 → 결과 → 고찰 → 서명)를 HWPX section0.xml로 변환
연동 패턴:
[사용자 요청: "연구노트를 한글 파일로 만들어줘"]
→ k-research-note 스킬 트리거 (내용/구조 결정)
→ hwpx 스킬 참조 (HWPX 파일 생성)
→ .hwpx 파일 출력
일반 문서 스킬과의 관계
- docx 스킬: MS Word 문서 생성 → 해외/국제 표준
- hwpx 스킬: 한컴 한글 문서 생성 → 한국 정부/공공기관 표준
- 사용자가 "한글로", "hwp로", "한컴으로" 등 명시하면 hwpx 스킬 사용
- 별도 지정 없으면 docx가 기본값 (호환성 우선)
주의사항
- HWPX는 한컴오피스 2018+ 에서 기본 지원. 이전 버전 사용자에게는 호환성 안내 필요
mimetype파일은 반드시 ZIP 내 첫 번째이며 비압축이어야 한다- OWPML 네임스페이스를 정확히 지켜야 한다 (section:
hs:, paragraph:hp:, core:hc:, head:hh:) - 편집 시
linesegarray제거 필수 - A4 용지: width=59528, height=84188 (HU 단위)
- 글자 크기 val은 테스트 후 확인 (구현마다 단위 해석이 다를 수 있음)