Skip to main content

가볍게 살펴보는 새로운 한/글 파일 포맷 HWPX

About 6 minHTMLCSSHWPArticle(s)blogmeetup.nhncloud.comhwphwpxbashblog

가볍게 살펴보는 새로운 한/글 파일 포맷 HWPX 관련

CSS > Article(s)

Article(s)

가볍게 살펴보는 새로운 한/글 파일 포맷 HWPX | NHN Cloud Meetup
가볍게 살펴보는 새로운 한/글 파일 포맷 HWPX

👀 이 글은 이런 분들이 가벼운 마음❤으로 살펴보세요.

  • 한/글 파일로부터 텍스트나, 이미지 등을 추출하는 업무를 맡아, 대략적인 개념 파악이 필요한 분
  • .HTML 이나, 자체적으로 관리하고 있는 DB상의 정보를 한/글 파일로 가공해야 하는 업무를 맡아, 대략적 인 개념 파악이 필요한 분
  • 마지막으로, 현재 이런 형태의 업무를 하고 있거나 하지 않지만 가볍게 알아는 두고 싶으신 분

프롤로그

저는 NHN에듀에서 서비스하는 NSAT(엔셋) 서비스를 개발하고 있는데요. NSAT은 응시자가 평가 문제를 풀고 제출한 답안을 바탕으로, 채점과 더불어 입체적인 통계와 진단ㆍ분석 결과를 제공하는 진단 도구입니다.

서비스를 제공하기 위해서는 수 많은 문제들이 필요하고, 문제들을 차곡 차곡 쌓고, 분류해서 관리해야 하는데요. 이러한 데이터베이스를 업계에서는 문제은행(Itembank 혹은 Itempool)이라고 부릅니다. 일종의 문제만 들어 있는 CMS(Contents Management System)인 셈이죠.

하지만, 평가 문제를 정형화된 데이터베이스로 관리하는 길은 험난한데요.

이유가 현실 세계에서는 다양한 형태로 시험(평가) 문제가 존재하기 때문입니다. 크게 2가지 유형으로 하드카피 혹은 소프트카피 상태로 분류해 볼 수 있고, 이런 원천 자료를 디지털화(digitization)하거나, 정규화(normalization)하여 문제은행에 탑재하게 됩니다.

첫 번째로는 하드 카피본으로 존재하는 경우에는 스캔 장치를 통해 이미지화하고, 이후 OCR 기술 등을 통해 이미지로부터 글자와 그림 등을 인식하는 방식을 통해 디지털화됩니다.

두 번째는 소프트 카피본의 경우, 해당 파일로부터 텍스트와 이미지 등을 영역별로 추출하여 정규화하는 과정을 거치게 됩니다. 소프트 카피본의 경우, 일반적으로 알려진 워드프로세서인 한/글 또는 MS워드 등의 파일로 저장되어 있고, 인쇄 등을 통해 발행되는 출판 간행물의 경우에는 인디자인 또는 쿽 파일, 혹은 인쇄용 PDF 파일로 존재합니다.

오늘 소개드리는 내용은 한/글 파일로 작업된 시험지 파일들을 문제은행에 탑재하기 위해 일련의 가공 작업을 하면서, 파악했던 한/글 파일의 구조에 대해 가볍게 공유드려고 합니다.

절대로 무겁지 않고, 가볍게 다루므로, 깊은 생각 없이 읽어주시면 좋겠습니다.


Ⅰ. 한/글 파일의 역사

한글과컴퓨터에서 개발한 한/글(아래한글)은 1989년 1.0 버전 출시 이후, 현재까지 꾸준히 업데이트 되어 한컴오피스 2022까지 발전해 왔는데요. 한/글로 문서를 작성하면, 기본적으로 바이너리 형태의 포맷인 HWP 파일로 저장이 되죠. 하지만, 저장된 문서의 내용을 제3의 시스템에서 활용하기는 여간 까다로운게 아니었습니다.

