logo
HWPJS
  • 가이드
  • API
  • 명세서
  • 로드맵
  • 백로그
    명세서
    HWP 자료형 (Types)
    HWP 3.0 / HWPML 형식
    HWP 5.0
    배포용 문서 형식
    한글 문서 파일 형식 - 수식
    차트 형식
    Previous pageHWP 3.0 / HWPML 형식Next page배포용 문서 형식

    #HWP 5.0

    revision 1.3: 20181108

    #차례

    • 저작권 - 페이지 1
    • 본 문서에 대하여 - 페이지 2
    • I. 한글 5.0 파일 구조 - 페이지 3
      • 1. 개요 - 페이지 5
      • 2. 자료형 설명 - 페이지 6
      • 3. 한글 파일 구조 - 페이지 7
        • 3.1. 한글 파일 구조 요약 - 페이지 7
        • 3.2. 스토리지 별 저장 정보 - 페이지 7
          • 3.2.1. 파일 인식 정보 - 페이지 7
          • 3.2.2. 문서 정보 - 페이지 8
          • 3.2.3. 본문 - 페이지 9
          • 3.2.4. 문서 요약 - 페이지 12
          • 3.2.5. 바이너리 데이터 - 페이지 12
          • 3.2.6. 미리보기 텍스트 - 페이지 12
          • 3.2.7. 미리보기 이미지 - 페이지 13
          • 3.2.8. 문서 옵션 - 페이지 13
          • 3.2.9. 스크립트 - 페이지 13
          • 3.2.10. XML 템플릿 - 페이지 13
          • 3.2.11. 문서 이력 관리 - 페이지 14
          • 3.2.12. 참고문헌 - 페이지 15
      • 4. 데이터 레코드 - 페이지 16
        • 4.1. 데이터 레코드 구조 - 페이지 16
        • 4.2. '문서 정보'의 데이터 레코드 - 페이지 17
          • 4.2.1. 문서 속성 - 페이지 17
          • 4.2.2. 아이디 매핑 헤더 - 페이지 17
          • 4.2.3. 바이너리 데이터 - 페이지 18
          • 4.2.4. 글꼴 - 페이지 20
          • 4.2.5. 테두리/배경 - 페이지 21
          • 4.2.6. 글자 모양 - 페이지 24
          • 4.2.7. 탭 정의 - 페이지 26
          • 4.2.8. 문단 번호 - 페이지 26
          • 4.2.9. 글머리표 - 페이지 27
          • 4.2.10. 문단 모양 - 페이지 28
          • 4.2.11. 스타일(문단 스타일) - 페이지 29
          • 4.2.12. 문서 임의의 데이터 - 페이지 30
          • 4.2.13. 배포용 문서 데이터 - 페이지 31
          • 4.2.14. 호환 문서 - 페이지 32
          • 4.2.15. 레이아웃 호환성 - 페이지 32
        • 4.3. '본문'의 데이터 레코드 - 페이지 33
          • 4.3.1. 문단 헤더 Tag ID : HWPTAG_PARA_HEADER - 페이지 33
          • 4.3.2. 문단의 텍스트 - 페이지 34
          • 4.3.3. 문단의 글자 모양 - 페이지 34
          • 4.3.4. 문단의 레이아웃 - 페이지 35
          • 4.3.5. 문단의 영역 태그 - 페이지 35
          • 4.3.6. 컨트롤 헤더 - 페이지 35
          • 4.3.7. 문단 리스트 헤더 - 페이지 36
          • 4.3.8. 컨트롤 임의의 데이터 - 페이지 36
          • 4.3.9. 개체 공통 속성을 포함하는 컨트롤(개체 컨트롤) - 페이지 36
            • 4.3.9.1. 표 개체 - 페이지 39
            • 4.3.9.2. 그리기 개체(선, 사각형, 타원, 호, 다각형, 곡선) - 페이지 40
              • 4.3.9.2.1. 개체 요소 - 페이지 40
              • 4.3.9.2.2. 선 개체 - 페이지 42
              • 4.3.9.2.3. 사각형 개체 - 페이지 43
              • 4.3.9.2.4. 타원 개체 - 페이지 43
              • 4.3.9.2.5. 다각형 개체 - 페이지 45
              • 4.3.9.2.6. 호 개체 - 페이지 45
              • 4.3.9.2.7. 곡선 개체 - 페이지 45
            • 4.3.9.3. 흔글 수식 개체 - 페이지 46
            • 4.3.9.4. 그림 개체(HWPTAG_SHAPE_COMPONENT_PICTURE) - 페이지 46
            • 4.3.9.5. OLE 개체(HWPTAG_SHAPE_COMPONENT_OLE) - 페이지 49
            • 4.3.9.6. 차트 개체 - 페이지 50
            • 4.3.9.7. 묶음 개체(HWPTAG_SHAPE_COMPONENT_CONTAINER) - 페이지 51
            • 4.3.9.8. 동영상 개체(HWPTAG_VIDEO_TDATA) - 페이지 51
          • 4.3.10. 개체 이외의 컨트롤 - 페이지 52
            • 4.3.10.1. 구역 정의 - 페이지 53
              • 4.3.10.1.1. 용지 설정 - 페이지 54
              • 4.3.10.1.2. 각주/미주 모양 - 페이지 55
              • 4.3.10.1.3. 쪽 테두리/배경 - 페이지 56
            • 4.3.10.2. 단 정의 - 페이지 56
            • 4.3.10.3. 머리말/꼬리말 - 페이지 57
            • 4.3.10.4. 각주/미주 - 페이지 57
            • 4.3.10.5. 자동 번호 - 페이지 58
            • 4.3.10.6. 새 번호 지정 - 페이지 58
            • 4.3.10.7. 감추기 - 페이지 58
            • 4.3.10.8. 홀/짝수 조정 - 페이지 59
            • 4.3.10.9. 쪽 번호 위치 - 페이지 59
            • 4.3.10.10. 찾아보기 표식 - 페이지 59
            • 4.3.10.11. 책갈피 - 페이지 60
            • 4.3.10.12. 글자 겹침 - 페이지 60
            • 4.3.10.13. 덧말 - 페이지 60
            • 4.3.10.14. 숨은 설명 - 페이지 60
            • 4.3.10.15. 필드 시작 - 페이지 61
        • 4.4. 문서 이력 관리 - 페이지 62
          • 4.4.1. 문서 이력 관리란 - 페이지 62
          • 4.4.2. 문서 이력 관리 레코드 정보 - 페이지 62
            • 4.4.2.1. 히스토리 아이템 정보 시작 - 페이지 62
            • 4.4.2.2. 히스토리 아이템 정보 끝 - 페이지 62
            • 4.4.2.3. 히스토리 아이템 버전 - 페이지 63
            • 4.4.2.4. 히스토리 날짜 - 페이지 63
            • 4.4.2.5. 히스토리 작성자 - 페이지 63
            • 4.4.2.6. 히스토리 설명 - 페이지 63
            • 4.4.2.7. 비교 정보 - 페이지 63
            • 4.4.2.8. 가장 마지막 최근 문서 - 페이지 63
          • 변경 사항 이력 - 페이지 65

    #저작권

    (주)한글과컴퓨터(이하 '한컴')는 문서 형식의 개방성과 표준화에 대하여 적극 찬성합니다. 한컴은 한글 97의 문서 형식을 무상으로 지원한 바 있으며, 한글 2002~2010 문서의 XML 형식은 HWPML에 대해서도 문서 형식을 공개한 바 있습니다. 개방형 문서 표준화 및 코드 관련 위원회에도 적극적으로 참여하여 파일 형식의 표준화와 개방성을 위해 노력해 왔습니다. 이러한 결과로 HWPML 스펙이 OWPML란 이름으로 한국산업표준(KS X 6101:2011)으로 제정되었습니다. 또한, 한컴오피스에서 기록물 장기보존 표준 포맷인 PDF/A-1의 지원과 ISO 국제 문서 형식인 ODF와 OOXML 파일 형식의 불러오기와 저장하기를 적극적으로 지원하였습니다.

    본 문서를 열람하고자 하는 자라면 누구에게나 제공되는 것이며, 본 문서를 열람하는 것 외에 복사, 배포, 게재 및 본 문서에 기재되어 있는 내용을 사용하고자 하는 자는 한글과컴퓨터의 본 저작권을 충분히 인식하고 동의하여야 합니다.

    본 문서를 누구나 열람, 복사, 배포, 게재 및 사용을 자유롭게 할 수 있습니다. 다만, 배포는 원 내용이 일체 수정되지 않은 원본 또는 복사본으로 제한됩니다. 원본 및 복사본은 한컴에서 제공하는 스펙의 최신 버전을 포함하고 있어야 합니다.

    한컴은 한컴오피스 한글 문서 파일(.hwp) 공개 문서에 따라 얻은 결과물을 기초로 또 다른 독점적, 배타적 권리를 취득하고 이를 (주)한글과컴퓨터를 상대로 행사하고자 하는 자를 상대로는 적극적으로 권리행사를 할 수도 있습니다.

    그리고, 본 문서 및 본 문서에 기재된 내용을 참고하여 개발한 결과물에 대한 모든 저작권은 결과물을 개발한 개인 또는 단체에 있을 것입니다. 그러나 반드시 개발 결과물에 "본 제품은 한글과컴퓨터의 한글 문서 파일(.hwp) 공개 문서를 참고하여 개발하였습니다."라고 제품 내 사용자 인터페이스, 매뉴얼, 도움말 및 소스에 모두 기재하여야 하며 제품이 이러한 구성물이 없을 시에는 존재하는 구성물에만 기재합니다. 한컴은 본 문서 및 본 문서에 기재된 내용을 참고하여 개발한 결과물에 대해서 어떠한 정확성, 진실성도 보증하지 아니합니다.


    #본 문서에 대하여

    본 문서는 한글 워드 프로세서의 파일 저장 형식 중, 한글 2002 이후 제품에서 사용되는 한글 문서 파일 형식 5.0에 관하여 설명한다.

    본 문서는 한글 문서 파일 형식 5.0의 주요한 자료 형식 및 파일 구조, 레코드 구조에 대해서 설명한다.

    한글 문서 수식, 차트, 배포용 문서, 한글 문서 파일 형식 3.0, HWPML에 관해서는 별도의 문서에서 설명한다.


    #I. 한글 5.0 파일 구조

    #1. 개요

    한글 문서 파일은 사용자가 지정하지 않는 한 기본적으로 .HWP 확장자를 사용한다.

    이 파일에 저장되는 내용은 사용자가 입력한 문서의 텍스트와 글자 모양 정보뿐만 아니라 편집 시 사용한 글꼴 정보와 용지 종류, 여백 정보 등 다양한 조판 설정 정보도 포함된다.

    한글 문서 파일 형식 5.0은 2000년 10월 이후 출시된 한글 제품군(예: 한글 워디안, 한글 2002, 한글 2005, 한글 2007, 한글 2010, 한글 2014, 한글 2018)에서 생성된다. 전체적인 구조는 동일하지만 추가된 정보로 인해 약간의 차이가 있을 수 있다.

    한글 문서 파일 형식 5.0은 파일 크기를 최소화하기 위해 압축을 사용한다. 압축된 문서 파일의 기본 정보 저장 부분은 압축되지 않으며, 사용자가 입력한 본문 텍스트와 이미지 관련 데이터만 압축된다.

    한글은 문서 파일 압축을 위해 zlib.org의 zlib을 사용한다. zlib은 소스 코드가 공개된 오픈소스 소프트웨어이다. zlib License에 따라 동작하며, 소스 코드를 자유롭게 사용할 수 있고 파생 작품에 대해서는 소스 코드 공개를 요구하지 않는다. 자세한 내용은 zlib에 포함된 라이선스 문서를 참조하라.

    한글 문서 파일 형식 5.0의 구조는 Windows Compound Files를 기반으로 하며, 문자 인코딩은 ISO-10646 표준을 따른다. 대부분의 문자 정보는 Unicode(UTF-16LE) 형식으로 전송 및 저장된다.

    참고: Compound Files에 접근하는 방법은 OLE 관련 문서나 MSDN의 StgOpenStorage(), IStorage::Open() 등의 함수를 참조하라.

    #2. 자료형 설명

    앞으로 계속되는 설명에서 한글의 문서 파일에 저장되는 정보는 아래 표에 설명하는 자료형을 이용해 표현한다.

    자료형에서 한 바이트는 8 비트로 표현되며, 두 바이트 이상의 길이를 가지는 자료형은 최하위 바이트가 가장 먼저 저장되고, 최상위 바이트가 가장 나중에 저장되는 리틀 엔디언(Little-endian) 형태이다.

    파일에 저장되는 자료가 배열(array)일 때는 '자료형 array[개수]'와 같이 표현한다. 예를 들어 10개의 원소를 갖는 word 배열이면 'word array[10]'과 같이 표현한다.

    표 1: 자료형

    자료형길이부호설명
    BYTE1부호 없는 한 바이트(0~255)
    WORD216비트 컴파일러에서 'unsigned int'에 해당
    DWORD416비트 컴파일러에서 'unsigned long'에 해당
    WCHAR2한글의 기본 코드로 유니코드 기반 문자
    HWPUNIT41/7200인치로 표현된 한글 내부 단위
    SHWPUNIT4✓1/7200인치로 표현된 한글 내부 단위
    UINT81'unsigned_int8'에 해당
    UINT162'unsigned_int16'에 해당
    UINT32(=UINT)4'unsigned_int32'에 해당
    INT81✓'signed_int8'에 해당
    INT162✓'signed_int16'에 해당
    INT324✓'signed_int32'에 해당
    HWPUNIT162✓INT16과 같다
    COLORREF4RGB값(0x00bbggrr)을 십진수로 표시 (rr: red 1 byte, gg: green 1 byte, bb: blue 1 byte)
    BYTE stream일련의 BYTE로 구성됨. 본문 내에서 다른 구조를 참조할 경우에 사용됨.

    WCHAR는 한글의 내부 코드로 표현된 문자 한 글자를 표현하는 자료형이다. 한글의 내부 코드는 한글, 영문, 한자를 비롯해 모든 문자가 2 바이트의 일정한 길이를 가진다.

    HWPUNIT과 SHWPUNIT는 문자의 크기, 그림의 크기, 용지 여백 등, 문서를 구성하는 요소들의 크기를 표현하기 위한 자료형이다. 문서 출력 장치의 해상도는 가변적이기 때문에, 크기 정보를 점(도트)의 수로 표현할 수는 없다. 따라서 일정한 단위를 기준으로 해야 하는데, 한글에서는 1/7200인치를 기본 단위로 사용한다. 예를 들어 [가로 2인치 x 세로 1인치]짜리 그림의 크기를 HWPUNIT 형으로 표현하면 각각 14400 x 7200이 된다.

    #3. 한글 파일 구조

    #3.1. 한글 파일 구조 요약

    한글 문서 파일은 복합 파일(Compound File) 구조를 가지며, 내부적으로 스토리지(Storage)와 스트림(Stream)으로 구성된다. 스트림에는 바이너리 또는 레코드 구조의 데이터가 저장되며, 압축/암호화될 수 있다.

    표 2: 전체 구조

    설명구별 이름길이레코드 구조압축/암호화
    파일 인식 정보FileHeader고정사용 안 함사용 안 함
    문서 정보DocInfo고정사용사용
    본문BodyText가변사용사용
    - Section0Section0가변사용사용
    - Section1Section1가변사용사용
    문서 요약\005HwpSummaryInformation고정사용 안 함사용 안 함
    바이너리 데이터BinData가변사용 안 함사용
    - BinaryData0BinaryData0가변사용 안 함사용
    - BinaryData1BinaryData1가변사용 안 함사용
    미리보기 텍스트PrvText고정사용 안 함사용 안 함
    미리보기 이미지PrvImage가변사용 안 함사용 안 함
    문서 옵션DocOptions가변사용 안 함사용 안 함
    - _LinkDoc_LinkDoc가변사용 안 함사용 안 함
    - DrmLicenseDrmLicense가변사용 안 함사용 안 함
    스크립트Scripts가변사용 안 함사용 안 함
    - Default.JScriptDefault.JScript가변사용 안 함사용 안 함
    - JScriptVersionJScriptVersion가변사용 안 함사용 안 함
    XML 템플릿XMLTemplate가변사용 안 함사용 안 함
    - SchemaSchema가변사용 안 함사용 안 함
    - InstanceInstance가변사용 안 함사용 안 함
    문서 이력 관리DocHistory가변사용사용
    - VersionLog0VersionLog0가변사용사용
    - VersionLog1VersionLog1가변사용사용

    압축된 문서 파일은 '파일 인식 정보'의 '압축' 플래그를 확인하여 압축을 풀고 처리해야 한다. 이후 설명은 압축이 풀린 상태의 파일을 기준으로 한다.

    '문서정보', '본문', '문서 이력 관리'에 사용되는 '레코드 구조'는 '데이터 레코드' 섹션에서 상세히 설명된다.

    #3.2. 스토리지 별 저장 정보

    #3.2.1. 파일 인식 정보

    한글의 문서 파일이라는 것을 나타내기 위해 '파일 인식 정보'가 저장된다. FileHeader 스트림에 저장되는 데이터는 다음과 같다.

    표 3: 파일 인식 정보

    자료형길이(바이트)설명
    BYTE array[32]32signature. 문서 파일은 "HWP Document File"
    DWORD4파일 버전. 0xMMnnPPrr의 형태(예 5.0.3.0)
    - MM: 문서 형식의 전체적인 구조 변경을 나타냄. 숫자가 다르면 이전 버전과 호환되지 않음
    - nn: 전체 구조는 같지만 주요 변경이 있음을 나타냄. 숫자가 다르면 이전 버전과 호환되지 않음
    - PP: 구조는 같지만 Record가 추가되었거나 이전 버전과 호환되지 않는 정보가 추가되었음을 나타냄. 숫자가 달라도 이전 버전과 호환됨
    - rr: Record에 정보가 추가되었음을 나타냄. 숫자가 달라도 이전 버전과 호환됨
    DWORD4속성
    - bit 0: 압축 여부
    - bit 1: 암호 설정 여부
    - bit 2: 배포용 문서 여부
    - bit 3: 스크립트 저장 여부
    - bit 4: DRM 보안 문서 여부
    - bit 5: XMLTemplate 스토리지 존재 여부
    - bit 6: 문서 이력 관리 존재 여부
    - bit 7: 전자 서명 정보 존재 여부
    - bit 8: 공인 인증서 암호화 여부
    - bit 9: 전자 서명 예비 저장 여부
    - bit 10: 공인 인증서 DRM 보안 문서 여부
    - bit 11: CCL 문서 여부
    - bit 12: 모바일 최적화 여부
    - bit 13: 개인 정보 보안 문서 여부
    - bit 14: 변경 추적 문서 여부
    - bit 15: 공공누리(KOGL) 저작권 문서
    - bit 16: 비디오 컨트롤 포함 여부
    - bit 17: 차례 필드 컨트롤 포함 여부
    - bit 18~31: 예약
    DWORD4속성
    - bit 0: CCL, 공공누리 라이선스 정보
    - bit 1: 복제 제한 여부
    - bit 2: 동일 조건 하에 복제 허가 여부 (복제 제한인 경우 무시)
    - bit 3~31: 예약
    DWORD4EncryptVersion
    - 0: None
    - 1: (한글 2.5 버전 이하)
    - 2: (한글 3.0 버전 Enhanced)
    - 3: (한글 3.0 버전 Old)
    - 4: (한글 7.0 버전 이상)
    BYTE1공공누리(KOGL) 라이선스 지원 국가
    - 6: KOR
    - 15: US
    BYTE array[207]207예약
    전체 길이256
    #3.2.2. 문서 정보

    문서 내에서 공통으로 사용되는 글꼴, 글자 속성, 문단 속성, 탭, 스타일 등의 상세 정보가 저장된다. 이 정보는 DocInfo 스트림에 저장된다.

    DocInfo 스트림에 저장되는 데이터는 다음과 같다.

    표 4: 문서 정보

    Tag ID길이(바이트)레벨설명
    HWPTAG_DOCUMENT_PROPERTIES30
    26
    0⚠️ 문서 속성(표 14 참조)
    HWPTAG_ID_MAPPINGS320아이디 매핑 헤더(표 15 참조)
    HWPTAG_BIN_DATA가변1바이너리 데이터(표 17 참조)
    HWPTAG_FACE_NAME가변1글꼴(표 19 참조)
    HWPTAG_BORDER_FILL가변1테두리/배경(표 23 참조)
    HWPTAG_CHAR_SHAPE721글자 모양(표 33 참조)
    HWPTAG_TAB_DEF141탭 정의(표 36 참조)
    HWPTAG_NUMBERING가변1문단 번호(표 38 참조)
    HWPTAG_BULLET101글머리표(표 42 참조)
    HWPTAG_PARA_SHAPE541문단 모양(표 43 참조)
    HWPTAG_STYLE가변1스타일(표 47 참조)
    HWPTAG_MEMO_SHAPE221메모 모양
    HWPTAG_TRACK_CHANGE_AUTHOR가변1변경 추적 작성자
    HWPTAG_TRACK_CHANGE가변1변경 추적 내용 및 모양
    HWPTAG_DOC_DATA가변0문서 임의의 데이터(표 49 참조)
    HWPTAG_FORBIDDEN_CHAR가변0금칙처리 문자
    HWPTAG_COMPATIBLE_DOCUMENT40호환 문서(표 54 참조)
    HWPTAG_LAYOUT_COMPATIBILITY201레이아웃 호환성(표 56 참조)
    HWPTAG_DISTRIBUTE_DOC_DATA2560배포용 문서
    HWPTAG_TRACKCHANGE10321변경 추적 정보
    전체 길이가변

    각 상세 정보는 '<문서 정보>의 데이터 레코드' 섹션에서 상세히 설명된다.

    #3.2.3. 본문

    문서의 본문에 해당하는 문단, 표, 그리기 개체 등의 내용이 저장되는 곳이다.

    BodyText 스토리지는 Section%d 스트림으로 나뉘며, %d는 구역 번호를 나타낸다. 구역의 개수는 문서 정보의 문서 속성에 저장된다.

    각 구역의 첫 번째 문단에는 구역 정의 레코드가 저장되고, 각 단 설정의 첫 번째 문단에는 단 정의 레코드가 저장된다.

    각 구역의 가장 마지막에는 확장 기본 쪽(마지막 쪽, 임의 쪽) 관련 정보가 저장되고, 마지막 구역의 가장 마지막에는 메모 관련 정보가 저장된다.

    Section 스트림에 저장되는 데이터는 문단(문단의 리스트)으로 구성되며, 다음 문단 정보가 반복된다.

    표 5: 본문

    Tag ID길이(바이트)레벨설명
    HWPTAG_PARA_HEADER220문단 헤더(표 58 참조)
    HWPTAG_PARA_TEXT가변1문단의 텍스트(표 60 참조)
    HWPTAG_PARA_CHAR_SHAPE가변1문단의 글자 모양(표 61 참조)
    HWPTAG_PARA_LINE_SEG가변1문단의 레이아웃
    HWPTAG_PARA_RANGE_TAG가변1문단의 영역 태그
    HWPTAG_CTRL_HEADER가변1컨트롤 헤더
    HWPTAG_LIST_HEADER가변1문단 리스트 헤더
    HWPTAG_PAGE_DEF가변1용지 설정
    HWPTAG_FOOTNOTE_SHAPE가변1각주/미주 모양
    HWPTAG_PAGE_BORDER_FILL가변1쪽 테두리/배경
    HWPTAG_SHAPE_COMPONENT가변1개체
    HWPTAG_TABLE가변1표 개체
    HWPTAG_SHAPE_COMPONENT_LINE가변1직선 개체
    HWPTAG_SHAPE_COMPONENT_RECTANGLE가변1사각형 개체
    HWPTAG_SHAPE_COMPONENT_ELLIPSE가변1타원 개체
    HWPTAG_SHAPE_COMPONENT_ARC가변1호 개체
    HWPTAG_SHAPE_COMPONENT_POLYGON가변1다각형 개체
    HWPTAG_SHAPE_COMPONENT_CURVE가변1곡선 개체
    HWPTAG_SHAPE_COMPONENT_OLE가변1OLE 개체
    HWPTAG_SHAPE_COMPONENT_PICTURE가변1그림 개체
    HWPTAG_SHAPE_COMPONENT_CONTAINER가변1컨테이너 개체
    HWPTAG_CTRL_DATA가변1컨트롤 임의의 데이터
    HWPTAG_EQEDIT가변1수식 개체
    RESERVED가변1예약
    HWPTAG_SHAPE_COMPONENT_TEXTART가변1글맵시
    HWPTAG_FORM_OBJECT가변1양식 개체
    HWPTAG_MEMO_SHAPE가변1메모 모양
    HWPTAG_MEMO_LIST가변1메모 리스트 헤더
    HWPTAG_CHART_DATA가변1차트 데이터
    HWPTAG_VIDEO_DATA가변1비디오 데이터
    HWPTAG_SHAPE_COMPONENT_UNKNOWN361Unknown
    전체 길이가변

    문서 파일에서 문단 내용을 읽다가 제어 문자를 발견하면, 문서를 읽는 쪽에서는 제어 문자 종류에 따라 읽어 들이거나 건너 뛰어 다음 데이터의 시작 위치까지 파일 포인터를 옮기기 위한 적절한 처리를 수행해야 한다. 제어 문자 가운데는 또 다른 문단 리스트를 포함하는 경우도 있기 때문에, 제어 문자를 일반 문자처럼 처리하면 문서 파일을 정상적으로 읽을 수 없다.

    표, 각주 등과 같은 문단 리스트를 포함하는 컨트롤 문자들은 독자적인 문단 리스트를 가진다. 해당 리스트들은 아래와 같은 리스트 헤더 정보를 포함한다. 실제 문단들은 그 다음에 serialize 된다.

    문단 내에서 컨트롤은 세 가지 형식에 따라 다음과 같은 차이가 있다.

    문자 컨트롤

    부가정보 없이 문자 하나로 표현되는 제어 문자이다. (3번째 ch)

    01234567891011
    'A''B''C'ch'D''E''F''G''H''I''J'13

    인라인 컨트롤

    부가정보가 12 바이트(6 WCHAR) 이내에서 표현될 수 있는 제어 문자이다. info에 부가정보를 다 넣지 못하는 경우는 확장 컨트롤로 대체된다. (3~9까지 8개의 ch)

    01234567891011
    'A''B'chinfo (6바이트)infoinfoinfoinfoinfoch'C'13

    확장 컨트롤

    제어 문자는 포인터를 가지고 있고, 포인터가 가리키는 곳에 실제 오브젝트가 존재하는 제어 문자이다. (3~9까지 8개의 ch)

    01234567891011
    'A''B'chpointer (6바이트)pointerpointerpointerpointerpointerch'C'13

    ↓ (포인터가 가리키는 위치)

    Control Object Instance

    본 문서에 부가 설명 없이 '컨트롤' 또는 '제어 문자'라고 하면 바로 이 확장 컨트롤을 지칭하는 것이다.

    표 6: 제어 문자

    코드설명제어 문자 유형
    4필드 끝inline
    5-7예약inline
    8title markinline
    9탭inline
    10한 줄 끝(line break)char
    11그리기 개체/표extended
    12예약extended
    13문단 끝(para break)char
    14예약extended
    15숨은 설명extended
    16머리말/꼬리말extended
    17각주/미주extended
    18자동번호(각주, 표 등)extended
    19-20예약inline
    21페이지 컨트롤(감추기, 새 번호로 시작 등)extended
    22책갈피/찾아보기 표식extended
    23덧말/글자 겹침extended
    24하이픈char
    25-29예약char
    30묶음 빈칸char
    31고정폭 빈칸char
    #3.2.4. 문서 요약

    \005HwpSummaryInformation 스트림에는 한글 메뉴의 "파일 - 문서 정보 - 문서 요약"에서 입력한 내용이 저장된다.

    Summary Information에 대한 자세한 설명은 MSDN을 참고:

    • The Summary Information Property Set
    • The DocumentSummaryInformation and UserDefined Property Set

    표 7: 문서 요약

    NameProperty ID stringProperty IDVT type
    TitlePIDSI_TITLE0x00000002VT_LPSTR
    SubjectPIDSI_SUBJECT0x00000003VT_LPSTR
    AuthorPIDSI_AUTHOR0x00000004VT_LPSTR
    KeywordsPIDSI_KEYWORDS0x00000005VT_LPSTR
    CommentsPIDSI_COMMENTS0x00000006VT_LPSTR
    Last Saved ByPIDSI_LASTAUTHOR0x00000008VT_LPSTR
    Revision NumberPIDSI_REVNUMBER0x00000009VT_LPSTR
    Last PrintedPIDSI_LASTPRINTED0x0000000BVT_FILETIME (UTC)
    Create Time/DatePIDSI_CREATE_DTM0x0000000CVT_FILETIME (UTC)
    Last saved Time/DatePIDSI_LASTSAVE_DTM0x0000000DVT_FILETIME (UTC)
    Number of PagesPIDSI_PAGECOUNT0x0000000EVT_I4
    Date String(User define)HWPPIDSI_DATE_STR0x00000014VT_LPSTR
    Para Count(User define)HWPPIDSI_PARACOUNT0x00000015VT_I4
    #3.2.5. 바이너리 데이터

    BinData 스토리지에는 그림이나 OLE 개체와 같이 문서에 첨부된 바이너리 데이터가 각각의 스트림으로 저장된다.

    압축: 표 2에 따르면 BinData 스토리지의 스트림은 압축되어 저장됩니다. 실제 구현에서는 CFB에서 스트림을 읽은 후 압축 해제가 필요합니다.

    • 압축 형식: raw deflate (zlib의 deflate 알고리즘, windowBits: -15)
    • 압축 해제 방법: zlib의 decompress(..., -15) 또는 동등한 함수 사용
    • 레거시 구현 참고:
      • hwpjs.js: pako.inflate(data.content, { windowBits: -15 })
      • pyhwp: zlib.decompress(compressed_data, -15)

    ⚠️ 실제 구현 시 주의사항 (Implementation Notes)

    스펙 문서에는 BinData 스토리지 내 스트림의 정확한 경로 형식이 명시되어 있지 않습니다.

    실제 구현에서는 표 17의 HWPTAG_BIN_DATA 레코드를 사용하여 스트림을 찾습니다:

    1. EMBEDDING 타입: binary_data_id와 extension 정보를 사용
      • 스트림 이름: BIN{id:04X} (16진수 4자리, 대문자)
      • 시도하는 경로:
        • BinData/BIN{id:04X}, Root Entry/BinData/BIN{id:04X}, BIN{id:04X}
        • BinData/BIN{id:04X}.{extension}, Root Entry/BinData/BIN{id:04X}.{extension} (표 17의 extension 정보 사용)
    2. STORAGE 타입: binary_data_id만 사용 (extension 없음)
      • 스트림 이름: BIN{id:04X}
      • 시도하는 경로: BinData/BIN{id:04X}, Root Entry/BinData/BIN{id:04X}, BIN{id:04X}
    3. LINK 타입: BinData 스토리지에 저장되지 않으므로 건너뜀

    표 17의 extension 필드는 EMBEDDING 타입일 때 바이너리 데이터의 형식 정보를 제공하며, 이를 활용하여 스트림 경로를 구성할 수 있습니다.

    압축 해제: CFB에서 스트림을 읽은 후, raw deflate 형식으로 압축 해제해야 합니다. 압축 해제 실패 시 원본 데이터를 사용하거나 에러를 처리해야 합니다.

    #3.2.6. 미리보기 텍스트

    PrvText 스트림에는 미리보기 텍스트가 유니코드 문자열로 저장된다.

    #3.2.7. 미리보기 이미지

    PrvImage 스트림에는 미리보기 이미지가 BMP 또는 GIF 형식으로 저장된다.

    #3.2.8. 문서 옵션

    DocOptions 스토리지에는 연결 문서, 배포용 문서, 공인인증서 DRM, 전자 서명 관련 정보가 각각의 스트림으로 저장된다.

    • _LinkDoc 스트림: 연결된 문서의 경로가 저장된다.
    • DrmLicense 스트림: DRM Packaging의 Version 정의가 저장된다.
    • DrmRootSect 스트림: 암호화 알고리즘이 저장된다.
    • CertDrmHeader 스트림: DRM Packaging의 Version 정의가 저장된다.
    • CertDrmInfo 스트림: 공인인증서 DRM 정보가 저장된다.
    • DigitalSignature 스트림: 전자 서명 정보가 저장된다.
    • PublicKeyInfo 스트림: 공개 키 정보가 저장된다.
    #3.2.9. 스크립트

    Scripts 스토리지에는 Script 코드를 저장한다.

    JScriptVersion 스트림에는 Script Version이 저장된다.

    표 8: 스크립트 버전

    자료형길이(바이트)설명
    DWORD4스크립트 버전 HIGH
    DWORD4스크립트 버전 LOW
    전체 길이8

    DefaultJScript 스트림에는 Script 헤더, 소스, Pre 소스, Post 소스가 저장된다.

    표 9: 스크립트

    자료형길이(바이트)설명
    DWORD4스크립트 헤더 길이 (len1)
    WCHAR array[len1]2×len1스크립트 헤더
    DWORD4스크립트 소스 길이 (len2)
    WCHAR array[len2]2×len2스크립트 소스
    DWORD4스크립트 Pre 소스 길이 (len3)
    WCHAR array[len3]2×len3스크립트 Pre 소스
    DWORD4스크립트 Post 소스 길이 (len4)
    WCHAR array[len4]2×len4스크립트 Post 소스
    DWORD4스크립트 end flag (-1)
    전체 길이20 + (2×len1) + (2×len2) + (2×len3) + (2×len4)
    #3.2.10. XML 템플릿

    XMLTemplate 스토리지에는 XML Template 정보를 저장한다.

    _SchemaName 스트림에는 Schema 이름 문자열이 저장된다.

    표 10: Schema 이름 정보

    자료형길이(바이트)설명
    DWORD4Schema 이름 길이 (len1)
    WCHAR array[len1]2×len1Schema 이름
    전체 길이4 + (2×len1)

    Schema 스트림에는 Schema 문자열이 저장된다.

    표 11: Schema 길이 정보

    자료형길이(바이트)설명
    DWORD4Schema 길이 (len1)
    WCHAR array[len1]2×len1Schema
    전체 길이4 + (2×len1)

    Instance 스트림에는 Instance 문자열이 저장된다.

    표 12: Instance 정보

    자료형길이(바이트)설명
    DWORD4Instance 길이 (len1)
    WCHAR array[len1]2×len1Instance
    전체 길이4 + (2×len1)
    #3.2.11. 문서 이력 관리

    한글 메뉴의 "파일 - 문서 이력 관리"에서 표시 및 생성되는 문서의 이력 정보를 저장하는 장소이다.

    문서 이력 정보의 각각의 아이템은 "히스토리" 혹은 "히스토리 아이템"이라 하며 한글 Compound 구조 내에서 각 아이템은 "DocHistory"라는 스토리지 내부에 VersionLog%d(%d는 버전) 이름의 스트림으로 저장된다. 또한, 각각 아이템은 압축, 암호화되어 저장된다.

    이력 정보 데이터를 "DocHistory"라는 새로운 스토리지로 저장한다. DocHistory 스토리지에 이력 정보 아이템은 추후 추가 정보가 저장되었을 때 하위 호환성을 위하여 다음의 구조로 저장한다.

    버전 정보 스토리지 구조:

    DocHistory : 스토리지
    ├── VersionLog0 : 이력 정보 스트림
    ├── VersionLog1 : 이력 정보 스트림
    ├── VersionLog2 : 이력 정보 스트림
    ├── ...
    └── HistoryLastDoc : 최종문서 스트림

    히스토리 아이템 스트림 구조:

    히스토리 아이템
    ├── 아이템 시작 레코드
    ├── 히스토리 정보 레코드 1
    ├── 히스토리 정보 레코드 2
    ├── 히스토리 정보 레코드 3
    ├── ...
    ├── (사용자, 시간, 날짜 등...)
    ├── 이력 정보 데이터 레코드
    └── 아이템 끝 레코드

    레코드 구성:

    RECORD_HEADER

    자료형설명
    BYTE레코드 Type
    UINT추가 데이터 블록 (RD) BYTE 크기

    RECORD_DATA (RD)

    자료형설명
    DATA레코드 Type에 따른 다양한 정보 (스트링, Bit flag 등)
    #3.2.12. 참고문헌

    Bibliography 스토리지에는 참고문헌 정보가 .XML 파일 형태로 저장한다.

    #4. 데이터 레코드

    #4.1. 데이터 레코드 구조

    데이터 레코드는 논리적으로 관련된 데이터를 헤더 정보와 함께 저장하는 방법이다. 레코드 구조를 가진 스트림은 여러 개의 연속된 레코드로 구성된다.

    데이터 레코드는 헤더와 데이터로 구성되며, 헤더 정보를 이용하여 전체적인 논리 구조를 만들 수 있다. 레코드 헤더에는 데이터 확장을 위한 정보가 포함되어 있어, 한글 문서의 이전 버전에서도 데이터가 추가된 레코드를 읽을 수 있도록 하여 하위 호환성을 보장한다.

    그림 45: 레코드 구조

    레코드
    ├── 헤더 (DWORD)
    │   ├── Tag ID (bits 0-9)
    │   ├── Level (bits 10-19)
    │   └── Size (bits 20-31)
    └── 데이터

    레코드 헤더의 크기는 32bits이고 TagID(10bits), Level(10bits), Size(12bits)로 구성된다.

    Tag ID:

    • 레코드가 나타내는 데이터의 종류를 나타낸다.
    • 10비트를 사용하므로 0x000부터 0x3FF까지의 값을 가질 수 있다.
    • 0x000 - 0x00F: 특수 목적으로 사용되며, 일반적인 레코드 태그로 사용되지 않는다.
    • 0x010 - 0x1FF: 한글 내부 사용을 위해 예약되어 있다 (HWPTAG_BEGIN = 0x010).
    • 0x200 - 0x3FF: 외부 응용 프로그램이 사용할 수 있는 영역이다.

    Level:

    • 대부분의 객체는 여러 개의 레코드로 구성되므로, "논리적으로 관련된 연속된 레코드"라는 개념이 필요하다.
    • Level은 이러한 논리적 그룹핑을 나타내는 정보를 제공한다.
    • 스트림을 구성하는 모든 레코드는 계층 구조로 표현할 수 있으며, Level은 이 계층 구조에서의 깊이를 나타낸다.

    Size:

    • 데이터 영역의 길이를 바이트 단위로 나타낸다.
    • 12비트가 모두 1인 경우(즉, 0xFFF)는 데이터 영역의 길이가 4095바이트 이상임을 나타낸다.
    • 이 경우(데이터가 4095바이트를 초과하는 경우) 레코드 헤더 바로 다음에 길이를 나타내는 DWORD가 추가된다.

    그림 46: 확장 데이터 레코드 구조

    레코드
    ├── 헤더 (DWORD)
    ├── 길이 (DWORD)
    └── 데이터

    #4.2. '문서 정보'의 데이터 레코드

    '문서 정보('DocInfo')'에서 사용되는 데이터 레코드는 다음과 같다.

    표 13: 문서 정보의 데이터 레코드

    Tag IDValue의미
    HWPTAG_DOCUMENT_PROPERTIESHWPTAG_BEGIN문서 속성
    HWPTAG_ID_MAPPINGSHWPTAG_BEGIN+1아이디 매핑 헤더
    HWPTAG_BIN_DATAHWPTAG_BEGIN+2BinData
    HWPTAG_FACE_NAMEHWPTAG_BEGIN+3Typeface Name
    HWPTAG_BORDER_FILLHWPTAG_BEGIN+4테두리/배경
    HWPTAG_CHAR_SHAPEHWPTAG_BEGIN+5글자 모양
    HWPTAG_TAB_DEFHWPTAG_BEGIN+6탭 정의
    HWPTAG_NUMBERINGHWPTAG_BEGIN+7번호 정의
    HWPTAG_BULLETHWPTAG_BEGIN+8불릿 정의
    HWPTAG_PARA_SHAPEHWPTAG_BEGIN+9문단 모양
    HWPTAG_STYLEHWPTAG_BEGIN+10스타일
    HWPTAG_DOC_DATAHWPTAG_BEGIN+11문서의 임의의 데이터
    HWPTAG_DISTRIBUTE_DOC_DATAHWPTAG_BEGIN+12배포용 문서 데이터
    RESERVEDHWPTAG_BEGIN+13예약
    HWPTAG_COMPATIBLE_DOCUMENTHWPTAG_BEGIN+14호환 문서
    HWPTAG_LAYOUT_COMPATIBILITYHWPTAG_BEGIN+15레이아웃 호환성
    HWPTAG_TRACKCHANGEHWPTAG_BEGIN+16변경 추적 정보
    HWPTAG_MEMO_SHAPEHWPTAG_BEGIN+76메모 모양
    HWPTAG_FORBIDDEN_CHARHWPTAG_BEGIN+78금칙처리 문자
    HWPTAG_TRACK_CHANGEHWPTAG_BEGIN+80변경 추적 내용 및 모양
    HWPTAG_TRACK_CHANGE_AUTHORHWPTAG_BEGIN+81변경 추적 작성자
    #4.2.1. 문서 속성

    Tag ID: HWPTAG_DOCUMENT_PROPERTIES

    표 14: 문서 속성

    자료형길이(바이트)설명
    UINT162구역 개수
    UINT162문서 내 각종 시작번호에 대한 정보
    UINT162페이지 시작 번호
    UINT162각주 시작 번호
    UINT162미주 시작 번호
    UINT162그림 시작 번호
    UINT162표 시작 번호
    UINT162수식 시작 번호
    UINT324문서 내 캐럿의 위치 정보
    UINT324리스트 아이디
    UINT324문단 아이디
    UINT324문단 내에서의 글자 단위 위치
    전체 길이26

    ⚠️ 실제 구현 시 주의사항 (Implementation Notes)

    첫 번째 UINT32 필드인 **"문서 내 캐럿의 위치 정보"**는 실제로 존재하지 않습니다.

    #4.2.2. 아이디 매핑 헤더

    Tag ID: HWPTAG_ID_MAPPINGS

    표 15: 아이디 매핑 헤더

    자료형길이(바이트)설명
    INT32 array[18]72아이디 매핑 개수(표 16 참조)
    전체 길이72doc version에 따라 가변적

    표 16: 아이디 매핑 개수 인덱스

    값설명
    0바이너리 데이터
    1한글 글꼴
    2영어 글꼴
    3한자 글꼴
    4일어 글꼴
    5기타 글꼴
    6기호 글꼴
    7사용자 글꼴
    8테두리/배경
    9글자 모양
    10탭 정의
    11문단 번호
    12글머리표
    13문단 모양
    14스타일
    15메모 모양 (5.0.2.1 이상)
    16변경추적 (5.0.3.2 이상)
    17변경추적 사용자 (5.0.3.2 이상)
    #4.2.3. 바이너리 데이터

    Tag ID: HWPTAG_BIN_DATA

    표 17: 바이너리 데이터

    자료형길이(바이트)설명
    그림, OLE 등의 바이너리 데이터 아이템에 대한 정보
    UINT162속성(표 18 참조)
    WORD2Type이 "LINK"일 때, 연결 파일의 절대 경로 길이 (len1)
    WCHAR array[len1]2×len1Type이 "LINK"일 때, 연결 파일의 절대 경로
    WORD2Type이 "LINK"일 때, 연결 파일의 상대 경로 길이 (len2)
    WCHAR array[len2]2×len2Type이 "LINK"일 때, 연결 파일의 상대 경로
    UINT162Type이 "EMBEDDING"이거나 "STORAGE"일 때, BINDATASTORAGE에 저장된 바이너리 데이터의 아이디
    WORD2Type이 "EMBEDDING"일 때, 바이너리 데이터의 형식 이름의 길이 (len3)
    WCHAR array[len3]2×len3Type이 "EMBEDDING"일 때 extension("." 제외)
    - 그림의 경우: jpg, bmp, gif
    - OLE의 경우: ole
    전체 길이가변10 + (2×len1) + (2×len2) + (2×len3) 바이트

    표 18: 바이너리 데이터 속성

    범위구분값설명
    bit 0-3Type0x0000LINK, 그림 외부 파일 참조
    0x0001EMBEDDING, 그림 파일 포함
    0x0002STORAGE, OLE 포함
    bit 4-5압축0x0000스토리지의 디폴트 모드 따라감
    0x0010무조건 압축
    0x0020무조건 압축하지 않음
    bit 8-9상태0x0000아직 access 된 적이 없는 상태
    0x0100access에 성공하여 파일을 찾은 상태
    0x0200access가 실패한 에러 상태
    0x0300링크 access가 실패했으나 무시된 상태
    #4.2.4. 글꼴

    Tag ID: HWPTAG_FACE_NAME

    표 19: 글꼴

    자료형길이(바이트)설명
    BYTE1속성(표 20 참조)
    WORD2글꼴 이름 길이(len1)
    WCHAR array[len1]2×len1글꼴 이름
    BYTE1대체 글꼴 유형(표 21 참조)
    WORD2대체 글꼴 이름 길이(len2)
    WCHAR array[len2]2×len2대체 글꼴 이름
    BYTE array[10]10글꼴 유형 정보(표 22 참조)
    WORD2기본 글꼴 이름 길이(len3)
    WCHAR array[len3]2×len3기본 글꼴 이름
    전체 길이가변18 + (2×len1) + (2×len2) + (2×len3) 바이트

    표 20: 글꼴 속성

    값설명
    0x80대체 글꼴 존재 여부
    0x40글꼴 유형 정보 존재 여부
    0x20기본 글꼴 존재 여부

    표 21: 대체 글꼴 유형

    값설명
    0원래 종류를 알 수 없을 때
    1트루타입 글꼴(TTF)
    2한글 전용 글꼴(HFT)

    표 22: 글꼴 유형 정보

    자료형길이(바이트)설명
    BYTE1글꼴 계열
    BYTE1세리프 유형
    BYTE1굵기
    BYTE1비례
    BYTE1대조
    BYTE1스트로크 편차
    BYTE1자획 유형
    BYTE1글자형
    BYTE1중간선
    BYTE1X-높이
    #4.2.5. 테두리/배경

    Tag ID: HWPTAG_BORDER_FILL

    표 23: 테두리/배경 속성

    자료형길이(바이트)설명
    UINT162속성(표 24 참조)
    UINT8 array[4]44방향 테두리선 종류(표 25 참조)
    UINT8 array[4]44방향 테두리선 굵기(표 26 참조)
    COLORREF array[4]164방향 테두리선 색상
    UINT81대각선 종류(표 27 참조)
    UINT81대각선 굵기
    COLORREF4대각선 색깔
    BYTE streamn채우기 정보(표 28 참조)
    전체 길이가변32+n 바이트

    표 24: 테두리/배경 속성

    범위설명
    bit 03D 효과의 유무
    bit 1그림자 효과의 유무
    bit 2-4Slash 대각선 모양(시계 방향으로 각각의 대각선 유무를 나타냄)
    - 000: none
    - 010: slash
    - 011: LeftTop --> Bottom Edge
    - 110: LeftTop --> Right Edge
    - 111: LeftTop --> Bottom & Right Edge
    bit 5-7BackSlash 대각선 모양(반시계 방향으로 각각의 대각선 유무를 나타냄)
    - 000: none
    - 010: / back slash
    - 011: RightTop --> Bottom Edge
    - 110: RightTop --> Left Edge
    - 111: RightTop --> Bottom & Left Edge
    bit 8-9Slash 대각선 꺽은선
    bit 10BackSlash 대각선 꺽은선
    bit 11Slash 대각선 모양 180도 회전 여부
    bit 12BackSlash 대각선 모양 180도 회전 여부
    bit 13중심선 유무

    표 25: 테두리선 종류

    값설명
    0실선
    1긴 점선
    2점선
    3----
    4----
    5Dash보다 긴 선분의 반복
    6Dot보다 큰 동그라미의 반복
    72중선
    8가는선 + 굵은선 2중선
    9굵은선 + 가는선 2중선
    10가는선 + 굵은선 + 가는선 3중선
    11물결
    12물결 2중선
    13두꺼운 3D
    14두꺼운 3D(광원 반대)
    153D 단선
    163D 단선(광원 반대)

    표 26: 테두리선 굵기

    값설명값설명
    00.1 mm80.6 mm
    10.12 mm90.7 mm
    20.15 mm101.0 mm
    30.2 mm111.5 mm
    40.25 mm122.0 mm
    50.3 mm133.0 mm
    60.4 mm144.0 mm
    70.5 mm155.0 mm

    표 27: 대각선 종류

    값설명
    0Slash
    1BackSlash
    2CrookedSlash

    표 28: 채우기 정보

    자료형길이(바이트)설명
    채우기 종류(type)
    UINT4채우기 종류(type)
    - 0x00000000: 채우기 없음
    - 0x00000001: 단색 채우기
    - 0x00000002: 이미지 채우기
    - 0x00000004: 그러데이션 채우기
    단색 채우기 (type & 0x0000001 != 0)
    COLORREF4배경색
    COLORREF4무늬색
    INT324무늬 종류(표 29 참조)
    그러데이션 채우기 (type & 0x0000004 != 0)
    INT162그러데이션 유형(표 30 참조)
    INT162그러데이션의 기울임(시작 각)
    INT162그러데이션의 가로 중심(중심 X 좌표)
    INT162그러데이션의 세로 중심(중심 Y 좌표)
    INT162그러데이션 번짐 정도(0-100)
    INT162그러데이션의 색 수(num). (워디안/훈글2002/SE에서는 항상 2이다.)
    INT324×num색상이 바뀌는 곳의 위치. (num > 2일 경우에만)
    COLORREF array[num]4×num색상
    이미지 채우기 (type & 0x0000002 != 0)
    BYTE1이미지 채우기 유형(표 31 참조)
    BYTE stream5그림 정보(표 32 참조)
    DWORD4type의 0x0004비트가 켜져 있으면 size(=추가적인 그라데이션 바이트) = 1, 아니면 size = 0
    BYTE1그러데이션 번짐정도의 중심 (0..100)
    DWORD4추가 채우기 속성 길이(size)
    BYTEsize추가 채우기 속성 - 그러데이션일 경우(type & 0x0000001 != 0) 번짐 정도의 중심(0-100): 1byte
    전체 길이가변8 + n 바이트

    표 29: 채우기 무늬 종류

    값설명
    1-----
    2|||||
    3\\\
    4/////
    5+++++
    6xxxxx

    표 30: 그러데이션 유형

    값설명
    1줄무늬형
    2원형
    3원뿔형
    4사각형

    표 31: 이미지 채우기 유형

    값설명
    0바둑판식으로-모두
    1바둑판식으로-가로/위
    2바둑판식으로-가로/아래
    3바둑판식으로-세로/왼쪽
    4바둑판식으로-세로/오른쪽
    5크기에 맞추어
    6가운데로
    7가운데 위로
    8가운데 아래로
    9왼쪽 가운데로
    10왼쪽 위로
    11왼쪽 아래로
    12오른쪽 가운데로
    13오른쪽 위로
    14오른쪽 아래로
    15NONE

    표 32: 그림 정보

    자료형길이(바이트)설명
    INT81밝기
    INT81명암
    BYTE1그림 효과
    - 0: REAL_PIC
    - 1: GRAY_SCALE
    - 2: BLACK_WHITE
    - 4: PATTERN8x8
    UINT162BinItem의 아이디 참조값
    전체 길이5
    #4.2.6. 글자 모양

    Tag ID: HWPTAG_CHAR_SHAPE

    표 33: 글자 모양

    자료형길이(바이트)설명
    WORD array[7]14언어별 글꼴 ID(FaceID) 참조 값(표 34 참조)
    UINT8 array[7]7언어별 장평, 50%~200%(표 34 참조)
    INT8 array[7]7언어별 자간, -50%~50%(표 34 참조)
    UINT8 array[7]7언어별 상대 크기, 10%~250%(표 34 참조)
    INT8 array[7]7언어별 글자 위치, -100%~100%(표 34 참조)
    INT324기준 크기, 0pt~4096pt
    UINT324속성(표 35 참조)
    INT81그림자 간격, -100%~100%
    INT81그림자 간격, -100%~100%
    COLORREF4글자 색
    COLORREF4밑줄 색
    COLORREF4음영 색
    COLORREF4그림자 색
    UINT162글자 테두리/배경 ID(CharShapeBorderFill ID) 참조 값 (5.0.2.1 이상)
    COLORREF4취소선 색 (5.0.3.0 이상)
    전체 길이72

    표 34: 글꼴에 대한 언어

    값설명
    0한글
    1영어
    2한자
    3일어
    4기타
    5기호
    6사용자

    표 35: 글자 모양 속성

    범위구분값설명
    bit 0기울임 여부
    bit 1진하게 여부
    bit 2-3밑줄 종류0없음
    1글자 아래
    2글자 위
    bit 4-7밑줄 모양0없음
    1실선
    2점선
    3굵은 실선(두꺼운 선)
    4파선(긴 점선)
    5일점쇄선 (-.-.-.-.)
    6이점쇄선 (-..-..-..)
    bit 8-10외곽선 종류0없음
    1비연속
    2연속
    bit 11-12그림자 종류
    bit 13양각 여부
    bit 14음각 여부
    bit 15위 첨자 여부
    bit 16아래 첨자 여부
    bit 17Reserved
    bit 18-20취소선 여부0없음
    1검정 동그라미 강조점
    2속빈 동그라미 강조점
    bit 21-24강조점 종류3-
    4-
    5-
    6-
    bit 25글꼴에 어울리는 빈칸 사용 여부
    bit 26-29취소선 모양(표 25 참조)
    bit 30Kerning 여부
    #4.2.7. 탭 정의

    Tag ID: HWPTAG_TAB_DEF

    표 36: 탭 정의

    자료형길이(바이트)설명
    UINT324속성
    INT162count
    HPWUNIT4탭의 위치
    UINT81탭의 종류
    - 0: 왼쪽
    - 1: 오른쪽
    - 2: 가운데
    - 3: 소수점
    UINT81채움 종류(표 25 참조)
    UINT1628 바이트를 맞추기 위한 예약
    전체 길이가변8+(8×count)

    표 37: 탭 정의 속성

    범위설명
    bit 0문단 왼쪽 끝 자동 탭(내어 쓰기용 자동 탭) 유무
    bit 1문단 오른쪽 끝 자동 탭 유무
    #4.2.8. 문단 번호

    Tag ID: HWPTAG_NUMBERING

    표 38: 문단 번호

    자료형길이(바이트)설명
    UINT4속성(표 40 참조)
    HWPUNIT162너비 보정값
    HWPUNIT162본문과의 거리
    UINT4글자 모양 아이디 참조
    전체 길이8

    참고: 표 38은 각 수준(1~7)의 기본 정보를 나타냅니다. 실제 바이너리 구조에서는 표 38의 8바이트 구조와 표 39의 가변 데이터가 각 수준마다 연속적으로 배치됩니다.

    표 39: 문단 머리 정보

    자료형길이(바이트)설명
    BYTE8문단 머리 정보(표 40 참조)
    stream번호 형식 길이 (len)
    WORD2번호 형식. 불릿 문단의 경우 제어 코드 ^와 수준 경로(예: 1,1,1,1,1,1,1)를 포함. 7회 반복, 수준(1~7). (표 36 참조)
    WCHAR array[len]2×len각 레벨에 해당하는 숫자 또는 문자 또는 기호를 표시
    UINT162시작 번호
    UINT4수준별 시작번호 (5.0.2.5 이상). 7회 반복, 수준(1~7)
    WORD2확장 번호 형식 길이 (len). 3회 반복
    WCHAR array[len]2×len확장 번호 형식. 불릿 문단의 경우 제어 코드 ^와 수준 경로(예: 1,1,1,1,1,1,1)를 포함. 수준(8~10). 각 레벨에 해당하는 숫자 또는 문자 또는 기호를 표시

    실제 바이너리 구조 / Actual Binary Structure

    표 38과 표 39는 구조를 설명하기 위해 분리되어 있지만, 실제 HWP 파일에서는 각 수준(1~7)마다 다음 구조가 연속적으로 반복됩니다:

    각 수준(1~7)마다 반복:

    1. 표 38 구조 (8바이트):
      • UINT 속성 (4바이트)
      • HWPUNIT16 너비 보정값 (2바이트)
      • HWPUNIT16 본문과의 거리 (2바이트)
      • UINT 글자 모양 아이디 참조 (4바이트)
    2. 표 39 가변 데이터:
      • WORD 번호 형식 길이 (len) (2바이트)
      • WCHAR array[len] 번호 형식 문자열 (2×len 바이트, UTF-16LE)
      • UINT16 시작 번호 (2바이트)
      • UINT 수준별 시작번호 (4바이트, 5.0.2.5 이상, 옵션)

    확장 번호 형식 (수준 8~10, 3회 반복):

    • WORD 확장 번호 형식 길이 (len) (2바이트)
    • WCHAR array[len] 확장 번호 형식 문자열 (2×len 바이트, UTF-16LE)

    표 40: 문단 머리 정보 속성

    범위구분값설명
    bit 0-1문단의 정렬 종류0왼쪽
    1가운데
    2오른쪽
    bit 20false
    1true
    bit 3자동 내어 쓰기 여부0false
    1true
    bit 4수준별 본문과의 거리 종류0글자 크기에 대한 상대 비율
    1값

    표 41: 문단 번호 형식

    값설명
    01, 2, 3
    1동그라미 쳐진 1, 2, 3
    2I, II, III
    3i, ii, iii
    4A, B, C
    5a, b, c
    6동그라미 쳐진 A, B, C
    7동그라미 쳐진 a, b, c
    8가, 나, 다
    9동그라미 쳐진 가, 나, 다
    10ㄱ, ㄴ, ㄷ
    11동그라미 쳐진 ㄱ, ㄴ, ㄷ
    12일, 이, 삼
    13-, =, ≡
    14동그라미 쳐진 -, =, ≡
    #4.2.9. 글머리표

    Tag ID: HWPTAG_BULLET

    표 42: 글머리표

    자료형길이(바이트)설명
    BYTE stream8문단 머리 정보(표 40 참조)
    WCHAR2글머리표 문자
    INT324이미지 글머리표 존재 여부(ID)
    BYTE stream4이미지 글머리표 속성(명암, 밝기, 효과, ID)
    WCHAR2체크 글머리표 문자
    전체 길이20
    #4.2.10. 문단 모양

    Tag ID: HWPTAG_PARA_SHAPE

    표 43: 문단 모양

    자료형길이(바이트)설명
    UINT324속성1(표 44 참조)
    INT324왼쪽 여백
    INT324오른쪽 여백
    INT324들여쓰기
    INT324내어쓰기
    INT324문단 위 간격
    INT324문단 아래 간격
    INT324줄 간격(한글 2007 이하 버전, 표 46 참조)
    UINT162탭 정의 ID 참조 값
    UINT162번호/글머리표 ID 참조 값
    UINT162테두리/배경 ID 참조 값
    INT162문단 테두리 간격(왼쪽)
    INT162문단 테두리 간격(오른쪽)
    INT162문단 테두리 간격(위)
    INT162문단 테두리 간격(아래)
    UINT324속성2(표 45 참조, 5.0.1.7 이상)
    UINT324속성3(표 46 참조, 5.0.2.5 이상)
    INT324줄 간격(5.0.2.5 이상, 표 46 참조)
    전체 길이54

    표 44: 문단 모양 속성1

    범위설명
    bit 0-1줄 간격 종류(한글 2007 이하 버전)
    - 0: 글자에 따라(%)
    - 1: 고정값
    - 2: 여백만 지정
    bit 2-4정렬 방법
    - 0: 양쪽 정렬
    - 1: 왼쪽
    - 2: 오른쪽
    - 3: 가운데
    - 4: 배분
    - 5: 나눔
    bit 5-6줄 나눔 기준 영문 단위
    - 0: 단어
    - 1: 하이픈
    - 2: 글자
    bit 7줄 나눔 기준 한글 단위
    - 0: 단어 단위
    - 1: 글자
    bit 8편집 용지의 줄 격자 사용 여부
    bit 9-15최소 공백 값(0%~75%)
    bit 16외톨이 줄 보호
    bit 17다음 문단과 함께
    bit 18문단 보호
    bit 19문단 앞에서 항상 쪽 나눔
    bit 20-21세로 정렬
    - 0: 글꼴 기준선
    - 1: 위
    - 2: 가운데
    - 3: 아래
    bit 22글꼴에 맞는 줄 높이
    bit 23-24문단 머리 모양 종류
    - 0: 없음
    - 1: 개요
    - 2: 번호
    - 3: 글머리표
    bit 25-27문단 수준(1~7)
    bit 28문단 테두리 연결
    bit 29문단 여백 무시
    bit 30문단 꼬리 모양

    표 45: 문단 모양 속성2

    범위설명
    bit 0-1한 줄 입력
    bit 2-3예약
    bit 4한글과 영문 사이 자동 간격 조정
    bit 5한글과 숫자 사이 자동 간격 조정

    표 46: 줄 간격 종류

    한글 2007 이하 버전:

    • bit 0-1: 줄 간격 종류
      • 0: 글자에 따라(%)
      • 1: 고정값
      • 2: 여백만 지정

    5.0.2.5 버전 이상:

    • bit 0-4: 줄 간격 종류
      • 0: 글자에 따라
      • 1: 고정값
      • 2: 여백만 지정
      • 3: 최소값
    #4.2.11. 스타일(문단 스타일)

    Tag ID: HWPTAG_STYLE

    표 47: 스타일

    자료형길이(바이트)설명
    WORD2길이(len1)
    WCHAR array[len1]2×len1로컬/한글 스타일 이름
    WORD2길이(len2)
    WCHAR array[len2]2×len2영문 스타일 이름
    BYTE1속성(표 43 참조)
    BYTE1다음 스타일 ID 참조 값
    INT162언어 ID(표 48 참조)
    UINT162문단 모양 ID 참조 값(스타일 종류가 문단인 경우 필수)
    UINT162글자 모양 ID(스타일 종류가 글자인 경우 필수)
    전체 길이가변12 + (2×len1) + (2×len2) 바이트

    표 48: 스타일 종류

    범위구분값설명
    bit 0-2스타일 종류0문단 스타일
    1글자 스타일
    #4.2.12. 문서 임의의 데이터

    라벨 문서인지 여부나 인쇄 대화상자의 정보를 저장한다.

    Tag ID: HWPTAG_DOC_DATA

    표 49: 문서 임의의 데이터

    자료형길이(바이트)설명
    Parameter Set가변파라미터 셋(표 50 참조)
    전체 길이가변

    파라미터 아이템의 개수만큼 아이템 데이터를 얻는다.

    표 50: 파라미터 셋

    자료형길이(바이트)설명
    WORD2파라미터 셋 ID
    INT162파라미터 셋에 존재하는 아이템 개수(n)
    Parameter Item가변×n파라미터 아이템(표 51 참조)
    전체 길이가변4 + (가변×n) 바이트

    표 51: 파라미터 아이템

    자료형길이(바이트)설명
    WORD2파라미터 아이템 ID
    WORD2파라미터 아이템 종류(표 52 참조)
    Parameter Item Type가변파라미터 아이템 데이터
    전체 길이가변4 + 가변 바이트

    표 52: 파라미터 아이템 종류

    값구분자료형설명
    0PIT_NULLUINTNULL
    1PIT_BSTRWORD문자열 길이(slen)
    WCHAR array[len]문자열
    2PIT_I1UINTINT8
    3PIT_I2UINTINT16
    4PIT_I4UINTINT32
    5PIT_IUINTINT
    6PIT_UI1UINTUINT8
    7PIT_UI2UINTUINT16
    8PIT_UI4UINTUINT32
    9PIT_UIUINTUINT
    0x8000PIT_SETParameter Set파라미터 셋
    INT16파라미터 셋 개수
    0x8001PIT_ARRAYParameterArray파라미터 셋 배열
    0x8002PIT_BINDATAUINT16바이너리 데이터 ID
    #4.2.13. 배포용 문서 데이터

    배포용 문서에서는 모든 스트림에 배포용 문서 데이터가 들어간다.

    Tag ID: HWPTAG_DISTRIBUTE_DOC_DATA

    표 53: 배포용 문서 데이터

    자료형길이(바이트)설명
    BYTE array[256]256배포용 문서 데이터
    전체 길이256
    #4.2.14. 호환 문서

    Tag ID: HWPTAG_COMPATIBLE_DOCUMENT

    표 54: 호환 문서

    자료형길이(바이트)설명
    UINT324대상 프로그램(표 55 참조)
    전체 길이4

    표 55: 대상 프로그램

    값설명
    0한글 문서(현재 버전)
    1한글 2007 호환 문서
    2MS 워드 호환 문서
    #4.2.15. 레이아웃 호환성

    Tag ID: HWPTAG_LAYOUT_COMPATIBILITY

    표 56: 레이아웃 호환성

    자료형길이(바이트)설명
    UINT324글자 단위 서식
    UINT324문단 단위 서식
    UINT324구역 단위 서식
    UINT324개체 단위 서식
    UINT324필드 단위 서식
    전체 길이20

    #4.3. '본문'의 데이터 레코드

    본문에서 사용되는 데이터 레코드는 다음과 같다.

    표 57: 본문의 데이터 레코드

    Tag IDValue설명
    HWPTAG_PARA_HEADERHWPTAG_BEGIN+50문단 헤더
    HWPTAG_PARA_TEXTHWPTAG_BEGIN+51문단의 텍스트
    HWPTAG_PARA_CHAR_SHAPEHWPTAG_BEGIN+52문단의 글자 모양
    HWPTAG_PARA_LINE_SEGHWPTAG_BEGIN+53문단의 레이아웃
    HWPTAG_PARA_RANGE_TAGHWPTAG_BEGIN+54문단의 영역 태그
    HWPTAG_CTRL_HEADERHWPTAG_BEGIN+55컨트롤 헤더
    HWPTAG_LIST_HEADERHWPTAG_BEGIN+56문단 리스트 헤더
    HWPTAG_PAGE_DEFHWPTAG_BEGIN+57용지 설정
    HWPTAG_FOOTNOTE_SHAPEHWPTAG_BEGIN+58각주/미주 모양
    HWPTAG_PAGE_BORDER_FILLHWPTAG_BEGIN+59쪽 테두리/배경
    HWPTAG_SHAPE_COMPONENTHWPTAG_BEGIN+60개체
    HWPTAG_TABLEHWPTAG_BEGIN+61표 개체
    HWPTAG_SHAPE_COMPONENT_LINEHWPTAG_BEGIN+62직선 개체
    HWPTAG_SHAPE_COMPONENT_RECTANGLEHWPTAG_BEGIN+63사각형 개체
    HWPTAG_SHAPE_COMPONENT_ELLIPSEHWPTAG_BEGIN+64타원 개체
    HWPTAG_SHAPE_COMPONENT_ARCHWPTAG_BEGIN+65호 개체
    HWPTAG_SHAPE_COMPONENT_POLYGONHWPTAG_BEGIN+66다각형 개체
    HWPTAG_SHAPE_COMPONENT_CURVEHWPTAG_BEGIN+67곡선 개체
    HWPTAG_SHAPE_COMPONENT_OLEHWPTAG_BEGIN+68OLE 개체
    HWPTAG_SHAPE_COMPONENT_PICTUREHWPTAG_BEGIN+69그림 개체
    HWPTAG_SHAPE_COMPONENT_CONTAINERHWPTAG_BEGIN+70컨테이너 개체
    HWPTAG_CTRL_DATAHWPTAG_BEGIN+71컨트롤 임의의 데이터
    HWPTAG_EQEDITHWPTAG_BEGIN+72수식 개체
    RESERVEDHWPTAG_BEGIN+73예약
    HWPTAG_SHAPE_COMPONENT_TEXTARTHWPTAG_BEGIN+74글맵시
    HWPTAG_FORM_OBJECTHWPTAG_BEGIN+75양식 개체
    HWPTAG_MEMO_SHAPEHWPTAG_BEGIN+76메모 모양
    HWPTAG_MEMO_LISTHWPTAG_BEGIN+77메모 리스트 헤더
    HWPTAG_CHART_DATAHWPTAG_BEGIN+79차트 데이터
    HWPTAG_VIDEO_DATAHWPTAG_BEGIN+82비디오 데이터
    HWPTAG_SHAPE_COMPONENT_UNKNOWNHWPTAG_BEGIN+99Unknown
    #4.3.1. 문단 헤더

    Tag ID: HWPTAG_PARA_HEADER

    표 58: 문단 헤더

    자료형길이(바이트)설명
    UINT324text(=chars)
    if (nchars & 0x80000000) { nchars &= 0x7fffffff; }
    UINT324control mask
    (UINT32)(1<<ctrich) 조합
    ctrich는 HwpCtrlAPI, Hwp 2.1 CtrlCh 참고
    UINT162문단 모양 아이디 참조값
    UINT81문단 스타일 아이디 참조값
    UINT81단 나누기 종류(표 59 참조)
    UINT162글자 모양 정보 수
    UINT162range tag 정보 수
    UINT162각 줄에 대한 align에 대한 정보 수
    UINT324문단 Instance ID (unique ID)
    UINT162변경추적 병합 문단여부, (5.0.3.2 버전 이상)
    전체 길이24

    표 59: 단 나누기 종류

    값설명
    0x01구역 나누기
    0x02다단 나누기
    0x04쪽 나누기
    0x08단 나누기

    레벨별 사용 / Usage by Level

    참고 / Note: 아래 내용은 공식 스펙 문서에 명시되지 않았지만, 실제 HWP 파일과 레거시 구현(libhwp, hwp-rs, pyhwp, hwpjs.js, ruby-hwp)에서 확인된 동작입니다. The following information is not explicitly stated in the official spec document, but has been confirmed through actual HWP files and legacy implementations (libhwp, hwp-rs, pyhwp, hwpjs.js, ruby-hwp).

    • Level 0: 본문의 문단 헤더 (일반적인 사용)

      • Section의 최상위 레벨에서 나타나며, 문단의 시작을 나타냅니다.
    • Level 1 이상: 컨트롤 헤더 내부의 문단 헤더 / Paragraph header inside control header

      • 각주/미주(fn , en ), 머리말/꼬리말(head, foot) 등의 컨트롤 헤더 내부에 직접 나타날 수 있습니다.
      • 이러한 경우 PARA_HEADER는 해당 컨트롤 헤더의 자식 레코드로 처리되며, 컨트롤 헤더 내부의 문단 내용을 나타냅니다.
    • SHAPE_COMPONENT 내부: LIST_HEADER 다음의 PARA_HEADER / PARA_HEADER after LIST_HEADER inside SHAPE_COMPONENT

      • SHAPE_COMPONENT(개체 요소) 내부에서 LIST_HEADER 다음에 PARA_HEADER가 나타날 수 있습니다 (글상자 텍스트).
      • PARA_HEADER can appear after LIST_HEADER inside SHAPE_COMPONENT (shape component) (textbox text).
      • 이러한 경우 PARA_HEADER는 LIST_HEADER의 형제 레코드로 나타나며, LIST_HEADER의 paragraphs 필드에 포함되어야 합니다.
      • In such cases, PARA_HEADER appears as a sibling record of LIST_HEADER and should be included in LIST_HEADER's paragraphs field.
    #4.3.2. 문단의 텍스트

    Tag ID: HWPTAG_PARA_TEXT

    텍스트의 수가 1 이상이면 문자 수만큼 텍스트를 로드하고 그렇지 않을 경우 PARA_BREAK로 문단을 생성한다.

    표 60: 문단 텍스트

    자료형길이(바이트)설명
    WCHAR array[sizeof(nchars)]2×nchars문자수만큼의 텍스트
    전체 길이가변(2×nchars) 바이트

    문단은 최소 하나의 문자 Shape buffer가 존재하며, 첫 번째 pos가 반드시 0이어야 한다. 예를 들어 문자길이 40자 짜리 문단이 10자씩 4가지 다른 글자 모양으로 구성되어 있다면 buffer는 다음과 같다.

    그림 47: 문단 버퍼 구조

    모양 1 (m_Pos=0, m_ID=1)
      ↓
    모양 2 (m_Pos=10, m_ID=2)
      ↓
    모양 3 (m_Pos=20, m_ID=3)
      ↓
    모양 4 (m_Pos=30, m_ID=4)

    텍스트 문자 Shape 레코드를 글자 모양 정보 수(Character Shapes)만큼 읽는다.

    #4.3.3. 문단의 글자 모양

    Tag ID: HWPTAG_PARA_CHAR_SHAPE

    표 61: 문단의 글자 모양

    자료형길이(바이트)설명
    UINT324글자 모양이 바뀌는 시작 위치
    UINT324글자 모양 ID
    전체 길이가변8×n
    #4.3.4. 문단의 레이아웃

    문단의 각 줄을 출력할 때 사용한 Cache 정보이며, 문단 정보의 '각 줄에 대한 align에 대한 정보 수'만큼 반복한다.

    Tag ID: HWPTAG_PARA_LINE_SEG

    표 62: 문단의 레이아웃

    자료형길이(바이트)설명
    UINT324텍스트 시작 위치
    INT324줄의 세로 위치
    INT324줄의 높이
    INT324텍스트 부분의 높이
    INT324줄의 세로 위치에서 베이스라인까지 거리
    INT324줄간격
    INT324컬럼에서의 시작 위치
    INT324세그먼트의 폭
    UINT324태그
    - bit 0: 페이지의 첫 줄인지 여부
    - bit 1: 컬럼의 첫 줄인지 여부
    - bit 16: 텍스트가 배열되지 않은 빈 세그먼트인지 여부
    - bit 17: 줄의 첫 세그먼트인지 여부
    - bit 18: 줄의 마지막 세그먼트인지 여부
    - bit 19: 줄의 마지막에 auto-hyphenation이 수행되었는지 여부
    - bit 20: indentation 적용
    - bit 21: 문단 머리 모양 적용
    - bit 31: 구현상의 편의를 위한 property
    전체 길이36
    #4.3.5. 문단의 영역 태그

    range tag 정보를 정보 수만큼 읽어 온다. range tag는 텍스트의 일정 영역을 마킹하는 용도로 사용되며. 글자 모양과는 달리 각 영역은 서로 겹칠 수 있다.(형광펜, 교정 부호 등)

    Tag ID: HWPTAG_PARA_RANGE_TAG

    표 63: 문단의 영역 태그

    자료형길이(바이트)설명
    UINT324영역 시작
    UINT324영역 끝
    UINT324태그(종류 + 데이터)
    상위 8비트가 종류를 하위 24비트가 종류별로 다른 설명을 부여할 수 있는 임의의 데이터를 나타낸다.
    전체 길이가변12×n
    #4.3.6. 컨트롤 헤더

    컨트롤 문자가 존재하면 컨트롤 문자로부터 존재하는 컨트롤 정보를 생성한다.

    Tag ID: HWPTAG_CTRL_HEADER

    표 64: 컨트롤 헤더

    자료형길이(바이트)설명
    UINT324컨트롤 ID
    컨트롤 ID 이하 속성들은 CtrlID에 따라 다르다. - 각 컨트롤 및 개체 참고
    전체 길이4

    컨트롤 ID 파싱 주의사항 / Control ID Parsing Notes

    본 라이브러리는 실제 HWP 파일 파싱 시 다음과 같은 커스텀 로직을 사용합니다:

    This library uses the following custom logic when parsing actual HWP files:

    바이트 순서 / Byte Order

    HWP 파일에서 컨트롤 ID는 4바이트 UINT32 값으로 저장되며, 바이트를 리버스해서 읽어야 올바른 문자열을 얻을 수 있습니다. 레거시 라이브러리들(pyhwp, hwp.js)과 동일하게 바이트를 리버스해서 읽습니다:

    In HWP files, control IDs are stored as 4-byte UINT32 values, and bytes must be read in reverse order to obtain the correct string. Legacy libraries (pyhwp, hwp.js) read bytes in reverse order:

    pyhwp 방식:

    def decode(bytes):
        return chr(bytes[3]) + chr(bytes[2]) + chr(bytes[1]) + chr(bytes[0])

    Rust 구현:

    let ctrl_id_bytes = [data[3], data[2], data[1], data[0]];
    let ctrl_id = String::from_utf8_lossy(&ctrl_id_bytes)
        .trim_end_matches('\0')
        .to_string();

    예시 / Example

    • 파일에 저장된 바이트: [0x20, 0x6C, 0x62, 0x74] (little-endian)

    • 리버스 후: [0x74, 0x62, 0x6C, 0x20] = "tbl " (테이블 컨트롤)

    • 리버스하지 않으면: [0x20, 0x6C, 0x62, 0x74] = " lbt" (잘못된 파싱)

    • Bytes stored in file: [0x20, 0x6C, 0x62, 0x74] (little-endian)

    • After reverse: [0x74, 0x62, 0x6C, 0x20] = "tbl " (table control)

    • Without reverse: [0x20, 0x6C, 0x62, 0x74] = " lbt" (incorrect parsing)

    공백 포함 분기 처리 / Branching with Spaces

    컨트롤 ID는 공백을 포함할 수 있으므로, 분기 처리 시 공백까지 포함해서 비교해야 합니다.

    Control IDs can include spaces, so branching logic must compare including spaces.

    주요 컨트롤 ID / Common Control IDs

    • "tbl " - 테이블 컨트롤 / Table control
    • "gso " - 일반 그리기 개체 / General shape object
    • "cold" - 단 정의 / Column definition
    • "head" - 머리말 / Header
    • "foot" - 꼬리말 / Footer

    구현 예시 / Implementation Example

    match ctrl_id.as_str() {
        "tbl " | "gso " => {
            // 개체 공통 속성 파싱 / Parse object common properties
            parse_object_common(remaining_data)?
        }
        "cold" => CtrlHeaderData::ColumnDefinition,
        "head" | "foot" => CtrlHeaderData::HeaderFooter,
        _ => CtrlHeaderData::Other,
    }

    주의: trim_end()를 사용하면 공백이 제거되어 "tbl "가 "tbl"로 변환되므로, 분기 처리 시 매칭되지 않을 수 있습니다.

    Note: Using trim_end() removes spaces, converting "tbl " to "tbl", which may cause branching to fail.

    #4.3.7. 문단 리스트 헤더

    Tag ID: HWPTAG_LIST_HEADER

    표 65: 문단 리스트 헤더

    자료형길이(바이트)설명
    INT162문단 수
    UINT324속성(표 65-1 참조)
    전체 길이6

    파싱 주의사항 / Parsing Notes

    실제 HWP 파일에서는 표 65와 다른 구조로 저장될 수 있습니다. 일부 구현체(pyhwp 등)에서는 다음과 같이 파싱합니다:

    자료형길이(바이트)설명
    UINT162문단 수
    UINT162알 수 없는 필드 (unknown1)
    UINT324속성(표 65-1 참조)
    전체 길이8

    따라서 ListHeader를 파싱할 때는 실제 데이터 구조를 확인하여 올바른 offset을 사용해야 합니다. 특히 표 셀(TableCell)의 경우 ListHeader 이후에 셀 속성(표 80)이 이어지므로, ListHeader의 실제 크기를 정확히 파악하는 것이 중요합니다.

    In actual HWP files, the structure may differ from Table 65. Some implementations (e.g., pyhwp) parse it as follows:

    Data TypeLength (bytes)Description
    UINT162Paragraph count
    UINT162Unknown field (unknown1)
    UINT324Attribute (see Table 65-1)
    Total Length8

    Therefore, when parsing ListHeader, the actual data structure should be verified to use the correct offset. Especially for table cells (TableCell), since cell attributes (Table 80) follow after ListHeader, it is important to accurately determine the actual size of ListHeader.

    표 65-1: 문단 리스트 헤더 속성

    범위구분값설명
    bit 0-2텍스트 방향0가로
    1세로
    bit 3-4문단의 줄바꿈0일반적인 줄바꿈
    1자간을 조종하여 한 줄을 유지
    2내용에 따라 폭이 늘어남
    bit 5-6세로 정렬0top
    1center
    2bottom
    #4.3.8. 컨트롤 임의의 데이터

    컨트롤의 필드 이름이나 하이퍼링크 정보를 저장한다.

    Tag ID: HWPTAG_CTRL_DATA

    표 66: 컨트롤 임의의 데이터

    자료형길이(바이트)설명
    Parameter Set가변파라미터 셋(표 50 참조)
    전체 길이가변
    #4.3.9. 개체 공통 속성을 포함하는 컨트롤(개체 컨트롤)

    extended type의 컨트롤은 종류를 나타내는 식별 기호로 32 비트 ID가 사용된다. 컨트롤 코드가 큰 범주를 나타내는 식별 기호라고 한다면, 컨트롤 ID는 세부 분류를 나타내는 식별 기호인 셈이다.

    예를 들어 단 정의 컨트롤 ID는 MAKE_4CHID('c', 'o', 'T', 'd') 같은 형식으로 정의한다.

    MAKE_4CHID(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))

    표 67: 개체 공통 속성을 포함하는 컨트롤과 컨트롤ID

    표컨트롤 ID개체 공통 속성개체 요소 속성
    1(그리기 개체)MAKE_4CHID('t', 'b', 'T', '')✓
    선MAKE_4CHID('$', 'r', 'T', 'n')✓
    2사각형MAKE_4CHID('$', 'r', 'e', 'c')✓
    타원MAKE_4CHID('$', 'e', 'l', 'l')✓
    호MAKE_4CHID('$', 'a', 'r', 'c')✓
    다각형MAKE_4CHID('$', 'p', 'o', 'l')✓
    곡선MAKE_4CHID('$', 'c', 'u', 'r')✓
    3한글 97 수식MAKE_4CHID('e', 'q', 'e', 'd')✓
    4그림MAKE_4CHID('$', 'p', 'i', 'c')✓
    5OLEMAKE_4CHID('$', 'o', 'l', 'e')✓
    6묶음 개체MAKE_4CHID('$', 'c', 'o', 'n')✓

    표 68: 개체 공통 속성

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 69 참조)
    BYTE streamn2캡션 정보가 있으면 캡션 리스트 정보를 얻는다(표 71 참조)
    전체 길이가변n + n2 바이트

    표 69: 개체 공통 속성

    자료형길이(바이트)설명
    UINT324ctrl ID
    UINT324속성(표 70 참조)
    HWPUNIT4세로 오프셋 값
    HWPUNIT4가로 오프셋 값
    HWPUNIT4width 오브젝트의 폭
    HWPUNIT4height 오브젝트의 높이
    INT324z-order
    HWPUNIT16 array[4]8오브젝트의 바깥 4방향 여백
    UINT324문서 내 각 개체에 대한 고유 아이디(instance ID)
    INT324쪽나눔 방지 on(1) / off(0)
    WORD2개체 설명문 글자 길이(len)
    WCHAR array[len]2×len개체 설명문 글자
    전체 길이가변46 + (2×len) 바이트

    구현 주의사항 (DIFFSPEC) / Implementation Notes (DIFFSPEC)

    스펙 문서 표 69에서는 offset_y와 offset_x가 HWPUNIT (unsigned)로 명시되어 있지만, 실제 HWP 파일에서는 SHWPUNIT (signed)로 파싱해야 합니다.

    이유:

    • 오프셋 값은 기준점보다 위나 왼쪽에 위치할 수 있어 음수 값이 필요합니다.
    • 예: 0xFFFFF9ED (4294964461 as u32) = -835 (as i32) = 약 -0.116인치

    레거시 구현 참고:

    • pyhwp: SHWPUNIT을 사용하고 # DIFFSPEC 주석으로 표시
    • hwpjs.js: getUint32를 사용하지만, 이는 잘못된 구현일 수 있음

    따라서 본 라이브러리는 offset_y와 offset_x를 INT32로 읽어 SHWPUNIT으로 변환합니다.

    파싱 주의사항 / Parsing Notes

    본 라이브러리는 실제 HWP 파일 파싱 시 parse_object_common 함수가 컨트롤 ID 이후의 데이터만 파싱하므로, 최소 40바이트가 필요합니다. 표 69의 전체 길이는 컨트롤 ID(4바이트)를 포함한 46 + (2×len) 바이트이지만, 컨트롤 ID를 제외하면 42 + (2×len) 바이트입니다.

    구조 분석:

    • 필수 필드 (컨트롤 ID 제외): attribute(4) + offset_y(4) + offset_x(4) + width(4) + height(4) + z_order(4) + margin(8) + instance_id(4) + page_divide(4) = 40바이트
    • 선택적 필드: description_len(2) + description(2×len)

    따라서 40바이트는 유효한 크기입니다 (page_divide까지 포함, description 없음). 일부 파일에서는 40바이트만 있을 수 있으며, 42바이트 이상일 때는 description이 포함될 수 있습니다.

    표 70: 개체 공통 속성

    범위구분값설명
    bit 0글자처럼 취급 여부
    bit 1예약
    bit 2줄 간격에 영향을 줄지 여부
    bit 3-4세로 위치의 기준 (VertRelTo)0paper
    1page
    2para
    bit 5-7세로 위치의 기준에 대한 상대적인 배열 방식0VerRelTo이 'paper'나 'page' 이면 top, 그렇지 않으면 left
    1VerRelTo이 'paper'나 'page' 이면 center
    2VerRelTo이 'paper'나 'page' 이면 bottom, 그렇지 않으면 right
    3VerRelTo이 'paper'나 'page' 이면 inside
    4VerRelTo이 'paper'나 'page' 이면 outside
    bit 8-9가로 위치의 기준 (HorzRelTo)0page
    1page
    2column
    3para
    bit 10-12HorzRelTo에 대한 상대적인 배열 방식(bit 5-7 참조)
    bit 13VertRelTo이 'para'일 때 오브젝트의 세로 위치를 본문 영역으로 제한할지 여부0off
    1on
    bit 14다른 오브젝트와 겹치는 것을 허용할지 여부오브젝트의 위치가 본문 영역으로 제한되면 언제나 false로 간주한다.
    bit 15-17오브젝트 폭의 기준0paper
    1page
    2column
    3para
    4absolute
    bit 18-19오브젝트 높이의 기준0paper
    1page
    2absolute
    bit 20VertRelTo이 para일 때 크기 보호 여부0off
    1on
    bit 21-23오브젝트 주위를 텍스트가 어떻게 흘러갈지 지정하는 옵션0Square (bound rect를 따라)
    1Tight (오브젝트의 outline을 따라)
    2Through (오브젝트 내부의 빈 공간까지)
    3TopAndBottom (좌, 우에는 텍스트를 배치하지 않음)
    4BehindText (글과 겹치게 하여 글 뒤로)
    5InFrontOfText (글과 겹치게 하여 글 앞으로)
    bit 24-25오브젝트의 좌/우 어느 쪽에 글을 배치할지 지정하는 옵션0BothSides
    1LeftOnly
    2RightOnly
    3LargestOnly
    bit 26-28이 개체가 속하는 번호 범주0none
    1figure
    2table
    3equation

    표 71: 캡션 리스트

    자료형길이(바이트)설명
    BYTE streamn문단 리스트 헤더(표 65 참조)
    BYTE stream12캡션(표 72 참조)
    전체 길이가변12+ 바이트

    표 72: 캡션

    자료형길이(바이트)설명
    UINT4속성(표 73 참조)
    HWPUNIT4캡션 폭(세로 방향일 때만 사용)
    HWPUNIT162캡션과 개체 사이 간격
    HWPUNIT4텍스트의 최대 길이(=개체의 폭)
    전체 길이14

    표 73: 캡션 속성

    범위구분값설명
    bit 0-1방향0left
    1right
    2top
    3bottom
    bit 2캡션 폭에 마진을 포함할 지 여부 (가로 방향일 때만 사용)
    #4.3.9.1. 표 개체

    Tag ID: HWPTAG_TABLE

    표 74: 표 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2표 개체 속성(표 75 참조)
    BYTE streamn3셀 리스트(표 79 참조)
    셀 sizex셀 개수
    전체 길이가변n + n2 + n3

    표 75: 표 개체 속성

    자료형길이(바이트)설명
    UINT324속성(표 76 참조)
    UINT162RowCount
    UINT162nCols
    HWPUNIT162CellSpacing
    BYTE stream8안쪽 여백 정보(표 77 참조)
    BYTE stream2×rowRow Size
    UINT162Border Fill ID
    UINT162Valid Zone Info Size (5.0.1.0 이상)
    BYTE stream10×zone영역 속성(표 78 참조) (5.0.1.0 이상)
    전체 길이가변22 + (2×row) + (10×zone)

    표 76: 표 속성의 속성

    범위구분값설명
    bit 0-1쪽 경계에서 나눔0나누지 않음
    1셀 단위로 나눔
    2나누지 않음
    bit 2제목 줄 자동 반복 여부

    표 77: 안쪽 여백 정보

    자료형길이(바이트)설명
    HWPUNIT162왼쪽 여백
    HWPUNIT162오른쪽 여백
    HWPUNIT162위쪽 여백
    HWPUNIT162아래쪽 여백
    전체 길이8

    표 78: 영역 속성

    자료형길이(바이트)설명
    UINT162시작 열 주소
    UINT162시작 행 주소
    UINT162끝 열 주소
    UINT162끝 행 주소
    UINT162테두리 채우기 ID
    전체 길이10

    표 79: 셀 리스트

    자료형길이(바이트)설명
    BYTE streamn문단 리스트 헤더(표 65 참조)
    BYTE stream26셀 속성(표 80 참조)
    전체 길이가변26+n 바이트

    파싱 주의사항 / Parsing Notes

    표 65에 명시된 ListHeader는 6바이트이지만, 실제 구현에서는 8바이트일 수 있습니다 (UINT16 + UINT16 + UINT32). 따라서 셀 속성(표 80)을 파싱할 때는 ListHeader의 실제 크기를 확인하여 올바른 offset(6 또는 8바이트)을 사용해야 합니다.

    Table 65 specifies ListHeader as 6 bytes, but actual implementations may use 8 bytes (UINT16 + UINT16 + UINT32). Therefore, when parsing cell attributes (Table 80), the actual size of ListHeader should be verified to use the correct offset (6 or 8 bytes).

    표 80: 셀 속성

    자료형길이(바이트)설명
    UINT162셀 주소(Column, 맨 왼쪽 셀이 0부터 시작하여 1씩 증가)
    UINT162셀 주소(Row, 맨 위쪽 셀이 0부터 시작하여 1씩 증가)
    UINT162열의 병합 개수
    UINT162행의 병합 개수
    HWPUNIT4셀의 폭
    HWPUNIT4셀의 높이
    HWPUNIT16 array[4]8셀 4방향 여백
    UINT162테두리/배경 아이디
    전체 길이26
    #4.3.9.2. 그리기 개체(선, 사각형, 타원, 호, 다각형, 곡선)

    모든 그리기 개체에 대한 serialization은 우선 base인 그리기 개체 공통 속성을 serialize한 다음 자신이 가지고 있는 개체 요소 속성을 serialize한다.

    표 81: 그리기 개체 공통 속성

    자료형길이(바이트)설명
    BYTE streamn개체 요소 속성(표 82 참조)
    BYTE stream11테두리 선 정보(표 86 참조)
    BYTE streamn2채우기 정보(표 28 참조)
    BYTE stream12글상자 속성이 있으면 글상자의 리스트 정보를 얻는다
    전체 길이가변23 + n + n2 바이트

    ####### 4.3.9.2.1. 개체 요소

    Tag ID: HWPTAG_SHAPE_COMPONENT (GenShapeObject일 경우 id가 두 번 기록됨)

    표 82: 개체 요소 속성

    자료형길이(바이트)설명
    UINT324개체 컨트롤 ID
    UINT324개체 컨트롤 ID (두 번째 ID, 실제 파일에서는 항상 존재)
    전체 길이8

    참고사항 / Notes

    실제 HWP 파일에서는 모든 SHAPE_COMPONENT 레코드에서 개체 컨트롤 ID가 두 번 기록됩니다. pyhwp, hwp.js도 항상 두 번째 ID를 읽고 있습니다.

    표 83: 개체 요소 속성

    자료형길이(바이트)설명
    INT324개체가 속한 그룹 내에서의 X offset
    INT324개체가 속한 그룹 내에서의 Y offset
    WORD2몇 번이나 그룹 되었는지
    WORD2개체 요소의 local file version
    UINT324개체 생성 시 초기 폭
    UINT324개체 생성 시 초기 높이
    UINT324개체의 현재 폭
    UINT324개체의 현재 높이
    UINT324속성
    - 0: horz flip
    - 1: vert flip
    HWPUNIT162회전각
    INT324회전 중심의 x 좌표(개체 좌표계)
    INT324회전 중심의 y 좌표(개체 좌표계)
    BYTE streamnRendering 정보(표 84 참조)
    전체 길이가변42+n 바이트

    표 84: Rendering 정보

    자료형길이(바이트)설명
    WORD2scale matrix와 rotation matrix쌍의 개수(cnt)
    초기엔 1, group할 때마다 하나씩 증가하고, ungroup할 때마다 하나씩 감소한다.
    BYTE stream48translation matrix(표 85 참조)
    BYTE streamcnt×48×2scale matrix/rotation matrix sequence(표 85 참조)
    전체 길이가변50 + (cnt×48×2) 바이트

    각 matrix는 원소가 double로 표현되는 3X3 matrix로 구현된다. 마지막 줄(row)은 항상 0, 0, 1이기 때문에 실제 serialization에서는 마지막 줄은 빠진다. 저장되는 정보는 다음과 같다.

    표 85: matrix 정보

    자료형길이(바이트)설명
    double array[6]483X2 matrix의 원소
    전체 길이48

    표 86: 테두리 선 정보

    자료형길이(바이트)설명
    COLORREF4선 색상
    INT162선 굵기
    UINT324속성(표 87 참조)
    BYTE1Outline style(표 88 참조)
    전체 길이11

    표 87: 테두리 선 정보 속성

    범위구분값설명
    bit 0-5선 종류
    bit 6-9선 끝 모양0round (그림일 때는 "Round")
    1flat (그리기 개체들일 때는 "Flat"이 디폴트)
    bit 10-15화살표 시작 모양0모양 없음
    1화살 모양
    2오목한 화살모양
    3속이 빈 다이아몬드 모양
    4속이 빈 원 모양
    5속이 빈 사각 모양
    6속이 채워진 다이아몬드 모양
    7속이 채워진 원 모양
    8속이 채워진 사각 모양
    bit 16-21화살표 끝 모양(화살표 시작 모양과 동일)
    bit 22-25화살표 시작 크기0작은-작은
    1작은-중간
    2작은-큰
    3중간-작은
    bit 26-29화살표 끝 크기4중간-중간
    5중간-큰
    6큰-작은
    7큰-중간
    8큰-큰
    bit 30시작부분 화살표 채움 여부
    bit 31끝부분 화살표 채움 여부

    표 88: Outline style

    값설명
    0normal
    1outer
    2inner

    표 89: 그리기 개체 글상자용 텍스트 정보

    자료형길이(바이트)설명
    BYTE stream12그리기 개체 글상자용 텍스트 속성(표 90 참조)
    BYTE streamn문단 리스트 헤더(표 65 참조)
    전체 길이가변12+n 바이트

    표 90: 그리기 개체 글상자용 텍스트 속성

    자료형길이(바이트)설명
    HWPUNIT162글상자 텍스트 왼쪽 여백
    HWPUNIT162글상자 텍스트 오른쪽 여백
    HWPUNIT162글상자 텍스트 위쪽 여백
    HWPUNIT162글상자 텍스트 아래쪽 여백
    HWPUNIT4텍스트 문자열의 최대 폭 (보통 그리기 개체의 가로 크기와 동일)
    전체 길이12

    ####### 4.3.9.2.2. 선 개체

    Tag ID: HWPTAG_SHAPE_COMPONENT_LINE

    구현 상태

    • 구현 완료
    • 테스트 파일(noori.hwp)에 SHAPE_COMPONENT_LINE 레코드가 없어 실제 파일로 테스트되지 않음

    표 91: 선 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2그리기 개체 공통 속성(표 81 참조)
    BYTE stream18선 개체 속성(표 92 참조)
    전체 길이가변18 + n + n2 바이트

    표 92: 선 개체 속성

    자료형길이(바이트)설명
    INT324시작점 X 좌표
    INT324시작점 Y 좌표
    INT324끝점 X 좌표
    INT324끝점 Y 좌표
    UINT162속성
    처음 생성 시 수직 또는 수평선일 때, 선의 방향이 언제나 오른쪽(위쪽)으로 잡힘으로 인한 현상 때문에, 방향을 바로 잡아주기 위한 플래그
    전체 길이18

    ####### 4.3.9.2.3. 사각형 개체

    Tag ID: HWPTAG_SHAPE_COMPONENT_RECTANGLE

    구현 상태

    • 구현 완료
    • 테스트 파일(noori.hwp)에 SHAPE_COMPONENT_RECTANGLE 레코드가 없어 실제 파일로 테스트되지 않음

    표 93: 사각형 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2그리기 개체 공통 속성(표 81 참조)
    BYTE stream33사각형 개체 속성(표 94 참조)
    전체 길이가변33 + n + n2 바이트

    표 94: 사각형 개체 속성

    자료형길이(바이트)설명
    BYTE1사각형 모서리 곡률(%)
    직각은 0, 둥근 모양은 20, 반원은 50, 그 외는 적당한 값을 % 단위로 사용한다.
    INT32 array[4]16사각형의 좌표(x)
    INT32 array[4]16사각형의 좌표(y)
    전체 길이33

    ####### 4.3.9.2.4. 타원 개체

    Tag ID: HWPTAG_SHAPE_COMPONENT_ELLIPSE

    구현 상태

    • 구현 완료
    • 테스트 파일(noori.hwp)에 SHAPE_COMPONENT_ELLIPSE 레코드가 없어 실제 파일로 테스트되지 않음

    표 95: 타원 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2그리기 개체 공통 속성(표 81 참조)
    BYTE stream60타원 개체 속성(표 96 참조)
    전체 길이가변60 + n + n2 바이트

    표 96: 타원 개체 속성

    자료형길이(바이트)설명
    UINT324속성(표 97 참조)
    INT324중심 좌표의 X 값
    INT324중심 좌표의 Y 값
    INT324제1축 X 좌표 값
    INT324제1축 Y 좌표 값
    INT324제2축 X 좌표 값
    INT324제2축 Y 좌표 값
    INT324start pos x
    INT324start pos y
    INT324end pos x
    INT324end pos y
    INT324start pos x2
    INT324interval of curve(effective only when it is an arc)
    INT324start pos y2
    INT324end pos x2
    INT324end pos y2
    전체 길이60

    표 97: 타원/호 개체 속성의 속성

    범위설명
    bit 0호(ARC)로 바뀌었을 때, interval을 다시 계산해야 할 필요가 있는지 여부 (interval - 원 위에 존재하는 두 점 사이의 거리)
    bit 1호(ARC)로 바뀌었는지 여부
    bit 2-9호(ARC)의 종류

    ####### 4.3.9.2.5. 다각형 개체

    Tag ID: HWPTAG_SHAPE_COMPONENT_POLYGON

    표 98: 다각형 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2그리기 개체 공통 속성(표 81 참조)
    BYTE streamn3다각형 개체 속성(표 99 참조)
    전체 길이가변n+n2+n3 바이트

    표 99: 다각형 개체 속성

    자료형길이(바이트)설명
    INT162count of points(cnt)
    INT32 array[cnt]4×cntx 좌표
    INT32 array[cnt]4×cnty 좌표
    전체 길이가변2+2(4×cnt) 바이트

    ####### 4.3.9.2.6. 호 개체

    Tag ID: HWPTAG_SHAPE_COMPONENT_ARC

    표 100: 호 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2그리기 개체 공통 속성(표 81 참조)
    BYTE stream28호 개체 속성(표 101 참조)
    전체 길이가변28+n+n2 바이트

    표 101: 호 개체 속성

    자료형길이(바이트)설명
    UINT324속성(표 97 참조)
    INT324타원의 중심 좌표 X 값
    INT324타원의 중심 좌표 Y 값
    INT324제1축 X 좌표 값
    INT324제1축 Y 좌표 값
    INT324제2축 X 좌표 값
    INT324제2축 Y 좌표 값
    전체 길이28

    ####### 4.3.9.2.7. 곡선 개체

    Tag ID: HWPTAG_SHAPE_COMPONENT_CURVE

    표 102: 곡선 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2그리기 개체 공통 속성(표 81 참조)
    BYTE streamn3곡선 개체 속성(표 103 참조)
    전체 길이가변n+n2+n3 바이트

    표 103: 곡선 개체 속성

    자료형길이(바이트)설명
    INT162count of points(cnt)
    INT32 array[cnt]4×cntx 좌표
    INT32 array[cnt]4×cnty 좌표
    BYTE array[cnt-1]cnt-1segment type(0: line, 1: curve)
    전체 길이가변2 + 2(4×cnt) + cnt-1 바이트
    #4.3.9.3. 호글 수식 개체

    Tag ID: HWPTAG_EQEDIT

    표 104: 수식 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2수식 개체 속성(표 105 참조)
    전체 길이가변n + n2 바이트

    표 105: 수식 개체 속성

    자료형길이(바이트)설명
    UINT324속성. 스크립트가 차지하는 범위. 첫 비트가 켜져 있으면 줄 단위, 꺼져 있으면 글자 단위.
    WORD2스크립트 길이(len)
    WCHAR array[len]2×len한글 수식 스크립트(*)
    HWPUNIT4수식 글자 크기
    COLORREF4글자 색상
    INT162base line
    WCHAR array[len]2×len수식 버전 정보
    WCHAR array[len]2×len수식 폰트 이름
    전체 길이가변16 + (6×len) 바이트

    *호글 수식 스크립트는 EQN 스크립트 호환이며 자세한 스펙은 뒤에 추가

    #4.3.9.4. 그림 개체(HWPTAG_SHAPE_COMPONENT_PICTURE)

    Tag ID: HWPTAG_SHAPE_COMPONENT_PICTURE

    구현 참고사항 / Implementation Notes

    레벨 정보 / Level Information

    스펙 문서 표 5에서는 HWPTAG_SHAPE_COMPONENT와 HWPTAG_SHAPE_COMPONENT_PICTURE 모두 레벨 1로 표시되어 있습니다. 하지만 실제 HWP 파일에서는 두 가지 경우가 모두 가능합니다:

    1. 레벨 1 (형제 관계): SHAPE_COMPONENT와 SHAPE_COMPONENT_PICTURE가 같은 레벨 형제로 나타나는 경우
    2. 레벨 3 (부모-자식 관계): SHAPE_COMPONENT_PICTURE가 SHAPE_COMPONENT의 자식(level 3)으로 파싱되는 경우

    이는 스펙 문서 표 106에서 SHAPE_COMPONENT_PICTURE가 SHAPE_COMPONENT와 동일한 "개체 요소 공통 속성(표 83)"을 포함하기 때문에, 실제 바이너리 구조에서 SHAPE_COMPONENT_PICTURE가 SHAPE_COMPONENT의 자식으로 중첩될 수 있기 때문입니다.

    파서 구현 / Parser Implementation

    파서 구현 시 SHAPE_COMPONENT의 children을 재귀적으로 처리하도록 구현해야 합니다. SHAPE_COMPONENT에 children 필드를 추가하여, SHAPE_COMPONENT_PICTURE가 자식으로 올 경우 이를 포함할 수 있도록 해야 합니다. 이렇게 하면 레벨 1과 레벨 3 두 경우 모두 올바르게 처리할 수 있습니다.

    표 106: 그림 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2개체 요소 공통 속성(표 83 참조)
    BYTE streamn3그림 개체 속성(표 107 참조)
    전체 길이가변n + n2 + n3 바이트

    표 107: 그림 개체 속성

    자료형길이(바이트)설명
    COLORREF4테두리 색
    INT324테두리 두께
    UINT324테두리 속성(표 87 참조)
    INT32 array[4]16이미지의 테두리 사각형의 x 좌표(최초 그림 삽입 시 크기)
    INT32 array[4]16이미지의 테두리 사각형의 y 좌표(최초 그림 삽입 시 크기)
    INT324자르기 한 후 사각형의 left
    INT324자르기 한 후 사각형의 top
    INT324자르기 한 후 사각형의 right
    INT324자르기 한 후 사각형의 bottom
    BYTE stream8안쪽 여백 정보(표 77 참조) 표(기본값: 141), 그림(기본값: 0)
    BYTE stream5그림 정보(표 32 참조)
    BYTE1테두리 투명도
    UINT324문서 내 각 개체에 대한 고유 아이디(instance ID)
    BYTE streamn그림 효과 정보(표 108 참조)
    전체 길이가변78 + n 바이트

    표 108: 그림 효과 속성

    자료형길이(바이트)설명
    UINT324그림 효과 정보(그림자, 네온, 부드러운 가장자리, 반사)
    BYTE streamn각 효과 정보(표 109 ~ 표 113 참조)
    전체 길이가변4 + n 바이트

    표 109: 그림자 효과 속성

    자료형길이(바이트)설명
    INT324그림자 스타일
    float4그림자 투명도
    float4그림자 흐릿하게
    float4방향
    float4거리
    INT324정렬
    float4기울기 각도(X)
    float4기울기 각도(Y)
    float4확대 비율(X)
    float4확대 비율(Y)
    INT324도형과 함께 그림자 회전
    BYTE streamn그림자 색상(표 113 참조)
    전체 길이가변44 + n 바이트

    표 110: 네온 효과 속성

    자료형길이(바이트)설명
    float4네온 투명도
    float4네온 반경
    BYTE streamn네온 색상(표 113 참조)
    전체 길이가변8 + n 바이트

    표 111: 부드러운 가장자리 효과 속성

    자료형길이(바이트)설명
    float4부드러운 가장자리 반경
    전체 길이4

    표 112: 반사 효과 속성

    자료형길이(바이트)설명
    INT324반사 스타일
    float4반경
    float4방향
    float4거리
    float4기울기 각도(X)
    float4기울기 각도(Y)
    float4확대 비율(X)
    float4확대 비율(Y)
    INT324회전 스타일
    float4시작 투명도
    float4시작 위치
    float4끝 투명도
    float4끝 위치
    float4오프셋 방향
    전체 길이53

    표 113: 색상 속성

    자료형길이(바이트)설명
    INT324색상 타입
    UINT324RGB (0x00rrggbb)
    UINT324CMYK (0xccmmyykk)
    INT324스키마 타입
    INT324시스템 타입
    INT324프리셋 타입
    float4ScR
    float4ScG
    float4ScB
    float4H
    float4S
    float4L
    UINT324색상 효과 수
    BYTE array[n]8×n색상 효과(표 114 참조)
    전체 길이가변4 + m(4 - 12) + n 바이트

    표 114: 색상 효과 속성

    자료형길이(바이트)의미
    INT324색상 효과 종류(표 115 참조)
    float4색상 효과 값
    전체 길이8

    표 115: 색상 효과 종류

    값설명
    0alpha
    1alpha_mod
    2alpha_off
    3red
    4red_mod
    5red_off
    6green
    7green_mod
    8green_off
    9blue
    10blue_mod
    11blue_off
    12hue
    13hue_mod
    14hue_off
    15sat
    16sat_mod
    17sat_off
    18lum
    19lum_mod
    20lum_off
    21shade
    22tint
    23gray
    24comp
    25gamma
    26inv_gamma
    27inv

    표 116: 그림 추가 속성

    자료형길이(바이트)설명
    HWPUNIT8그림 최초 생성 시 기준 이미지 크기
    INT81이미지 투명도
    전체 길이9
    #4.3.9.5. OLE 개체(HWPTAG_SHAPE_COMPONENT_OLE)

    Tag ID: HWPTAG_SHAPE_COMPONENT_OLE

    구현 상태

    • 구현 완료
    • 테스트 파일(noori.hwp)에 SHAPE_COMPONENT_OLE 레코드가 없어 실제 파일로 테스트되지 않음

    표 117: OLE 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE stream24OLE 개체 속성(표 118 참조)
    전체 길이가변24 + n 바이트

    표 118: OLE 개체 속성

    자료형길이(바이트)설명
    UINT162속성(표 119 참조)
    INT324오브젝트 자체의 extent x크기
    INT324오브젝트 자체의 extent y크기
    UINT162오브젝트가 사용하는 스토리지의 BinData ID
    COLORREF4테두리 색
    INT324테두리 두께
    UINT324테두리 속성(표 87 참조)
    전체 길이24

    표 119: OLE 개체 속성의 속성

    범위설명
    bit 0-7drawing aspect
    - DVASPECT_CONTENT = 1
    - DVASPECT_THUMBNAIL = 2
    - DVASPECT_ICON = 4
    - DVASPECT_DOCPRINT = 8
    자세한 설명은 MSDN의 MFC COleClientItem::m_nDrawAspect 참고
    bit 8TRUE if moniker is assigned
    자세한 설명은 MSDN의 MFC COleClientItem::m_bMoniker 참고
    bit 9-15베이스라인. 0은 기본값(85%), 1-101은 0-100%를 나타냄. 현재는 수식만 별도의 베이스라인을 가짐
    bit 16-21개체 종류
    - 0: Unknown
    - 1: Embedded
    - 2: Link
    - 3: Static
    - 4: Equation

    ⚠️ 실제 구현 시 주의사항 (Implementation Notes)

    표 119에서 bit 16-21은 "개체 종류"를 나타낸다고 명시되어 있으나, 실제로 속성 필드는 UINT16 (16비트) 타입입니다.

    UINT16은 16비트이므로 bit 16-21은 이 필드에 존재하지 않습니다. 실제 구현에서는:

    • bit 0-7: drawing aspect
    • bit 8: has moniker
    • bit 9-15: baseline

    만약 "개체 종류" 정보가 필요하다면, 이후 데이터 필드에서 별도로 읽어야 할 수 있습니다.

    #4.3.9.6. 차트 개체

    차트 개체는 본문에 OLE 개체로 저장되며, 그 내용은 OLE Compound file에 저장된다.

    차트 파일의 최상위 스토리지는 "Contents" 또는 "OOXMLChartContents" 스트림이 될 수 있다.

    구버전 한글(한글 Neo) 차트는 "Contents" 스트림만 사용한다.

    한글 2018은 OOXML 차트를 지원하며, "OOXMLChartContents"와 "Contents" 스트림 모두에 저장한다.

    한글 2018에서 차트의 "Contents" 스트림은 OOXML 차트를 구버전 한글 Neo 형식으로 변환하기 위한 백업 데이터 역할을 한다.

    "Contents" 스트림의 내용은 첨부 파일("한글문서파일형식_차트_revision1.2_원본.hwp")을 참조한다.

    "OOXMLChartContents" 스트림은 MS OOXML 차트 저장용이며, 최상위 요소는 "chartSpace"이다. 그 내용은 ISO/IEC 29500 또는 ECMA 376의 DrawingML Chart 섹션을 참조한다.

    #4.3.9.7. 묶음 개체(HWPTAG_SHAPE_COMPONENT_CONTAINER)

    Tag ID: HWPTAG_SHAPE_COMPONENT_CONTAINER

    구현 상태

    • 구현 완료
    • 테스트 파일(noori.hwp)에 SHAPE_COMPONENT_CONTAINER 레코드가 없어 실제 파일로 테스트되지 않음

    표 120: 묶음 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2묶음 개체 속성(표 121 참조)
    BYTE streamn3개체 속성 x 묶음 개체의 갯수 (묶음 가능 개체: 그리기 개체, OLE, 그림, 묶음 개체)
    전체 길이가변n + n2 + n3 바이트

    표 121: 묶음 개체 속성

    자료형길이(바이트)설명
    WORD2개체의 개수(n)
    UINT32 array[n]4×n개체의 컨트롤 ID array
    전체 길이가변2 + (4×n) 바이트
    #4.3.9.8. 동영상 개체(HWPTAG_VIDEO_TDATA)

    Tag ID: HWPTAG_VIDEO_DATA

    표 122: 동영상 개체

    자료형길이(바이트)설명
    BYTE streamn개체 공통 속성(표 68 참조)
    BYTE streamn2동영상 개체 속성(표 123 참조)
    전체 길이가변n + n2 바이트

    표 123: 동영상 개체 속성

    자료형길이(바이트)설명
    INT324동영상 타입(표 124 참조)
    BYTE streamn동영상 타입에 따라 길이가 다름(표 125, 표 126 참조)
    전체 길이가변4 + n 바이트

    표 124: 동영상 타입

    값설명
    0로컬 동영상
    1웹 동영상

    표 125: 로컬 동영상 속성

    자료형길이(바이트)설명
    UINT162비디오 파일이 사용하는 스토리지의 BinData ID
    UINT162썸네일 파일이 사용하는 스토리지의 BinData ID
    전체 길이4

    표 126: 웹 동영상 속성

    자료형길이(바이트)설명
    WCHAR array[len]2×len웹 태그
    UINT162썸네일 파일이 사용하는 스토리지의 BinData ID
    전체 길이가변(2×len)+2 바이트
    #4.3.10. 개체 이외의 컨트롤

    HWPTAG_CTRL_HEAD부터 시작하며 ctrlid로 각 개체를 확인할 수 있다.

    특징 컨트롤은 정보 이외의 문단 리스트를 가질 수 있다.

    개체 컨트롤 ID / Object Control IDs

    개체 공통 속성(Object Common Properties)을 가지는 컨트롤 ID들입니다. 이들은 표 127에 포함되지 않지만 중요한 컨트롤 ID입니다.

    컨트롤 ID의미설명
    MAKE_4CHID('t', 'b', 'l', ' ') = "tbl "테이블 컨트롤 / Table control표 개체를 나타내는 컨트롤 ID
    MAKE_4CHID('g', 's', 'o', ' ') = "gso "일반 그리기 개체 / General shape object글상자, 그림 등 그리기 개체를 나타내는 컨트롤 ID

    표 127: 개체 이외의 컨트롤과 컨트롤 ID

    표의미컨트롤 ID문단 리스트파일 태그
    1구역 정의MAKE_4CHID('s', 'e', 'c', 'd')
    2단 정의MAKE_4CHID('c', 'o', 'l', 'd')
    3머리말/꼬리말MAKE_4CHID('h', 'e', 'a', 'd')✓
    3-1머리말MAKE_4CHID('h', 'e', 'a', 'd')✓
    참고: 스펙 문서에 명시적으로 정의되지 않았으나 실제 구현에서 머리말로 사용됨
    4각주/미주MAKE_4CHID('f', 'o', 'o', 't')✓
    4-1꼬리말MAKE_4CHID('f', 'o', 'o', 't')✓
    참고: 스펙 문서에 명시적으로 정의되지 않았으나 실제 구현에서 꼬리말로 사용됨
    4-2각주MAKE_4CHID('f', 'n', ' ', ' ')✓
    참고: 스펙 문서에 명시적으로 정의되지 않았으나 실제 구현에서 각주로 사용됨 (공백 포함)
    4-3미주MAKE_4CHID('e', 'n', ' ', ' ')✓
    참고: 스펙 문서에 명시적으로 정의되지 않았으나 실제 구현에서 미주로 사용됨 (공백 포함)
    5자동번호MAKE_4CHID('a', 'u', 't', 'n')
    6새 번호 지정MAKE_4CHID('n', 'e', 'w', 'n')
    7감추기MAKE_4CHID('p', 'g', 'h', 'd')✓
    8홀/짝수 조정MAKE_4CHID('p', 'g', 'a', 'd')
    9쪽 번호 위치MAKE_4CHID('p', 'g', 'n', 'o')
    9-1쪽 번호 위치MAKE_4CHID('p', 'g', 'n', 'p')
    참고: 스펙 문서에 명시적으로 정의되지 않았으나 실제 파일에서 사용됨
    10찾아보기 표식MAKE_4CHID('b', 'k', 'm', 'k')
    11책갈피MAKE_4CHID('b', 'k', 'm', 'k')
    12글자 겹침MAKE_4CHID('o', 'v', 'e', 'r')
    13덧말MAKE_4CHID('c', 'm', 't', 't')
    14숨은 설명MAKE_4CHID('h', 'i', 'd', 'e')✓
    15필드 시작MAKE_4CHID('%', '%', '%', '%')

    표 128: 필드 컨트롤 ID

    필드컨트롤 ID
    FIELD_UNKNOWNMAKE_4CHID('%', 'u', 'n', 'k')
    FIELD_DATEMAKE_4CHID('%', 'd', 't', 'e')
    FIELD_DOCDATEMAKE_4CHID('%', 'd', 'd', 't')
    FIELD_PATHMAKE_4CHID('%', 'p', 'a', 't')
    FIELD_BOOKMARKMAKE_4CHID('%', 'b', 'k', 'm')
    FIELD_MAILMERGEMAKE_4CHID('%', 'm', 'm', 'g')
    FIELD_CROSSREFMAKE_4CHID('%', 'c', 'r', 'f')
    FIELD_FORMULAMAKE_4CHID('%', 'f', 'm', 'l')
    FIELD_HYPERLINKMAKE_4CHID('%', 'h', 'l', 'k')
    FIELD_REVISION_SIGNMAKE_4CHID('%', '%', 's', 'g')
    FIELD_REVISION_DELETEMAKE_4CHID('%', '%', 'd', 'e')
    FIELD_REVISION_INSERTMAKE_4CHID('%', '%', 'i', 'n')
    FIELD_REVISION_CHANGEMAKE_4CHID('%', '%', 'c', 'h')
    FIELD_REVISION_ATTACHMAKE_4CHID('%', '%', 'a', 't')
    FIELD_REVISION_HYPERLINKMAKE_4CHID('%', '%', '', 'h')
    FIELD_REVISION_LINEATTACHMAKE_4CHID('%', '%', '', 'A')
    FIELD_REVISION_LINELINKMAKE_4CHID('%', '%', '', 'l')
    FIELD_REVISION_LINETRANSFERMAKE_4CHID('%', '%', '', 't')
    FIELD_MEMOMAKE_4CHID('%', '%', 'm', 'e')
    FIELD_PRIVATE_INFO_SECURITYMAKE_4CHID('%', 'c', 'p', 'r')
    FIELD_TABLEOFCONTENTSMAKE_4CHID('%', '', 'o', 'c')
    #4.3.10.1. 구역 정의

    Tag ID: MAKE_4CHID('s', 'e', 'c', 'd')

    표 129: 구역 정의

    자료형길이(바이트)설명
    UINT324속성(표 130 참조)
    HWPUNIT162동일한 페이지에서 서로 다른 단 사이의 간격
    HWPUNIT162세로로 줄맞춤을 할지 여부 (0=off, 1-n = 간격을 HWPUNIT 단위로 지정)
    HWPUNIT162가로로 줄맞춤을 할지 여부 (0=off, 1-n = 간격을 HWPUNIT 단위로 지정)
    HWPUNIT4기본 팁 간격(hwpunit 또는 relative characters)
    UINT162번호 문단 모양 ID
    UINT162쪽 번호 (0 = 앞 구역에 이어, n = 임의의 번호로 시작)
    UINT16 array[3]6그림, 표, 수식 번호 (0 = 앞 구역에 이어, n = 임의의 번호로 시작)
    UINT162대표Language(Language값이 없으면(==0), Application에 지정된 Language) 5.0.1.5 이상
    하위 레코드
    BYTE stream40용지설정 정보(표 131 참조)
    BYTE stream26각주 모양 정보(표 133 참조)
    BYTE stream26미주 모양 정보(표 133 참조)
    BYTE stream12쪽 테두리/배경 정보(표 135 참조)
    BYTE stream10양쪽, 홀수 쪽, 짝수 쪽의 바탕쪽 내용이 있으면 바탕쪽 정보를 얻는다. 바탕쪽 정보는 문단 리스트를 포함한다(표 137 참조)
    전체 길이140

    표 130: 구역 정의 속성

    범위설명
    bit 0머리말을 감출지 여부
    bit 1꼬리말을 감출지 여부
    bit 2바탕쪽을 감출지 여부
    bit 3테두리를 감출지 여부
    bit 4배경을 감출지 여부
    bit 5쪽 번호 위치를 감출지 여부
    bit 8구역의 첫 쪽에만 테두리 표시 여부
    bit 9구역의 첫 쪽에만 배경 표시 여부
    bit 16-18텍스트 방향(0: 가로, 1: 세로)
    bit 19빈출 감춤 여부
    bit 20-21구역 나눔으로 새 페이지가 생길 때의 페이지 번호 적용할지 여부
    bit 22원고지 정서법 적용 여부

    ####### 4.3.10.1.1. 용지 설정

    Tag ID: HWPTAG_PAGE_DEF

    표 131: 용지 설정

    자료형길이(바이트)설명
    HWPUNIT4용지 가로 크기
    HWPUNIT4용지 세로 크기
    HWPUNIT4용지 왼쪽 여백
    HWPUNIT4오른쪽 여백
    HWPUNIT4위 여백
    HWPUNIT4아래 여백
    HWPUNIT4머리말 여백
    HWPUNIT4꼬리말 여백
    HWPUNIT4제본 여백
    UINT324속성(표 132 참조)
    전체 길이40

    표 132: 용지 설정 속성

    범위구분값설명
    bit 0용지 방향0좁게
    1넓게
    bit 1-2제책 방법0한쪽 편집
    1맞쪽 편집
    2위로 넘기기

    ####### 4.3.10.1.2. 각주/미주 모양

    Tag ID: HWPTAG_FOOTNOTE_SHAPE

    표 133: 각주/미주 모양

    자료형길이(바이트)설명
    UINT324속성(표 134 참조)
    WCHAR2사용자 기호
    WCHAR2앞 장식 문자
    WCHAR2뒤 장식 문자
    UINT162시작 번호
    HWPUNIT162구분선 길이
    HWPUNIT162구분선 위 여백
    HWPUNIT162구분선 아래 여백
    HWPUNIT162주석 사이 여백
    UINT81구분선 종류(테두리/배경의 테두리 선 종류 참조)
    UINT81구분선 굵기(테두리/배경의 테두리 선 굵기 참조)
    COLORREF4구분선 색상(테두리/배경의 테두리 선 색상 참조)
    전체 길이26

    표 134: 각주/미주 모양 속성

    범위구분값설명
    bit 0-7번호 모양01, 2, 3
    1동그라미 쳐진 1, 2, 3
    2I, II, III
    3i, ii, iii
    4A, B, C
    5a, b, c
    6동그라미 쳐진 A, B, C
    7동그라미 쳐진 a, b, c
    8가, 나, 다
    9동그라미 쳐진 가, 나, 다
    10ㄱ, ㄴ, ㄷ
    11동그라미 쳐진 ㄱ, ㄴ, ㄷ
    12일, 이, 삼
    13一, 二, 三
    14동그라미 쳐진 一, 二, 三
    15갑, 을, 병, 정, 무, 기, 경, 신, 임, 계
    16甲, 乙, 丙, 丁, 戊, 己, 庚, 辛, 壬, 癸
    0x804가지 문자가 차례로 반복
    0x81사용자 지정 문자 반복
    bit 8-9한 페이지 내에서 각주를 다단에 위치시킬 방법0(각주인 경우) 각 단마다 따로 배열
    1(각주인 경우) 통단으로 배열
    2(각주인 경우) 가장 오른쪽 단에 배열
    0(미주인 경우) 문서의 마지막
    1(미주인 경우) 구역의 마지막
    bit 10-11numbering0앞 구역에 이어서
    1현재 구역부터 새로 시작
    2쪽마다 새로 시작(각주 전용)
    bit 12각주 내용 중 번호 코드의 모양을 위 첨자 형식으로 할지 여부
    bit 13텍스트에 이어 바로 출력할지 여부

    ####### 4.3.10.1.3. 쪽 테두리/배경

    Tag ID: HWPTAG_PAGE_BORDER_FILL

    표 135: 쪽 테두리/배경

    자료형길이(바이트)설명
    UINT4속성(표 136 참조)
    HWPUNIT162테두리/배경 위치 왼쪽 간격
    HWPUNIT162테두리/배경 위치 오른쪽 간격
    HWPUNIT162테두리/배경 위치 위쪽 간격
    HWPUNIT162테두리/배경 위치 아래쪽 간격
    UINT162테두리/배경 ID
    전체 길이12

    표 136: 쪽 테두리/배경 속성

    범위구분값설명
    bit 0위치 기준0본문 기준
    1종이 기준
    bit 1머리말 포함0미포함
    1포함
    bit 2꼬리말 포함0미포함
    1포함
    bit 3-4채울 영역0종이
    1쪽
    2테두리

    표 137: 바탕쪽 정보

    자료형길이(바이트)설명
    HWPUNIT4텍스트 영역의 폭
    HWPUNIT4텍스트 영역의 높이
    BYTE1각 비트가 해당 레벨의 텍스트에 대한 참조를 했는지 여부
    BYTE1각 비트가 해당 레벨의 번호에 대한 참조를 했는지 여부
    전체 길이10
    #4.3.10.2. 단 정의

    Tag ID: MAKE_4CHID('c', 'o', 'l', 'd')

    표 138: 단 정의

    자료형길이(바이트)설명
    UINT162속성의 bit 0-15(표 139 참조)
    HWPUNIT162단 사이 간격
    WORD array[cnt]2×cnt단 너비가 동일하지 않으면, 단의 개수만큼 단의 폭
    UINT162속성의 bit 16-31(표 139 참조)
    UINT81단 구분선 종류(테두리/배경의 테두리 선 종류 참조)
    UINT81단 구분선 굵기(테두리/배경의 테두리 선 굵기 참조)
    COLORREF4단 구분선 색상(테두리/배경의 테두리 선 색상 참조)
    전체 길이가변12 + (2×cnt) 바이트

    표 139: 단 정의 속성

    범위구분값설명
    bit 0-1단 종류0일반 다단
    1배분 다단
    2평행 다단
    bit 2-9단 개수(cnt)1-255
    bit 10-11단 방향 지정0왼쪽부터
    1오른쪽부터
    2맞쪽
    bit 12단 너비 동일하게 여부
    #4.3.10.3. 머리말/꼬리말

    Tag ID: MAKE_4CHID('h', 'e', 'a', 'd')

    문단 리스트를 포함한다.

    표 140: 머리말/꼬리말

    자료형길이(바이트)설명
    UINT324속성(표 141 참조)
    HWPUNIT4텍스트 영역의 폭
    HWPUNIT4텍스트 영역의 높이
    BYTE1각 비트가 해당 레벨의 텍스트에 대한 참조를 했는지 여부
    BYTE1각 비트가 해당 레벨의 번호에 대한 참조를 했는지 여부
    전체 길이14

    참고: 가변 길이 처리 / Note: Variable length handling

    스펙 문서에는 14바이트로 명시되어 있지만, 실제 파일에서는 가변 길이일 수 있습니다. 레거시 라이브러리들(libhwp, hwpjs.js)의 구현을 보면 다음과 같이 처리합니다:

    • libhwp: 레코드 헤더의 크기(header.size)와 현재까지 읽은 바이트 수(readAfterHeader)를 비교하여 가변 길이를 처리합니다.

      • applyPage (4바이트)는 항상 읽습니다.
      • if (!sr.isEndOfRecord()) 또는 if (sr.header.size > sr.readAfterHeader)로 체크하여 추가 필드를 읽습니다.
    • hwpjs.js: 주석에 "이때는 사이즈가 8로 아무것도 없음"이라고 명시되어 있어, 컨트롤 ID(4바이트) + 데이터(4바이트) = 8바이트인 경우도 있습니다.

    현재 구현의 가변 길이 처리 기준 / Current implementation's variable length handling criteria:

    • 최소 4바이트: applyPage (속성) 필수
    • 8바이트 이상: textWidth 읽기
    • 12바이트 이상: textHeight 읽기
    • 13바이트 이상: text_ref 읽기
    • 14바이트 이상: number_ref 읽기

    데이터가 없는 필드는 기본값(0)을 사용합니다.

    표 141: 머리말/꼬리말 속성

    범위구분값설명
    bit 0-1머리말이 적용될 범위(페이지 종류)0양쪽
    1짝수 쪽만
    2홀수 쪽만
    #4.3.10.4. 각주/미주

    Tag ID: MAKE_4CHID('f', 'o', 'o', 't')

    각주/미주는 문단 리스트 외에 속성을 갖지 않는다. 하지만 쓰레기 값이나 불필요한 업데이트를 줄이기 위해 8 byte를 serialize한다.

    참고: 실제 구현에서는 다음과 같이 구분하여 사용됩니다:

    • MAKE_4CHID('f', 'o', 'o', 't') = "foot" - 꼬리말 (Footer)
    • MAKE_4CHID('f', 'n', ' ', ' ') = "fn " - 각주 (Footnote, 공백 포함)
    • MAKE_4CHID('e', 'n', ' ', ' ') = "en " - 미주 (Endnote, 공백 포함)

    레거시 라이브러리들(pyhwp, ruby-hwp, hwplib)도 이 구분을 따릅니다.

    #4.3.10.5. 자동 번호

    Tag ID: MAKE_4CHID('a', 'u', 't', 'n')

    표 142: 자동 번호

    자료형길이(바이트)설명
    UINT324속성(표 143 참조)
    UINT162번호
    WCHAR2사용자 기호
    WCHAR2앞 장식 문자
    WCHAR2뒤 장식 문자
    전체 길이12

    표 143: 자동 번호 속성

    범위구분값설명
    bit 0-3번호 종류0쪽 번호
    1각주 번호
    2미주 번호
    3그림 번호
    4표 번호
    5수식 번호
    bit 4-11번호 모양표 134 참조
    bit 12superscript각주에서만 사용된다. 각주 내용 중 번호 코드의 모양을 위 첨자 형식으로 할지 여부.
    #4.3.10.6. 새 번호 지정

    Tag ID: MAKE_4CHID('n', 'e', 'w', 'n')

    표 144: 새 번호 지정

    자료형길이(바이트)설명
    UINT324속성
    - bit 0-3: 번호 종류(표 143 참조)
    UINT162번호
    전체 길이8
    #4.3.10.7. 감추기

    Tag ID: MAKE_4CHID('p', 'g', 'h', 'd')

    표 145: 감추기

    자료형길이(바이트)설명
    UINT2속성
    - 감출 대상
    - 0x00000001: 머리말
    - 0x00000002: 꼬리말
    - 0x00000004: 바탕쪽
    - 0x00000008: 테두리
    - 0x00000010: 배경
    - 0x00000020: 쪽 번호 위치
    전체 길이2
    #4.3.10.8. 홀/짝수 조정

    Tag ID: MAKE_4CHID('p', 'g', 'a', 'd')

    표 146: 홀/짝수 조정

    자료형길이(바이트)설명
    UINT324속성
    - bit 0-1: 홀/짝수 구분
    - 0: 양쪽
    - 1: 짝수 쪽
    - 2: 홀수 쪽
    전체 길이4
    #4.3.10.9. 쪽 번호 위치

    Tag ID: MAKE_4CHID('p', 'g', 'n', 'o')

    표 147: 쪽 번호 위치

    자료형길이(바이트)설명
    UINT324속성(표 148 참조)
    WCHAR2사용자 기호
    WCHAR2앞 장식 문자
    WCHAR2뒤 장식 문자
    WCHAR2항상 "-"
    전체 길이12

    표 148: 쪽 번호 위치 속성

    범위구분값설명
    bit 0-7번호 모양표 143 참조
    bit 8-11번호의 표시 위치0쪽 번호 없음
    1왼쪽 위
    2가운데 위
    3오른쪽 위
    4왼쪽 아래
    5가운데 아래
    6오른쪽 아래
    7바깥쪽 위
    8바깥쪽 아래
    9안쪽 위
    10안쪽 아래
    #4.3.10.10. 찾아보기 표식

    Tag ID: MAKE_4CHID('b', 'k', 'm', 'k')

    표 149: 찾아보기 표식

    자료형길이(바이트)설명
    WORD2키워드 길이(len1)
    WCHAR array[len1]2×len1찾아보기에 사용할 첫 번째 키워드
    WORD2키워드 길이(len2)
    WCHAR array[len2]2×len2찾아보기에 사용할 두 번째 키워드
    UINT162dummy
    전체 길이가변6 + (2×len1) + (2×len2) 바이트
    #4.3.10.11. 책갈피

    Tag ID: HWPTAG_CTRL_DATA

    책갈피 컨트롤은 '책갈피 이름'만 정보로 가지고 있으며, 임의의 컨트롤 데이터 HWPTAG_CTRL_DATA로 기록된다.

    #4.3.10.12. 글자 겹침

    Tag ID: MAKE_4CHID('o', 'v', 'e', 'r')

    표 150: 글자 겹침

    자료형길이(바이트)설명
    UINT324ctrl ID
    WORD2겹칠 글자 길이(len)
    WCHAR array[len]2×len겹칠 글자
    UINT81테두리 타입
    INT81내부 글자 크기
    UINT81테두리 내부 글자 펼침
    UINT81테두리 내부 글자 속성 아이디의 수 (cnt)
    UINT array[cnt]4×cnt테두리 내부 글자의 charshapeid 의 배열
    전체 길이가변10 + (2×len) + (4×cnt) 바이트
    #4.3.10.13. 덧말

    Tag ID: MAKE_4CHID('c', 'm', 't', 't')

    표 151: 덧말

    자료형길이(바이트)설명
    WORD2main Text 길이
    WCHAR2main Text
    WORD2sub Text 길이
    WCHAR2sub Text
    UINT4댓말의 위치
    - 0: 위
    - 1: 아래
    - 2: 가운데
    UINT4Fsizeratio
    UINT4Option
    UINT4Style number
    UINT4정렬 기준
    - 0: 양쪽 정렬
    - 1: 왼쪽 정렬
    - 2: 오른쪽 정렬
    - 3: 가운데 정렬
    - 4: 배분 정렬
    - 5: 나눔 정렬(공백에만 배분)
    전체 길이18
    #4.3.10.14. 숨은 설명

    Tag ID: MAKE_4CHID('h', 'i', 'd', 'e')

    문단 리스트만 포함한다. (숨은 설명 데이터는 문서 보안 수준에 따라 무효화될 수 있다.)

    #4.3.10.15. 필드 시작

    Tag ID: MAKE_4CHID('%', '%', '%', '%')

    표 152: 필드

    자료형길이(바이트)설명
    UINT324ctrl ID
    UINT4속성(표 153 참조)
    BYTE1기타 속성
    WORD2command 길이(len)
    WCHAR array[len]2×lencommand(각 필드 종류마다 처리해야할 고유 정보)
    UINT324id(문서 내 고유 아이디)
    전체 길이가변15 + (2×len) 바이트

    표 153: 필드 속성

    범위구분값설명
    bit 0읽기 전용 상태에서도 수정 가능한지 여부
    bit 11-14하이퍼링크 필드 업데이트 시 글자 속성 업데이트 종류0x1열어보지 않은 링크
    0x2열어본 링크
    0x4링크 생성
    bit 15필드 내용이 수정되었는지 여부

    #4.4. 문서 이력 관리

    문서 이력 관리에서 사용되는 데이터 레코드는 다음과 같다.

    #4.4.1. 문서 이력 관리란

    한글의 "문서 이력 관리 정보"는 한글 2005(버전 6.5.0.724)와 문서 형식 버전 Doc 5.0.1.7부터 지원된다.

    "파일 - 문서 이력 관리" 메뉴에서 표시되고 생성되는 문서 이력 정보가 저장되는 곳이다. 한글 2005부터 2007까지는 이 기능이 '버전 비교(파일 - 버전 비교)'라고 불렸다.

    문서 이력 정보의 각 항목은 "히스토리" 또는 "히스토리 아이템"이라고 불리며, 한글 Compound 구조 내부의 "DocHistory"라는 이름의 스토리지 안에 VersionLog%d(%d는 버전을 나타냄)라는 이름의 스트림으로 저장된다. 이 항목들은 압축되고 암호화된다.

    히스토리 정보 데이터는 "DocHistory"라는 새로운 스토리지에 저장된다.

    #4.4.2. 문서 이력 관리 레코드 정보
    #4.4.2.1. 히스토리 아이템 정보 시작

    Tag ID: HISTORY_RECORD_TYPE_STAG (0x10)

    표 154: 히스토리 아이템 정보 시작

    내용첨부 데이터 길이 및 Type
    히스토리 아이템 정보 시작WORD: flag
    UINT: option

    flag: 이 flag는 각 아이템에 포함된 레코드를 나타낸다:

    • HISTORY_INFO_FLAG_VERSION (0x01): Version 존재
    • HISTORY_INFO_FLAG_DATE (0x02): Date 존재
    • HISTORY_INFO_FLAG_WRITER (0x04): Writer 존재
    • HISTORY_INFO_FLAG_DESCRIPTION (0x08): Description 존재
    • HISTORY_INFO_FLAG_DIFFDATA (0x10): Diff Data 존재
    • HISTORY_INFO_FLAG_LASTDOCDATA: 최근 문서 존재 (기록되지 않음, 선택적)
    • HISTORY_INFO_FLAG_LOCK (0x40): 현재 History Item Lock 상태

    option: 버전 정보와 관련된 공통 옵션:

    • HWPVERSION_AUTOSAVE (0x00000001): 문서 저장 시 자동 저장
    #4.4.2.2. 히스토리 아이템 정보 끝

    Tag ID: HISTORY_RECORD_TYPE_ETAG (0x11)

    표 155: 히스토리 아이템 정보 끝

    내용첨부 데이터 Type
    히스토리 아이템 정보 끝NONE
    #4.4.2.3. 히스토리 아이템 버전

    Tag ID: HISTORY_RECORD_TYPE_VERSION (0x20)

    표 156: 히스토리 아이템 버전

    내용첨부 데이터 Type
    히스토리 아이템 버전DWORD
    #4.4.2.4. 히스토리 날짜

    Tag ID: HISTORY_RECORD_TYPE_DATE (0x21)

    표 157: 히스토리 날짜

    내용첨부 데이터 Type
    히스토리 날짜SYSTEMDATE
    #4.4.2.5. 히스토리 작성자

    Tag ID: HISTORY_RECORD_TYPE_WRITER (0x22)

    표 158: 히스토리 작성자

    내용첨부 데이터 Type
    히스토리 작성자WCHAR
    #4.4.2.6. 히스토리 설명

    Tag ID: HISTORY_RECORD_TYPE_DESCRIPTION (0x23)

    표 159: 히스토리 설명

    내용첨부 데이터 Type
    히스토리 설명WCHAR
    #4.4.2.7. 비교 정보

    Tag ID: HISTORY_RECORD_TYPE_DIFFDATA (0x30)

    표 160: 비교 정보

    내용첨부 데이터 Type
    비교 정보: DiffMLWCHAR
    #4.4.2.8. 가장 마지막 최근 문서

    Tag ID: HISTORY_RECORD_TYPE_LASTDOCDATA (0x31)

    표 161: 가장 마지막 최근 문서

    내용첨부 데이터 Type
    가장 마지막 최근 문서 (HWPML)WCHAR

    히스토리 아이템 저장 시 시작은 HISTORY_RECORD_TYPE_STAG 레코드로 시작하며, 아이템 내용의 끝은 HISTORY_RECORD_TYPE_ETAG 레코드로 종료한다.

    #변경 사항 이력

    revision 1.3: 20181108

    • 참고 문헌
    • 차트 개체
    • 동영상 개체
    • 그림 추가 속성
    • 파일 인식 정보 추가
    • 수식 개체 속성 추가
    • 글머리표 추가
    • 필드 컨트롤 ID 추가
    • 개체 공통 속성 수정
    • 문단번호 수정
    • 내용 중 일부 오타 수정

    revision 1.2: 20141009

    • 한글 문서 파일 구조 파트별로 구성
    • 5.0 일부 상세 내용 추가
    • 내용 중 일부 오타 수정
    • 3.0, HWPML 제외

    revision 1.1: 20110124

    • 저작권 내용 수정
    • 내용 중 일부 오타 수정

    revision 1.0: 20100701

    • 한글 문서 파일 형식 공개

    #한글 문서 파일 구조 5.0

    발행처 (주)한글과컴퓨터

    주소:

    • (우) 463-400
    • 경기도 성남시 분당구 대왕판교로
    • 644번길 49 한컴타워 10층
    • 전화: (031) 627-7000
    • 팩스: (031) 627-7709