25 KiB
HWP/HWPX ↔ HTML/CSS 도메인 가이드
목적: HWPX에서 문서 유형·스타일·템플릿을 추출하거나, HTML → HWPX → HWP 변환 시
하드코딩 없이 이 가이드를 참조하여 정확한 매핑을 수행한다.
출처: 한글과컴퓨터 공식 "글 문서 파일 구조 5.0" (revision 1.3, 2018-11-08)
범위: HWP 5.0 바이너리 스펙의 개념 체계 + HWPX XML 태그 + HTML/CSS 매핑
0. 문서 형식 관계
HWP (바이너리) HWPX (XML) HTML/CSS
───────────────── ───────────────────── ─────────────────
Compound File ZIP Archive 단일 HTML 파일
├─ FileHeader ├─ META-INF/ ├─ <head>
├─ DocInfo │ └─ manifest.xml │ ├─ <meta>
│ (글꼴, 스타일, ├─ Contents/ │ └─ <style>
│ 테두리/배경, │ ├─ header.xml └─ <body>
│ 글자모양 등) │ │ (DocInfo 대응) ├─ 헤더 영역
├─ BodyText/ │ ├─ section0.xml │ ├─ 본문
│ └─ Section0 │ │ (본문 대응) │ └─ 푸터 영역
├─ BinData/ │ └─ section1.xml └─ @page CSS
│ └─ 이미지 등 ├─ BinData/
└─ PrvImage │ └─ 이미지 파일
└─ version.xml
핵심: HWP 바이너리의 레코드 구조와 HWPX XML의 엘리먼트는 1:1 대응한다.
이 가이드는 두 형식의 공통 개념 체계를 기준으로, CSS 변환까지 연결한다.
1. 단위 체계
1.1 HWPUNIT (글 내부 단위)
HWP는 1/7200 인치를 기본 단위로 사용한다.
| 변환 대상 | 공식 | 예시 |
|---|---|---|
| HWPUNIT → mm | hwpunit / 7200 * 25.4 |
7200 → 25.4mm (= 1인치) |
| HWPUNIT → pt | hwpunit / 7200 * 72 |
7200 → 72pt |
| HWPUNIT → px (96dpi) | hwpunit / 7200 * 96 |
7200 → 96px |
| mm → HWPUNIT | mm / 25.4 * 7200 |
25.4mm → 7200 |
| pt → HWPUNIT | pt / 72 * 7200 |
10pt → 1000 |
def hwpunit_to_mm(hwpunit): return hwpunit / 7200 * 25.4
def hwpunit_to_pt(hwpunit): return hwpunit / 7200 * 72
def hwpunit_to_px(hwpunit): return hwpunit / 7200 * 96
def mm_to_hwpunit(mm): return mm / 25.4 * 7200
1.2 글자 크기 (CharShape)
HWP의 글자 크기는 HWPUNIT 단위이지만 100배 스케일이 적용되어 있다.
| HWP 값 | 실제 크기 | CSS |
|---|---|---|
| 1000 | 10pt | font-size: 10pt |
| 1200 | 12pt | font-size: 12pt |
| 2400 | 24pt | font-size: 24pt |
def charsize_to_pt(hwp_size): return hwp_size / 100 # 1000 → 10pt
1.3 COLORREF (색상)
HWP는 0x00BBGGRR 형식(리틀 엔디안 BGR). CSS는 #RRGGBB.
| HWP COLORREF | 분해 | CSS |
|---|---|---|
| 0x00000000 | R=0, G=0, B=0 | #000000 (검정) |
| 0x00FF0000 | R=0, G=0, B=255 | #0000ff (파랑) |
| 0x0000FF00 | R=0, G=255, B=0 | #00ff00 (초록) |
| 0x000000FF | R=255, G=0, B=0 | #ff0000 (빨강) |
| 0x00FFFFFF | R=255, G=255, B=255 | #ffffff (흰색) |
def colorref_to_css(colorref):
r = colorref & 0xFF
g = (colorref >> 8) & 0xFF
b = (colorref >> 16) & 0xFF
return f'#{r:02x}{g:02x}{b:02x}'
HWPX XML에서의 색상: #RRGGBB 형식으로 직접 기록됨 (변환 불필요).
2. 테두리/배경 (BorderFill)
HWP:
HWPTAG_BORDER_FILL(DocInfo 레코드)
HWPX:<hh:borderFill>(header.xml 내)
용도: 표 셀, 문단, 쪽 테두리/배경에 공통 적용
2.1 테두리선 종류
| HWP 값 | 이름 | HWPX type 속성 | CSS border-style |
|---|---|---|---|
| 0 | 실선 | SOLID |
solid |
| 1 | 긴 점선 | DASH |
dashed |
| 2 | 점선 | DOT |
dotted |
| 3 | -.-.-. | DASH_DOT |
dashed (근사) |
| 4 | -..-.. | DASH_DOT_DOT |
dashed (근사) |
| 5 | 긴 Dash | LONG_DASH |
dashed |
| 6 | 큰 동그라미 | CIRCLE |
dotted (근사) |
| 7 | 2중선 | DOUBLE |
double |
| 8 | 가는선+굵은선 | THIN_THICK |
double (근사) |
| 9 | 굵은선+가는선 | THICK_THIN |
double (근사) |
| 10 | 가는+굵은+가는 | THIN_THICK_THIN |
double (근사) |
| 11 | 물결 | WAVE |
solid (근사) |
| 12 | 물결 2중선 | DOUBLE_WAVE |
double (근사) |
| 13 | 두꺼운 3D | THICK_3D |
ridge |
| 14 | 두꺼운 3D(역) | THICK_3D_REV |
groove |
| 15 | 3D 단선 | 3D |
outset |
| 16 | 3D 단선(역) | 3D_REV |
inset |
| — | 없음 | NONE |
none |
2.2 테두리선 굵기
| HWP 값 | 실제 굵기 | HWPX width 속성 | CSS border-width |
|---|---|---|---|
| 0 | 0.1 mm | 0.1mm |
0.1mm ≈ 0.4px |
| 1 | 0.12 mm | 0.12mm |
0.12mm ≈ 0.5px |
| 2 | 0.15 mm | 0.15mm |
0.15mm ≈ 0.6px |
| 3 | 0.2 mm | 0.2mm |
0.2mm ≈ 0.8px |
| 4 | 0.25 mm | 0.25mm |
0.25mm ≈ 1px |
| 5 | 0.3 mm | 0.3mm |
0.3mm ≈ 1.1px |
| 6 | 0.4 mm | 0.4mm |
0.4mm ≈ 1.5px |
| 7 | 0.5 mm | 0.5mm |
0.5mm ≈ 1.9px |
| 8 | 0.6 mm | 0.6mm |
0.6mm ≈ 2.3px |
| 9 | 0.7 mm | 0.7mm |
0.7mm ≈ 2.6px |
| 10 | 1.0 mm | 1.0mm |
1mm ≈ 3.8px |
| 11 | 1.5 mm | 1.5mm |
1.5mm ≈ 5.7px |
| 12 | 2.0 mm | 2.0mm |
2mm ≈ 7.6px |
| 13 | 3.0 mm | 3.0mm |
3mm ≈ 11.3px |
| 14 | 4.0 mm | 4.0mm |
4mm ≈ 15.1px |
| 15 | 5.0 mm | 5.0mm |
5mm ≈ 18.9px |
BORDER_WIDTH_MAP = {
0: 0.1, 1: 0.12, 2: 0.15, 3: 0.2, 4: 0.25, 5: 0.3,
6: 0.4, 7: 0.5, 8: 0.6, 9: 0.7, 10: 1.0, 11: 1.5,
12: 2.0, 13: 3.0, 14: 4.0, 15: 5.0
}
def border_width_to_css(hwp_val):
mm = BORDER_WIDTH_MAP.get(hwp_val, 0.12)
return f'{mm}mm' # 또는 mm * 3.7795px
2.3 테두리 4방향 순서
| HWP 배열 인덱스 | HWPX 속성 | CSS 대응 |
|---|---|---|
| [0] | <left> / <hh:left> |
border-left |
| [1] | <right> / <hh:right> |
border-right |
| [2] | <top> / <hh:top> |
border-top |
| [3] | <bottom> / <hh:bottom> |
border-bottom |
2.4 채우기 (Fill) 정보
| 채우기 종류 (type 비트) | HWPX 엘리먼트 | CSS 대응 |
|---|---|---|
| 0x00 — 없음 | (없음) | background: none |
| 0x01 — 단색 | <hh:windowBrush> 또는 <hh:colorFill> |
background-color: #... |
| 0x02 — 이미지 | <hh:imgBrush> |
background-image: url(...) |
| 0x04 — 그러데이션 | <hh:gradation> |
background: linear-gradient(...) |
단색 채우기 구조 (가장 빈번):
<!-- HWPX header.xml -->
<hh:borderFill id="4">
<hh:slash .../>
<hh:backSlash .../>
<hh:left type="SOLID" width="0.12mm" color="#000000"/>
<hh:right type="SOLID" width="0.12mm" color="#000000"/>
<hh:top type="SOLID" width="0.12mm" color="#000000"/>
<hh:bottom type="SOLID" width="0.12mm" color="#000000"/>
<hh:diagonal .../>
<hh:fillBrush>
<hh:windowBrush faceColor="#E8F5E9" hatchColor="none" .../>
</hh:fillBrush>
</hh:borderFill>
/* CSS 대응 */
.cell-bf4 {
border-left: 0.12mm solid #000000;
border-right: 0.12mm solid #000000;
border-top: 0.12mm solid #000000;
border-bottom: 0.12mm solid #000000;
background-color: #E8F5E9;
}
2.5 HWPX borderFill → CSS 변환 함수 (의사 코드)
def borderfill_to_css(bf_element):
"""HWPX <hh:borderFill> 엘리먼트 → CSS 딕셔너리"""
css = {}
for side in ['left', 'right', 'top', 'bottom']:
el = bf_element.find(f'hh:{side}')
if el is None:
css[f'border-{side}'] = 'none'
continue
btype = el.get('type', 'NONE')
width = el.get('width', '0.12mm')
color = el.get('color', '#000000')
if btype == 'NONE':
css[f'border-{side}'] = 'none'
else:
css_style = BORDER_TYPE_MAP.get(btype, 'solid')
css[f'border-{side}'] = f'{width} {css_style} {color}'
# 배경
fill = bf_element.find('.//hh:windowBrush')
if fill is not None:
face = fill.get('faceColor', 'none')
if face and face != 'none':
css['background-color'] = face
return css
3. 글꼴 (FaceName)
HWP:
HWPTAG_FACE_NAME(DocInfo)
HWPX:<hh:fontface>→<hh:font>(header.xml)
CSS:font-family
3.1 언어별 글꼴 시스템
HWP는 한글·영문·한자·일어·기타·기호·사용자 총 7개 언어 슬롯에 각각 다른 글꼴을 지정한다.
| 언어 인덱스 | HWPX lang 속성 | 주요 글꼴 예시 |
|---|---|---|
| 0 | HANGUL |
맑은 고딕, 나눔고딕 |
| 1 | LATIN |
Arial, Times New Roman |
| 2 | HANJA |
(한글 글꼴 공유) |
| 3 | JAPANESE |
MS Mincho |
| 4 | OTHER |
— |
| 5 | SYMBOL |
Symbol, Wingdings |
| 6 | USER |
— |
CSS 매핑: 일반적으로 한글(0)과 영문(1) 글꼴을 font-family 스택으로 결합.
/* HWPX: hangul="맑은 고딕" latin="Arial" */
font-family: "맑은 고딕", Arial, sans-serif;
3.2 글꼴 관련 HWPX 구조
<!-- header.xml -->
<hh:fontfaces>
<hh:fontface lang="HANGUL">
<hh:font face="맑은 고딕" type="TTF" id="0"/>
</hh:fontface>
<hh:fontface lang="LATIN">
<hh:font face="Arial" type="TTF" id="0"/>
</hh:fontface>
...
</hh:fontfaces>
4. 글자 모양 (CharShape)
HWP:
HWPTAG_CHAR_SHAPE(DocInfo, 72바이트)
HWPX:<hh:charPr>(header.xml charProperties 내)
CSS: font-*, color, text-decoration 등
4.1 주요 속성 매핑
| HWP 필드 | HWPX 속성 | CSS 속성 | 비고 |
|---|---|---|---|
| 글꼴 ID [7] | fontRef |
font-family |
언어별 참조 |
| 장평 [7] | ratio |
font-stretch |
50%~200% |
| 자간 [7] | spacing |
letter-spacing |
-50%~50%, pt 변환 필요 |
| 기준 크기 | height |
font-size |
값/100 = pt |
| 글자 색 | color 속성 |
color |
COLORREF → #RRGGBB |
| 밑줄 색 | underline color |
text-decoration-color |
|
| 진하게(bit 1) | bold="true" |
font-weight: bold |
|
| 기울임(bit 0) | italic="true" |
font-style: italic |
|
| 밑줄(bit 2-3) | underline type |
text-decoration: underline |
|
| 취소선(bit 18-20) | strikeout type |
text-decoration: line-through |
|
| 위첨자(bit 15) | supscript |
vertical-align: super; font-size: 70% |
|
| 아래첨자(bit 16) | subscript |
vertical-align: sub; font-size: 70% |
4.2 HWPX charPr 구조 예시
<hh:charPr id="1" height="1000" bold="false" italic="false"
underline="NONE" strikeout="NONE" color="#000000">
<hh:fontRef hangul="0" latin="0" hanja="0" japanese="0"
other="0" symbol="0" user="0"/>
<hh:ratio hangul="100" latin="100" .../>
<hh:spacing hangul="0" latin="0" .../>
<hh:relSz hangul="100" latin="100" .../>
<hh:offset hangul="0" latin="0" .../>
</hh:charPr>
5. 문단 모양 (ParaShape)
HWP:
HWPTAG_PARA_SHAPE(DocInfo, 54바이트)
HWPX:<hh:paraPr>(header.xml paraProperties 내)
CSS: text-align, margin, line-height, text-indent 등
5.1 정렬 방식
| HWP 값 (bit 2-4) | HWPX 속성값 | CSS text-align |
|---|---|---|
| 0 | JUSTIFY |
justify |
| 1 | LEFT |
left |
| 2 | RIGHT |
right |
| 3 | CENTER |
center |
| 4 | DISTRIBUTE |
justify (근사) |
| 5 | DISTRIBUTE_SPACE |
justify (근사) |
5.2 줄 간격 종류
| HWP 값 | HWPX 속성값 | CSS line-height | 비고 |
|---|---|---|---|
| 0 | PERCENT |
160% (예) |
글자 크기 기준 % |
| 1 | FIXED |
24pt (예) |
고정 pt |
| 2 | BETWEEN_LINES |
— | 여백만 지정 |
| 3 | AT_LEAST |
— | 최소값 |
5.3 주요 속성 매핑
| HWP 필드 | HWPX 속성 | CSS 속성 | 단위 |
|---|---|---|---|
| 왼쪽 여백 | margin left |
margin-left / padding-left |
HWPUNIT → mm |
| 오른쪽 여백 | margin right |
margin-right / padding-right |
HWPUNIT → mm |
| 들여쓰기 | indent |
text-indent |
HWPUNIT → mm |
| 문단 간격 위 | spacing before |
margin-top |
HWPUNIT → mm |
| 문단 간격 아래 | spacing after |
margin-bottom |
HWPUNIT → mm |
| 줄 간격 | lineSpacing |
line-height |
종류에 따라 다름 |
| BorderFill ID | borderFillIDRef |
border + background | ID로 참조 |
5.4 HWPX paraPr 구조 예시
<hh:paraPr id="0" align="JUSTIFY">
<hh:margin left="0" right="0" indent="0"/>
<hh:spacing before="0" after="0"
lineSpacingType="PERCENT" lineSpacing="160"/>
<hh:border borderFillIDRef="1"
left="0" right="0" top="0" bottom="0"/>
<hh:autoSpacing eAsianEng="false" eAsianNum="false"/>
</hh:paraPr>
6. 표 (Table) 구조
HWP:
HWPTAG_TABLE(본문 레코드)
HWPX:<hp:tbl>(section*.xml 내)
HTML:<table>,<tr>,<td>/<th>
6.1 표 속성 매핑
| HWP 필드 | HWPX 속성 | HTML/CSS 대응 | 비고 |
|---|---|---|---|
| RowCount | rowCnt |
(행 수) | |
| nCols | colCnt |
(열 수) | <colgroup> 참조 |
| CellSpacing | cellSpacing |
border-spacing |
HWPUNIT16 |
| 안쪽 여백 | cellMargin left/right/top/bottom |
padding |
|
| BorderFill ID | borderFillIDRef |
표 전체 테두리 | |
| 쪽나눔(bit 0-1) | pageBreak |
page-break-inside |
0=avoid, 1=auto |
| 제목줄 반복(bit 2) | repeatHeader |
<thead> 출력 |
6.2 열 너비
<!-- HWPX -->
<hp:tbl colCnt="3" rowCnt="5" ...>
<hp:colSz>
<hp:widthList>8504 8504 8504</hp:widthList> <!-- HWPUNIT -->
</hp:colSz>
...
</hp:tbl>
<!-- HTML 변환 -->
<colgroup>
<col style="width: 33.33%"> <!-- 8504 / 총합 * 100 -->
<col style="width: 33.33%">
<col style="width: 33.33%">
</colgroup>
6.3 셀 (Cell) 속성
| HWP 필드 | HWPX 속성 | HTML 속성 | 비고 |
|---|---|---|---|
| Column 주소 | colAddr |
— | 0부터 시작 |
| Row 주소 | rowAddr |
— | 0부터 시작 |
| 열 병합 개수 | colSpan |
colspan |
1 = 병합 없음 |
| 행 병합 개수 | rowSpan |
rowspan |
1 = 병합 없음 |
| 셀 폭 | width |
width |
HWPUNIT |
| 셀 높이 | height |
height |
HWPUNIT |
| 셀 여백 [4] | cellMargin |
padding |
HWPUNIT16 → mm |
| BorderFill ID | borderFillIDRef |
border + background |
셀별 스타일 |
6.4 HWPX 셀 구조 예시
<hp:tc colAddr="0" rowAddr="0" colSpan="2" rowSpan="1"
width="17008" height="2400" borderFillIDRef="4">
<hp:cellMargin left="510" right="510" top="142" bottom="142"/>
<hp:cellAddr colAddr="0" rowAddr="0"/>
<hp:subList ...>
<hp:p ...>
<!-- 셀 내용 -->
</hp:p>
</hp:subList>
</hp:tc>
<!-- HTML 변환 -->
<td colspan="2" style="
width: 60mm;
height: 8.5mm;
padding: 0.5mm 1.8mm;
border: 0.12mm solid #000;
background-color: #E8F5E9;
">셀 내용</td>
6.5 병합 셀 처리 규칙
HWP/HWPX에서 병합된 셀은 왼쪽 위 셀만 존재하고, 병합에 포함된 다른 셀은 아예 없다.
HTML에서는 colspan/rowspan으로 표현하고, 병합된 위치의 <td>를 생략한다.
HWPX: colSpan="2", rowSpan="3" at (col=0, row=0)
→ 이 셀이 col 0~1, row 0~2를 차지
→ col=1/row=0, col=0/row=1, col=1/row=1, col=0/row=2, col=1/row=2 셀은 없음
HTML: <td colspan="2" rowspan="3">...</td>
→ 해당 행/열 위치에서 <td> 생략
7. 용지 설정 (PageDef / SecPr)
HWP:
HWPTAG_PAGE_DEF(구역 정의 하위)
HWPX:<hp:secPr>→<hp:pageDef>(section*.xml 내)
CSS:@page,@media print
7.1 용지 크기 사전 정의
| 용지 이름 | 가로 (mm) | 세로 (mm) | HWPUNIT (가로×세로) |
|---|---|---|---|
| A4 | 210 | 297 | 59528 × 84188 |
| A3 | 297 | 420 | 84188 × 119055 |
| B5 | 176 | 250 | 49896 × 70866 |
| Letter | 215.9 | 279.4 | 61200 × 79200 |
| Legal | 215.9 | 355.6 | 61200 × 100800 |
7.2 여백 매핑
<!-- HWPX section0.xml -->
<hp:secPr>
<hp:pageDef width="59528" height="84188"
landscape="NARROWLY"> <!-- 좁게 = 세로 -->
<hp:margin left="8504" right="8504"
top="5668" bottom="4252"
header="4252" footer="4252"
gutter="0"/>
</hp:pageDef>
</hp:secPr>
/* CSS 변환 */
@page {
size: A4 portrait; /* 210mm × 297mm */
margin-top: 20mm; /* 5668 / 7200 * 25.4 ≈ 20mm */
margin-bottom: 15mm; /* 4252 → 15mm */
margin-left: 30mm; /* 8504 → 30mm */
margin-right: 30mm; /* 8504 → 30mm */
}
/* 머리말/꼬리말 여백은 CSS에서 body padding으로 근사 */
7.3 용지 방향
| HWP 값 (bit 0) | HWPX 속성값 | CSS |
|---|---|---|
| 0 | NARROWLY (좁게) |
portrait |
| 1 | WIDELY (넓게) |
landscape |
8. 머리말/꼬리말 (Header/Footer)
HWP:
HWPTAG_CTRL_HEADER→ 컨트롤 IDhead/foot
HWPX:<hp:headerFooter>(section*.xml 내, 또는 별도 header/footer 영역)
HTML: 페이지 상단/하단 고정 영역
8.1 머리말/꼬리말 적용 범위
| HWP/HWPX 설정 | 의미 |
|---|---|
| 양쪽 | 모든 쪽에 동일 |
| 짝수쪽만 | 짝수 페이지 |
| 홀수쪽만 | 홀수 페이지 |
8.2 HTML 근사 표현
<!-- 머리말 -->
<div class="page-header" style="
position: absolute; top: 0; left: 0; right: 0;
height: 15mm; /* header margin 값 */
padding: 0 30mm; /* 좌우 본문 여백 */
">
<table class="header-table">...</table>
</div>
<!-- 꼬리말 -->
<div class="page-footer" style="
position: absolute; bottom: 0; left: 0; right: 0;
height: 15mm; /* footer margin 값 */
padding: 0 30mm;
">
<span class="footer-text">페이지 번호</span>
</div>
9. 구역 정의 (Section)
HWP: 구역 정의 컨트롤 (
secd)
HWPX:<hp:secPr>(section*.xml 최상위)
9.1 구역 속성
| 속성 | HWPX | CSS/HTML 대응 | 비고 |
|---|---|---|---|
| 머리말 감춤 | hideHeader |
header 영역 display:none | |
| 꼬리말 감춤 | hideFooter |
footer 영역 display:none | |
| 텍스트 방향 | textDirection |
writing-mode |
0=가로, 1=세로 |
| 단 정의 | <hp:colDef> |
CSS columns / column-count |
|
| 쪽 번호 | pageStartNo |
쪽 번호 출력 값 | 0=이어서 |
10. HTML → HWPX → HWP 변환 파이프라인
10.1 전체 흐름
[HTML (우리 출력)]
↓ (1) HTML 파싱 → CSS 속성 추출
[중간 표현 (JSON)]
↓ (2) 이 가이드의 역방향 매핑
[HWPX (XML ZIP)]
↓ (3) 한컴오피스 변환 도구
[HWP (바이너리)]
10.2 단계별 매핑 방향
| 단계 | 입력 | 출력 | 참조할 가이드 섹션 |
|---|---|---|---|
| HTML → HWPX | CSS border | <hh:borderFill> 생성 |
§2 역방향 |
| HTML → HWPX | CSS font | <hh:charPr> + <hh:fontface> |
§3, §4 역방향 |
| HTML → HWPX | CSS text-align 등 | <hh:paraPr> |
§5 역방향 |
| HTML → HWPX | <table> |
<hp:tbl> + <hp:tc> |
§6 역방향 |
| HTML → HWPX | @page CSS | <hp:pageDef> |
§7 역방향 |
| HTML → HWPX | header/footer div | <hp:headerFooter> |
§8 역방향 |
10.3 CSS → HWPX 역변환 예시
def css_border_to_hwpx(css_border):
"""'0.12mm solid #000000' → HWPX 속성"""
parts = css_border.split()
width = parts[0] # '0.12mm'
style = parts[1] # 'solid'
color = parts[2] # '#000000'
hwpx_type = CSS_TO_BORDER_TYPE.get(style, 'SOLID')
return {
'type': hwpx_type,
'width': width,
'color': color
}
CSS_TO_BORDER_TYPE = {
'solid': 'SOLID', 'dashed': 'DASH', 'dotted': 'DOT',
'double': 'DOUBLE', 'ridge': 'THICK_3D', 'groove': 'THICK_3D_REV',
'outset': '3D', 'inset': '3D_REV', 'none': 'NONE'
}
10.4 HWPX ZIP 구조 생성
output.hwpx (ZIP)
├── META-INF/
│ └── manifest.xml ← 파일 목록
├── Contents/
│ ├── header.xml ← DocInfo (글꼴, 스타일, borderFill)
│ ├── section0.xml ← 본문 (문단, 표, 머리말/꼬리말)
│ └── content.hpf ← 콘텐츠 메타
├── BinData/ ← 이미지 등
├── Preview/
│ └── PrvImage.png ← 미리보기
└── version.xml ← 버전 정보
header.xml 필수 구조:
<?xml version="1.0" encoding="UTF-8"?>
<hh:head xmlns:hh="...">
<hh:beginNum .../>
<hh:refList>
<hh:fontfaces>...</hh:fontfaces> <!-- §3 -->
<hh:borderFills>...</hh:borderFills> <!-- §2 -->
<hh:charProperties>...</hh:charProperties> <!-- §4 -->
<hh:tabProperties>...</hh:tabProperties>
<hh:numberingProperties>...</hh:numberingProperties>
<hh:bulletProperties>...</hh:bulletProperties>
<hh:paraProperties>...</hh:paraProperties> <!-- §5 -->
<hh:styles>...</hh:styles>
</hh:refList>
</hh:head>
section0.xml 필수 구조:
<?xml version="1.0" encoding="UTF-8"?>
<hp:sec xmlns:hp="...">
<hp:secPr>
<hp:pageDef .../> <!-- §7 -->
<hp:headerFooter .../> <!-- §8 -->
</hp:secPr>
<hp:p paraPrIDRef="0" styleIDRef="0"> <!-- 문단 -->
<hp:run charPrIDRef="0">
<hp:t>텍스트</hp:t>
</hp:run>
</hp:p>
<hp:p ...>
<hp:ctrl>
<hp:tbl ...>...</hp:tbl> <!-- §6 -->
</hp:ctrl>
</hp:p>
</hp:sec>
11. 시스템 적용 가이드
11.1 적용 대상 모듈
| 모듈 | 파일 | 이 가이드 활용 방식 |
|---|---|---|
| doc_template_analyzer.py | HWPX → HTML 템플릿 추출 | §2,6,7,8 정방향 (HWPX→CSS) |
| template_manager.py | 추출된 스타일 저장/로드 | §2 borderFill ID 매핑 |
| custom_doc_type.py | HTML 문서 생성 | §2,4,5 CSS 값 참조 |
| hwpx_converter.py (예정) | HTML → HWPX 변환 | §2~8 역방향 (CSS→HWPX) |
| hwp_converter.py (예정) | HWPX → HWP 변환 | §1 단위 변환 |
11.2 하드코딩 제거 전략
현재 문제 (AS-IS):
# doc_template_analyzer.py에 하드코딩됨
border_css = "2px solid var(--primary)"
header_bg = "#E8F5E9"
해결 방향 (TO-BE):
# style.json에서 추출된 borderFill 참조
bf = style['border_fills']['3'] # id=3
border_css = f"{bf['top']['width']} {bf['top']['css_style']} {bf['top']['color']}"
# → "0.12mm solid #000000"
header_bf = style['border_fills']['4'] # id=4 (헤더 배경 포함)
header_bg = header_bf.get('background', 'none')
# → "#E8F5E9"
11.3 이 가이드를 코드에서 참조하는 방식
이 문서(hwpx_domain_guide.md)는 다음과 같이 활용한다:
-
변환 테이블을 JSON으로 추출 →
hwpx_mappings.json- 테두리선 종류, 굵기, 색상 변환 등의 룩업 테이블
-
변환 함수 라이브러리 →
hwpx_utils.pyhwpunit_to_mm(),borderfill_to_css(),css_border_to_hwpx()등
-
AI 프롬프트 컨텍스트 → 문서 유형/구조 분석 시 참조
- "이 HWPX의 borderFill id=3은 실선 0.12mm 검정이므로 표 일반 셀에 해당"
-
검증 기준 → 변환 결과물 검증 시 정확성 확인
- 추출된 CSS가 원본 HWPX의 스펙과 일치하는지
부록 A. 빠른 참조 — HWPX XML 태그 ↔ HWP 레코드 대응
| HWP 레코드 (Tag ID) | HWPX XML 엘리먼트 | 위치 |
|---|---|---|
| HWPTAG_DOCUMENT_PROPERTIES | <hh:beginNum> 등 |
header.xml |
| HWPTAG_ID_MAPPINGS | (암묵적) | header.xml |
| HWPTAG_FACE_NAME | <hh:font> |
header.xml > fontfaces |
| HWPTAG_BORDER_FILL | <hh:borderFill> |
header.xml > borderFills |
| HWPTAG_CHAR_SHAPE | <hh:charPr> |
header.xml > charProperties |
| HWPTAG_TAB_DEF | <hh:tabPr> |
header.xml > tabProperties |
| HWPTAG_NUMBERING | <hh:numbering> |
header.xml > numberingProperties |
| HWPTAG_BULLET | <hh:bullet> |
header.xml > bulletProperties |
| HWPTAG_PARA_SHAPE | <hh:paraPr> |
header.xml > paraProperties |
| HWPTAG_STYLE | <hh:style> |
header.xml > styles |
| HWPTAG_PARA_HEADER | <hp:p> |
section*.xml |
| HWPTAG_TABLE | <hp:tbl> |
section*.xml > p > ctrl |
| (셀 속성) | <hp:tc> |
section*.xml > tbl > tr > tc |
| HWPTAG_PAGE_DEF | <hp:pageDef> |
section*.xml > secPr |
| (머리말/꼬리말) | <hp:headerFooter> |
section*.xml > secPr |
부록 B. 빠른 참조 — CSS → HWPX 역변환
| CSS 속성 | HWPX 대응 | 변환 공식 |
|---|---|---|
font-family |
<hh:font face="..."> |
첫 번째 값 → hangul, 두 번째 → latin |
font-size: 10pt |
<hh:charPr height="1000"> |
pt × 100 |
font-weight: bold |
bold="true" |
|
font-style: italic |
italic="true" |
|
color: #1a365d |
color="#1a365d" |
동일 |
text-align: center |
align="CENTER" |
대문자 |
margin-left: 30mm |
left="8504" |
mm → HWPUNIT |
line-height: 160% |
lineSpacing="160" + type="PERCENT" |
|
border: 1px solid #000 |
<hh:borderFill> 내 각 방향 |
§2 참조 |
background-color: #E8F5E9 |
<hh:windowBrush faceColor="..."> |
|
padding: 2mm 5mm |
<hp:cellMargin top="567" left="1417"> |
mm → HWPUNIT |
width: 210mm |
width="59528" |
mm → HWPUNIT |
@page { size: A4 } |
<hp:pageDef width="59528" height="84188"> |
이 가이드는 한글과컴퓨터의 "글 문서 파일 구조 5.0 (revision 1.3)"을 참고하여 작성되었습니다.