2010년 경에 바이너리 포맷인 HWP의 형식을 공개했지만, 제3자가 활용하는 것은 여전히 녹록하지 않았던게 사실입니다. 물론, 마크업 언어인 HWPML로 함께 공개했으나 기본 확장자가 아니어서, 사용성이 떨어졌죠. 이후 2011년 말에 국가 표준화 작업으로 HWPML을 기반으로 하여, OWPML(개방형 워드프로세서 마크업 언어)이라는 규격이 만들어집니다. 그럼에도 한/글의 기본 저장 포맷은 아니었기 때문에 사용성면에서는 큰 변화가 없었습니다.

하지만! 2021년 4월 15일에 한글과컴퓨터에서 개방형 문서 포맷인 HWPX를 기본 저장 파일로 변경한다고 발표했고, 실제로 한/글이 업데이트되면서 기본 확장자가 HWPX로 변경되었습니다.

본 글에서 소개하는 한/글 파일의 구조는 OWPML(개방형 워드프로세서 마크업 언어)로 불리는 규격인 HWPX를 기준으로 하고 있습니다.

한컴 '아래아한글' 기본 형식 'HWP→HWPX' 무엇이 달라지나 < IT기업 < IT·과학 < 기사본문 - 블로터
한글과컴퓨터(이하 한컴)의 워드프로세서 '아래아한글(이하 한글)' 문서의 기본 형식이 'HWP'에서 'HPWX'로 바뀐다. 이를 통해 기업은 한글 문서 내 데이터 분류·추출 접근성이 한층 개선되며 기존 한글 이용자들의 사용성에는 큰 변화가 없을 전망이다.한컴은 15일 한글 문서의 기본

Ⅱ. HWPX 파일의 구조 확인하기

HWPX 파일은 문서 본문 내용을 XML로 기술하고 있는데요. 문서 본문에서 참조하고 있는 다른 파일(예: 이미지 등)과 문서 본문을 기술한 XML 파일 등을 하나의 ZIP 파일로 묶고 확장자를 .hwpx를 사용하고 있습니다.

그래서 파일의 확장자를 .zip으로 변경한 뒤, 압축 프로그램으로 압축 해제하면 간단히 HWPX 파일의 내부 파일 구조를 살펴 볼 수 있습니다.

이러한 형태는 IDPF에서 제정한 OCF(Open Container Format) 스펙을 따르기 때문인데요. MS오피스 파일이나, 전자 책 규격인 EPUB에서도 볼 수 있습니다. 참고로, IDPF는 국제 디지털 출판 포럼(International Digital Publishing Forum)의 약자로 전자 출판과 관련된 표준을 제정하는 영향력 있는 협회입니다.

위 그림과 같이 파일의 확장자를 변경하고 압축을 해제하면, 아래와 같이 OCF 스펙에서 정의된 디렉토리(이하, 윈도 기준으로 폴더로 표기 통일합니다.)와 파일의 구조를 확인할 수 있습니다.

최상위(root) 경로에는 아래와 같이 3개의 파일이 존재하게 되는데요.

각 파일의 역할과 내용은 아래와 같습니다.

파일명설명
mimetype 파일
  • OCF 스펙에 따라, MIME 타입을 기술하는 파일
  • HWPX는 application/hwp+zip 라고 기술
version.xml 파일
  • 이 HWPX 문서 파일을 저장한 워드프로세서의 정보 기술
  • OWPML 형식 버전 정보 기술
  • HWPX 파일을 읽고 화면에 렌더링하는 뷰어 개발 시,이 버전에 따라 처리해야 하는 로직이 달라질 수 있음
settings.xml한/글 프로그램에서 사용하는 사용자 설정 값을 저장
(예시) 마지막으로 커서가 있었던 위치 값 등

그리고 아래와 같은 폴더가 존재하고, 그 역할은 다음과 같습니다.

이외 XMLTemplate, DocHistory, Chart 등의 폴더가 존재 할 수 있고, 사용하지 않는(데이터가 없는) 폴더의 경우, 생략 가능합니다.

폴더명설명
META-INF
  • manifest.xml, container.xml, container.rdf 파일
  • ZIP 파일에 적재되어 있는 파일 목록 정보를 지님 (OCF 스펙)
Contents
  • 문서의 실제 콘텐츠 데이터를 담은 XML 파일을 담는 폴더
  • content.hpf, header.xml, section0.xml 등의 파일
BinData
  • 문서에 삽입된 바이너리 파일(예: 이미지 파일 등)을 보관
Preview
  • 문서의 형태를 미리 확인할 수 있는 이미지 파일(PrvImage.png)
  • 순수 텍스트만 추출해둔 (PrvText.txt) 파일
Scripts
  • 문서에서 사용되는 매크로 스크립트 보관
    (예시) default.js 등의 파일

Ⅲ. 문서 본문 내용은 어떻게 관리되는가?

한/글 파일의 문서 본문 내용은 크게 ① 헤더(header) 파일과 ② 섹션(section) 파일 2가지 부분으로 나눠 관리하게 되고, 이 2가지 정보가 어떤 파일들에 기재되어 있는지 관리하는 content.hpf 파일에 의해 문서 관계가 성립됩니다.

1. content.hpf 파일의 구조

content.hpf 파일은 크게 3개의 정보를 기술하고 있고, HWPX 파일로부터 데이터를 파싱(parsing)하거나 렌더링(rendering)하는 뷰어를 만들어야 한다면 가장 먼저 참조해야 하는 파일입니다.

첫 번째는 더블린 코어(Dublin Core) 메타데이터를 기반으로, 문서에 대한 정보를 기술하고 있습니다. 그 내용에는 문서 생성/수정 일시, 생성자, 주제, 설명글, 키워드 등의 정보가 있습니다.

두 번째는 문서에서 참조하고 있는 파일들에 대한 정보로 헤더 파일, 섹션 파일과 더불어 본문에서 사용된 이미지 파일 등의 경로 등이 같이 기술하고 고유한 ID 값을 부여합니다.

마지막으로, 앞서 이야기한 헤더 파일과 섹션 파일의 목록(여러 섹션이 존재할 경우, 그 순서 정보)을 기술한 부분으로 구성되고, 이때 두 번째 영역에서 파일의 목록을 작성하며 부여한 고유한 ID 값의 순서를 나열하게 됩니다. 이 순서가 실제 문서이 조합되는 기준이 됩니다.

content.hpf 파일 내용 예시

<opf:package xmlns:opf="http://www.idpf.org/2007/opf/">
    <!-- 문서 요약 정보를 담은 메타데이터 -->
    <opf:metadata>
        <opf:title>NSAT문항등록카드(시험지형)</opf:title>
        <opf:language>ko</opf:language>
        <opf:meta name="creator" content="text">NHN Edu</opf:meta>
        <opf:meta name="subject" content="text">NSAT문항등록카드</opf:meta>
        <opf:meta name="description" content="text">본 파일은 NSAT 서비스를 위한 문항 등록을 위한 파일입니다.</opf:meta>
        <opf:meta name="lastsaveby" content="text">NHN</opf:meta>
        <opf:meta name="CreatedDate" content="text">2021-06-21T05:33:02Z</opf:meta>
        <opf:meta name="ModifiedDate" content="text">2021-10-05T03:22:32Z</opf:meta>
        <opf:meta name="date" content="text">2020년 6월 13일 토요일 오후 2:47:50</opf:meta>
        <opf:meta name="keyword" content="text">NSAT</opf:meta>
    </opf:metadata>

    <!-- 문서와 관련된 내부 파일 경로 -->
    <opf:manifest>
        <opf:item id="header" href="Contents/header.xml" media-type="application/xml" />
        <opf:item id="image1" href="BinData/image1.png" media-type="image/png" isEmbeded="1" />
        <opf:item id="image2" href="BinData/image2.png" media-type="image/png" isEmbeded="1" />
        <opf:item id="section0" href="Contents/section0.xml" media-type="application/xml" />
        <opf:item id="settings" href="settings.xml" media-type="application/xml" />
    </opf:manifest>

    <!-- 문서의 순서 정보를 정의 -->
    <opf:spine>
        <opf:itemref idref="header" />
        <opf:itemref idref="section0" linear="yes" />
    </opf:spine>
</opf:package>

2. 헤더 파일(header.xml)의 구조

헤더 파일에서는 문서 본문에서 참조하는 문서의 편집 스타일에 대한 정보를 다루게 되는데요. 웹 페이지를 구성하는 HTML과 CSS의 관계를 보았을 떄, CSS 파일에 해당된다고 이해하면 됩니다.

각 정보 단위별로 설정된 값의 묶음이 존재하고, CSS의 클래스 선택자(Class Selector)와 유사한 개념으로 이해하면 될 것 같습니다. 그래서 이 정보 마다 고유한 ID가 부여되고, 이 ID 값을 헤더 파일 내에서 상호 참조하고 있거나, 본문 내용을 기록하는 섹션 파일 내에서 참조하여, 문서 편집 정보를 표현하게 됩니다.

일반적으로 아래 정도의 정보 영역이 존재하고, 이외 필요에 따라 참고해서 활용하면 됩니다.
이해를 돕기 위해 정보 영역과 관련된 한/글 상의 화면도 같이 삽입해 보았습니다.

정보 영역명(XML 노드명)노드 설명 / 관련 화면
글꼴(fontfaces)<ul><li>언어 별로 문서에서 사용된 글꼴 목록 정보</li><li>한글/영문/한자/일어/기타 외국어/기호/사용자 정의 영역로 구별</li><li>글꼴 유형은 트루타입 글꼴(TTF) 혹은 한/글 전용 글꼴(HFT) 중에서 선택</li><li>해당 글꼴이 없을 때, 대체 사용될 글꼴 정보를 subsFont 노드에서 정의</li></ul>
테두리(borderFills)<ul><li>표와 셀에서 적용 받는 테두리에 대한 옵션 정보</li><li>CSS의 border 속성에 해당- 상/하/좌/우 방향 테두리의 두께와 색상, 표현 방식을 정의</li><li>대각선 방향의 테두리도 정의 가능- 테두리의 두께는 기본적으로 mm로 지정하고, 0.1mm부터 설정 가능</li><li>테두리의 색상은 CSS에서 사용하는 HEX Color 값으로 설정하게 됨</li><li>섹션 파일에서 표 등을 삽입 시, 여기에서 정의한 테두리 설정  값을 참조</li></ul>
글자 속성(charProperties)<ul><li>본문 내용으로 입력한 글자 모양에 대한 옵션 정보</li><li>글꼴에 대한 정보는 앞서 fontfaces에서 추가한 값을 참조</li><li>글자 색상과 크기(장평,자간 등등)에 대한 설정 값을 줄 수 있음</li><li>글자를 꾸미는 요소로 굵게, 이탤릭, 밑줄, 취소선, 윤곽선 등의 효과를 줄 수 있음</li></ul>
탭 속성(tabProperties)<ul><li>본문에서 특정 부분을 내어쓰기를 하기 위해 설정 탭에 대한 정보</li><li>탭의 종류(왼쪽/오른쪽/가운데/소수점), 채울 모양 정보</li><li>탭 위치를 지정할 수 있고, 위치 값에 대한 단위는 HWPUNIT 또는 mm 등 편집 단위를 사용 할 수 있음</li></ul>
문단 번호 목록(numberings)<ul><li>문단에 자동으로 넘버링할 형식 정보</li><li>각 수준 별로 시작 번호 서식과 번호 모양, 너비 등을 지정할 수 있음</li><li>HTML의 <ol> 태그에 대해, CSS로 스타일을 조정하는 것으로 이해하면 됨</li></ul>
문단 속성(paraProperties)<ul><li>문단에 적용될 모양 정보</li><li>텍스트 정렬 방향(양쪽 균등/왼쪽/중앙/오른쪽 등)</li><li>여백 정보, 들여쓰기/내어쓰기</li><li>줄 간격, 문단 위/아래 여백</li></ul>
한/글 스타일(styles)<ul><li>문단 모양, 글자 모양, 문단 번호글 머리표 등을 미리 지정해 두고, 명칭을 붙여 관리하는 스타일에 대한 정보를 기술</li><li>CSS의 개념을 차용하면, 여러 클래스 선택자(selector)를 묶어두는 상위 클래스 선택자의 개념으로 이해하면 됨</li></ul>
글 머리표 문단 모양 목록(bullets)
  • 문단 번호와 같이, 순서 없이 불릿과 같은 모양으로 목록을 나열할 때 사용하는 정보
  • HTML의 태그에 대한 CSS 클래스 선택자라고 이해하면 됨
메모 모양 목록(memoProperties)설명 생략
변경 추적 정보 목록(trackChanges)설명 생략
변경 추적 검토자 목록(trackChangeAuthors)설명 생략

header.xml 파일 내용 예시

<?xml version="1.0" encoding="UTF-8"?>
<hh:head xmlns:hh="http://www.hancom.co.kr/hwpml/2011/head" version="1.31" secCnt="1">
    <hh:beginNum page="1" footnote="1" endnote="1" pic="1" tbl="1" equation="1" />
    <hh:refList>
        <hh:fontfaces itemCnt="1">
            <hh:fontface lang="HANGUL" fontCnt="4">
                <hh:font id="0" face="한컴바탕" type="TTF" isEmbedded="0">
                    <hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1" />
                </hh:font>
            </hh:fontface>
            <hh:fontface lang="LATIN" fontCnt="4" />
            <hh:fontface lang="HANJA" fontCnt="4" />
            <hh:fontface lang="JAPANESE" fontCnt="4" />
            <hh:fontface lang="OTHER" fontCnt="4" />
            <hh:fontface lang="SYMBOL" fontCnt="4" />
            <hh:fontface lang="USER" fontCnt="4" />
        </hh:fontfaces>
        <hh:borderFills itemCnt="1">
            <hh:borderFill id="1" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
                <hh:slash type="NONE" Crooked="0" isCounter="0" />
                <hh:backSlash type="NONE" Crooked="0" isCounter="0" />
                <hh:leftBorder type="NONE" width="0.1 mm" color="#000000" />
                <hh:rightBorder type="NONE" width="0.1 mm" color="#000000" />
                <hh:topBorder type="NONE" width="0.1 mm" color="#000000" />
                <hh:bottomBorder type="NONE" width="0.1 mm" color="#000000" />
                <hh:diagonal type="SOLID" width="0.1 mm" color="#000000" />
            </hh:borderFill>
        </hh:borderFills>
        <hh:charProperties itemCnt="1">
            <hh:charPr id="0" height="1000" textColor="#000000" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1">
                <hh:fontRef hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0" />
                <hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100" />
                <hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0" />
                <hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100" />
                <hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0" />
            </hh:charPr>
        </hh:charProperties>
        <hh:tabProperties itemCnt="1">
            <hh:tabPr id="2" autoTabLeft="1" autoTabRight="1" />
        </hh:tabProperties>
        <hh:numberings itemCnt="1">
            <hh:numbering id="1" start="0">
                <hh:paraHead start="1" level="1" align="LEFT" useInstWidth="1" autoIndent="1" widthAdjust="0" textOffsetType="PERCENT" textOffset="50" numFormat="DIGIT" charPrIDRef="4294967295" checkable="0">^1.</hh:paraHead>
            </hh:numbering>
        </hh:numberings>
        <hh:paraProperties itemCnt="1">
            <hh:paraPr id="0" tabPrIDRef="0" condense="0" fontLineHeight="0" snapToGrid="1" suppressLineNumbers="0" checked="0">
                <hh:align horizontal="JUSTIFY" vertical="BASELINE" />
                <hh:heading type="NONE" idRef="0" level="0" />
                <hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="KEEP_WORD" widowOrphan="0" keepWithNext="0" keepLines="0" pageBreakBefore="0" lineWrap="BREAK" />
                <hh:autoSpacing eAsianEng="0" eAsianNum="0" />
                <hp:switch />
                <hh:border borderFillIDRef="2" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0" />
            </hh:paraPr>
        </hh:paraProperties>
        <hh:styles itemCnt="1">
            <hh:style id="0" type="PARA" name="바탕글" engName="Normal" paraPrIDRef="0" charPrIDRef="10" nextStyleIDRef="0" langID="1042" lockForm="0" />
        </hh:styles>
    </hh:refList>
    <hh:compatibleDocument targetProgram="HWP201X">
        <hh:layoutCompatibility />
    </hh:compatibleDocument>
    <hh:docOption>
        <hh:linkinfo path="" pageInherit="1" footnoteInherit="0" />
    </hh:docOption>
    <hh:trackchageConfig flags="56" />
</hh:head>

3. 섹션 (section0.xml) 파일

3.1. 구역 나누기

섹션 파일은 한/글의 구역 나누기와 대응되는데요.

구역 나누기 기능은 보통은 잘 사용하지 않으나, 위 그림과 같이 A4 용지를 세로 방향으로 작성하다가

특별히 표를 넓게 봐야해서 특정 페이지만 가로 방향으로 전환하여 편집해야 하는 경우 활용되게 됩니다.

문서 편집 과정에서 여러 구역으로 나누지 않았다면 section0.xml 파일만 존재하게 되는데요.

구격 나누기를 한 상태라면, section1.xml 등과 같이 다른 섹션 파일이 존재할 수 있게 됩니다.

이때 구역의 순서 정보는 content.hpf 파일에서 정의하는 것을 참조해야 합니다.

3.2. 본문 내용

섹션 파일에는 실제 문서 본문의 내용을 구조화하여 저장하게 되는데요. 구조화된 내용을 꾸미는 방법에 대해서는 앞서 다룬 헤더 파일의 각 속성 값들의 ID 값을 참조하게 됩니다.

텍스트와 이미지, 표가 삽입된 문서를 기준으로 구조를 포함 관계를 그려보면 아래 그림과 같습니다.

문서는 모두 문단의 나열과 조합으로 구성되기 때문에 최상위 노드인 섹션 노드(<hs:sec>) 하위에는 문단을 의미하는 <hp:p> 노드가 위치해야 합니다.

그리고 문단(<hp:p>) 노드 하위에는 <hp:run> 노드를 통해 내용을 구성하는 텍스트, 이미지, 표 등을 처리할 수 있습니다. <hp:run> 노드는 항상 <hp:linesegarray> 노드를 형제 노드로 쌍을 이루어야 하는 규칙을 가지고 있는데요. 해당 문단 내 줄 마다 간격 정보를 설정하는데 활용하게 됩니다.


Ⅳ. 익숙한 HTML 코드와 비교해 보기

지금까지는 HWPX 파일의 구조와, 구성이 어떻게 되는지를 살펴 보았는데요.

실제 우리가 익숙한 HTML과 어떻게 작성 방법이 다른지를 살펴보려고 합니다.

주로 많이 사용되는 개념과 대응되게 정리해 보았으며, 대략적인 느낌으로 참고해 주세요.

① 일반 텍스트 표기 (기본 문단에 글 쓰기)

HWPX 코드

파일 구분예시 코드
헤더 파일
섹션 파일

CSS 코드

/* 정의할 사항 없음 */

HTML 코드

<p>
일반 텍스트
</p>
②~④. 글자 굵게 / 이탤릭 / 밑줄 처리하기

HWPX 코드

파일 구분예시 코드
헤더 파일
섹션 파일

CSS 코드

.charPr7 { <span class="hljs-attribute">font-weight:bold; }
.charPr8 { <span class="hljs-attribute">font-style:italic; }
.charPr9 { <span class="hljs-attribute">text-decoration:underline; }

HTML 코드

<p>
  <span class="charPr7">글자 굵게<span> class="hljs-tag"></span>
</p>
<p>
  <span class="charPr8">글자 이탤릭<span> class="hljs-tag"></span>
</p>
<p>
  <span class="charPr9">글자 밑줄<span> class="hljs-tag"></span>
</p>
⑤~⑥. 글자 위 첨자 / 아래 첨자 처리

HWPX 코드

파일 구분예시 코드
헤더 파일
섹션 파일

CSS 코드

/* 정의할 사항 없음 */

HTML 코드

<p>  
  <sup>글자 위 첨자</sup>
</p>
<p>
  <sub>글자 아래 첨자</sub>
</p>
⑦~⑩. 글자 색상 변경 및 복합 스타일 지정

HWPX 코드

파일 구분예시 코드
헤더 파일
섹션 파일

CSS 코드

.charPr12 { <span class="hljs-attribute">color:<span class="hljs-number">#ff0000; }
.charPr13 { <span class="hljs-attribute">font-weight:bold;<span class="hljs-attribute">text-decoration:underline; }
.charPr14 { <span class="hljs-attribute">font-weight:bold;<span class="hljs-attribute">font-style:italic; }
.charPr15 { <span class="hljs-attribute">font-weight:bold;<span class="hljs-attribute">color:<span class="hljs-number">#ff0000; }

HTML 코드

<p>
<span class="charPr12">글자 빨강<span> class="hljs-tag"></span>
</p>
<p>
<span class="charPr13">글자 굵고, 밑줄<span> class="hljs-tag"></span>
</p>
<p>
<span class="charPr14">글자 굵고, 이탤릭<span> class="hljs-tag"></span>
</p>
<p>
<span class="charPr15">글자 굵고, 글자 빨강<span> class="hljs-tag"></span>
</p>

Ⅴ. HWPX 파일 공통으로 참고하면 좋을 Tip

1. 한/글 파일에서 사용하는 단위 값

  • 대부분 HWPUNIT이라고 한/글 자체 단위를 사용하고 있습니다.
  • 10pt = 1000 hwpunit 이라고 스펙 문서에 정의되어 있어서, 한/글 파일을 HTML 등으로 변환 시 단위 변환에 주의가 필요합니다.

2. 하위 노드의 갯수

  • 컨테이너 성격의 노드(예: 헤더 파일의 hh:charProperties 노드 등)에서는 하위 노드의 갯수를 ~Cnt패턴의 속성으로 관리하고 있습니다.
  • 경우에 따라서, 이 속성이 누락되거나 값과 실제 하위 노드의 갯수가 맞지 않으면 HWPX 파일을 한/글에서 열었을 때 프로그램이 바로 종료될 수 있습니다.
  • 특히 표를 처리할 때는 표를 구성하는 행(row)의 갯수와 행 안에서 칸(cell)의 갯수를 잘 기재해야 합니다.

3. HTML의 \ \ \ 등의 스타일 관련 태그는 헤더에서 관리

  • 앞서 HTML 코드와의 비교에서 살펴본 것과 같이 섹션 파일은 본문 내용에 대한 데이터 구조만 다룹니다.
  • 그래서 HTML에서 태그로 글자 스타일을 조정했던 것은 HWPX에서는 지원하지 않기 때문에 모두 헤더 파일에서 스타일을 정의하고 참조하는 구조로 작성해야 합니다.

Ⅵ. 기타 참고해볼만한 한/글 관련 오픈 소스 프로젝트들

1. hwp.js

2. 한글 수식 변환기


참고 자료

HWP : 한글과컴퓨터

한컴오피스와 함께 HWP 파일 포맷을 추가 공개합니다.
KS X 6101: 국가표준 상세 | e나라 표준인증

개방형 워드프로세서 마크업 언어(OWPML) 문서 구조

이찬희 (MarkiiimarK)
Never Stop Learning.