Skip to content

zobithecat/ts-hwp-transpiler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

163 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ts-hwp-transpiler

LLM이 읽고 편집하는 Markdown 으로 바꾸고, 표·서식·양식을 그대로 보존한 채 다시 한글로 되돌립니다. 한글(HWP/HWPX) ⇄ Markdown 양방향 트랜스파일러 — 전부 브라우저 안에서, 파일 업로드 0.

.hwp / .hwpx 파일을 드래그하면 끝입니다.


🎯 우리가 해낸 것

LLM이 이해하고 편집하는 Markdown ↔ 서식을 보존한 한글 문서.

한글(HWP/HWPX) ⇄ Markdown 양방향 트랜스파일러.

핵심은 이겁니다: 한글 문서를 LLM이 읽고 고칠 수 있는 깔끔한 Markdown으로 바꾸고 — AI가 원하는 부분만 수정한 뒤 — 표·병합 셀·양식을 그대로 보존한 채 다시 .hwp/.hwpx로 되돌립니다.

기존 변환기는 "텍스트만 뽑고 서식을 버려서" 되돌리기가 불가능했습니다. 우리는 서식을 버리지 않는 양방향 트랜스파일러를 만들었고, 그 서식 보존이 진짜인지를 가장 엄격한 방법으로 증명했습니다:

무엇을 증명
서식 보존이 완벽한가 .hwpx → md → .hwpx 왕복이 한컴 원본과 컨테이너 15개 스트림 전부 byte-equal (1:1 동일)
실무 문서에서 되나 실제 37쪽 국가 R&D 계획서 · 표 62개 · 병합 셀 다수 · 이미지 4개로 검증
뭐가 보존되나 표·테두리·셀 음영·열 너비·문단 줄높이·페이지 여백·스타일 전부
실제로 똑같이 보이나 한컴 오피스 렌더가 원본과 육안 동일(사용자 검증)
어디서 도나 Rust → WebAssembly, 전부 브라우저 안에서, 업로드 0

즉 "byte-equal"은 자랑이 아니라 "우리가 서식을 정말 하나도 안 버린다"는 증거입니다. 이 무손실 기반 위에서 LLM 편집 워크플로가 성립합니다.


두 가지 모드 (용도에 따라)

① 아카이브 모드 (기본) — 바이트 단위 무손실

.hwpx → Markdown → .hwpx 왕복이, 한컴이 직접 만든 원본과 컨테이너 15개 스트림 전부 바이트 단위로 동일(byte-equal). 원본 섹션을 그대로 보존·재생하므로 완벽 무손실 — 대신 이 모드의 Markdown 은 읽기용 (본문 편집은 반영되지 않음).

② 편집 모드 (--editable / --edit-color / 웹앱 토글) — LLM 편집

각 섹션을 문단 레코드에서 재조립하므로 Markdown 편집이 실제로 반영됩니다. 원본에서 실어 나른 스타일·줄높이·셀 너비·페이지 메타로 레이아웃을 복원 — 바이트 동일은 아니지만 표·서식을 재현합니다.

이게 열어주는 워크플로:

  1. 한글 문서를 LLM이 읽고 고칠 수 있는 깔끔한 Markdown으로 변환
  2. AI 에이전트에게 "시험평가 방법 섹션만 고쳐줘" (규칙 프롬프트는 docs/llm-edit-prompt.md)
  3. 편집 모드로 다시 .hwpx 복원 — 고친 곳만 바뀌고 나머지 양식은 재현. --edit-color 를 켜면 AI가 고친 문단이 지정색으로 표시됩니다.

즉 "양식이 곧 규칙인" 공공·제안 문서를 AI로 편집하는 워크플로가 실제로 성립합니다. (경쟁 비교는 아래 비슷한 도구와 무엇이 다른가 참고.)


어떤 문제를 풉니까?

한글 파일을 마크다운/텍스트로 바꾸는 도구는 이미 많습니다. 하지만 국가과제 계획서, 사업계획서, 공공기관 제출 양식처럼 표가 많은 문서를 변환하면 거의 항상 이런 일이 벌어집니다.

  • 표가 무너져서 어디가 라벨이고 어디가 값인지 알 수 없게 됨
  • 병합된 셀이 사라짐
  • 그림과 캡션의 연결이 끊어짐
  • 다시 한글 파일로 되돌리는 게 불가능해짐

이 도구는 그 반대 방향을 노립니다. "예쁘게 평탄화"하지 않고, 표 구조·병합 셀·그림·캡션 관계를 그대로 보존한 채 마크다운으로 옮기고, 필요하면 다시 .hwpx 파일로 복원합니다.


데모에서 할 수 있는 것

브라우저에서 파일을 올리면 화면이 좌우로 갈라집니다.

왼쪽 — 미리보기 (탭 3개)

  • HTML — 이 프로젝트가 만든 깔끔한 구조형 미리보기
  • 에디터 — 한컴 그대로의 화면 + 편집 UI (외부 라이브러리 임베드)
  • Markdown — 지금 옵션대로 다운로드하면 어떤 마크다운이 나올지 실시간으로 보여줍니다

오른쪽 — 출력 옵션 + 다운로드

1. Markdown 출력

체크박스로 어떻게 변환할지 고를 수 있습니다.

  • LLM 구조화 모드 — 각 섹션·문단·표·셀에 ID를 붙여서 같은 문서를 여러 번 변환해도 ID가 안 바뀜. LLM에 보내서 일부만 수정하거나 diff를 떠야 할 때 유용.
  • role / editable 태그 — "이 셀은 라벨, 이 셀은 값, 이 셀은 수정 가능" 정보를 같이 출력.
  • 도메인 힌트 — 자주 등장하는 표(기관 정보·예산표·일정표 등)에 자동으로 종류 라벨을 붙임.
  • 인라인 스타일 — 굵게·기울임·취소선을 **bold** 같은 마크다운 표기로 살릴지 평문으로 풀지.
  • 그림 처리 — 셋 중 선택:
    • 텍스트만 — 그림 자리에 [FIGURE] 마커만 남김 (가장 가벼움)
    • 인라인 base64 — 그림까지 한 파일 안에 모두 담음
    • 분리 — 본문 .md + 그림 모음 .assets.md 두 파일로 나눠서 LLM 컨텍스트 절약
  • DPI 72 / 36 — 그림 해상도. 36으로 낮추면 파일 크기 절반.

.md 다운로드 또는 복사 버튼.

2. HWPX 다운로드

지금 보고 있는 문서를 .hwpx로 저장. 원본의 그림과 메타데이터가 그대로 보존됩니다.

3. HTML / PDF 다운로드

왼쪽 HTML 미리보기를 그대로 정적 HTML 파일 또는 인쇄용 PDF로 저장.

4. 마크다운 → 한글 (라운드트립)

.md 파일을 거꾸로 업로드하면 .hwpx로 다시 저장할 수 있습니다. "분리 모드"로 내보낸 .md + .assets.md 페어를 한 번에 같이 드래그하면 자동으로 짝이 맞춰집니다.


이런 분께 쓸모 있습니다

  • 공공기관·연구실 실무자 — 양식이 강한 한글 문서를 복사·붙여 넣지 않고 검색 가능한 텍스트로 만들고 싶을 때
  • LLM·AI 워크플로우 만드는 분 — 한글 문서를 GPT/Claude로 보내서 특정 셀만 수정하고, 결과를 다시 한글로 복원하는 흐름이 필요할 때
  • RAG 인덱스 만드는 분 — 본문을 의미 단위(섹션·표·셀)로 나누고 안정적인 ID를 부여해서 인용·근거 추적이 가능한 청크가 필요할 때
  • 문서 양식 자동화 — 사업계획서·예산표 같은 양식의 빈 셀만 채우거나, 변경된 셀만 diff 추적하고 싶을 때

어떻게 동작합니까?

브라우저 화면
   │
   ├─ Rust로 작성된 변환 엔진 → WebAssembly로 컴파일 → 브라우저에서 실행
   │     · 한글 파일을 직접 읽고 씁니다 (서버 거치지 않음)
   │     · 모르는 부분은 "원본 그대로 통과"시켜서 깨뜨리지 않습니다
   │
   └─ 픽셀 그대로의 한컴 화면이 필요할 때는 외부 에디터를 iframe으로 띄움

핵심 아이디어 한 줄: 모르는 영역을 버리지 않고 원본 그대로 보존하면서, 우리가 이해한 부분만 깔끔하게 다시 쓴다. 그 덕에 한 번 변환했다가 한글로 되돌렸을 때 그림·서식이 사라지지 않습니다.

(엔지니어링 세부는 docs/PROJECT-HISTORY.md 참고.)


한 줄 요약 비교

기존 변환기 이 도구
텍스트만 뽑고 표 구조는 버림 표·병합 셀·그림 관계까지 보존
한 방향(HWP → 텍스트)만 양방향 (HWP ↔ Markdown ↔ HWPX)
서버 업로드 필요한 경우 많음 브라우저 안에서 끝, 업로드 0
결과가 LLM이 보기엔 모호함 안정적 ID + role 태그로 LLM 친화

비슷한 도구와 무엇이 다른가

가장 가까운 오픈소스는 kordoc입니다. kordoc은 잘 만든 도구고, 읽을 수 있는 포맷(HWP3/5·HWPX·PDF·DOCX·XLS)이 우리보다 많습니다. 하지만 "문서를 어떻게 고치는가"의 접근이 근본적으로 다릅니다.

  • kordoc = 원본 파일 안에서 텍스트를 제자리 교체(in-place patch). 원본 XML의 기존 텍스트 런에 새 글자를 끼워 넣고, 나머지는 바이트 그대로 둡니다. 그래서 텍스트 치환에는 강하지만, 블록 추가·삭제나 표 구조 변경 같은 편집은 지원하지 않고 skipped[]로 보고합니다. LLM이 낼 수 있는 수정이 "원본에 이미 있는 런에 매핑되는 텍스트"로 제한됩니다.

  • 이 도구 = 문서 전체를 편집 가능한 시맨틱 Markdown으로 바꿨다가 다시 조립(full round-trip). LLM은 제자리 치환에 갇히지 않고 섹션·표·내용을 자유롭게 다시 쓸 수 있고, 그걸 다시 .hwpx로 복원하면 손대지 않은 부분은 원본과 바이트 단위로 동일합니다. 각 문단·셀엔 안정적 ID + 역할(label/value/header) + 도메인 힌트가 붙어 LLM/RAG에 최적화됩니다.

한 줄로: kordoc은 "원본을 조심스럽게 패치"하고, 우리는 "문서를 LLM이 자유롭게 편집한 뒤 원본 충실도로 재조립"합니다. 전자는 바꿀 수 있는 것이 텍스트로 제한되고, 후자는 문서 구조 전체가 편집 대상이 되면서도 무손실 왕복(byte-equal)이 성립한다는 점 — 이게 실제 37쪽 계획서로 검증된 차이입니다.

kordoc 이 도구
편집 모델 원본 XML 제자리 텍스트 패치 전체를 편집 가능한 Markdown으로 왕복
LLM이 할 수 있는 편집 텍스트 치환 (구조 변경은 skip) 텍스트 + 구조 자유 편집 후 재조립
무손실 안 건드린 ZIP 엔트리 바이트 보존 안 건드린 부분 스트림 15/15 byte-equal (실측)
시맨틱 레이어 파서/패처 중심 안정 ID · role · editable · 도메인 힌트
실행 Node CLI / MCP 서버 브라우저 안(Rust→WASM), 업로드 0

두 접근 다 "안 바꾼 부분 보존"은 잘합니다. 결정적 차이는 바꿀 수 있는 범위중간 표현이 LLM-native인가입니다.


로컬에서 돌려보고 싶다면

# 1. Rust → WebAssembly 컴파일 도구 설치
curl -sSf https://rustwasm.github.io/wasm-pack/installer/init.sh | sh

# 2. 데모 페이지 실행
cd ts
npm install
npm run build:wasm
npm run dev          # http://localhost:5173

명령줄에서 직접 변환하는 CLI도 있습니다:

cargo run -p hwp-transpiler-codec --bin hwp-to-md -- doc.hwp
cargo run -p hwp-transpiler-codec --bin md-to-hwpx -- doc.md

✅ 지금 되는 것

파일 입출력

  • .hwp 읽기·쓰기 — 옛날 한컴 바이너리 포맷. 우리가 안 건드린 영역은 원본 바이트 그대로 보존되어 round-trip 시 깨지지 않음.
  • .hwpx 읽기·쓰기 — 신형 ZIP+XML 포맷. 컨테이너 13개 stream byte-equal 라운드트립 달성 (mimetype, section, header, manifest, BinData, META-INF, Preview, settings, version 모두 동일 바이트).
  • .hwpx → md → .hwpx 레이아웃 충실 라운드트립 (한컴 검증) — 실 문서(37쪽, 표 62개, 이미지 4개)에서 한컴이 만든 원본 대비 15개 stream 중 14개 byte-equal(본문 section 포함), 한컴 오피스 렌더가 원본과 사실상 동일. 표 테두리·셀 음영·열 비율·문단 줄높이까지 보존.
  • .md 읽기·쓰기 — 우리가 정의한 마크다운 → .hwpx 양방향 변환. CLI + 웹 데모 둘 다 동작.

표·구조 보존

  • 병합 셀[r,c] span N×M: 표기로 손실 없이 보존
  • 표 안의 표 (중첩 표) — 정상 처리
  • wrapper 표 자동 정리 — 시각적 박스 용도의 1×1 표는 본문으로 풀어줌
  • 빈 셀 압축 — 같은 빈 셀이 연속되면 range로 묶어 가독성 ↑
  • 헤딩 자동 감지 — 한컴 스타일 이름 + 숫자 prefix("1.", "1.1.") 둘 다 인식해서 # ## ### 레벨 변환
  • 한컴 PUA 글머리표 정규화󰊱 같은 비표준 글머리를 ① ② 표준 기호로 자동 치환

그림 처리

  • 자동 추출 + 라운드트립 — HWP5 /BinData/* (DEFLATE 자동 해제), HWPX BinData/* 둘 다 추출 → 마크다운 → HWPX 복원 시 동일 픽셀
  • 레거시 포맷 자동 변환 — BMP/TIFF는 미리보기용 JPEG으로 자동 트랜스코딩 (브라우저가 못 띄우는 옛 포맷 대응)
  • MIME 자동 결정
  • 인라인 / 분리 모드 — 단일 자족 .md 또는 본문+에셋 페어 선택
  • DPI 72/36 리샘플 — LLM 컨텍스트 길이 절약 가능

LLM·AI 워크플로우

  • 안정적 IDsec-..., par-..., tbl-..., cell-..., fig-... 위치 기반이라 같은 문서 두 번 변환해도 ID 동일
  • role / editable 태그 — 라벨/값/수정 가능 여부 명시
  • 도메인 힌트 — 기관 정보·예산표·일정표 등 자주 등장하는 표 종류 자동 라벨링
  • 레코드 표기SECTION[...], PARAGRAPH[id=,level=], TABLE[...], CELL[...], FIGURE[...] 양방향 파싱

수식·서식

  • 수식 → LaTeX — HWP equation script를 토크나이즈해서 LaTeX로 출력 (마크다운·HTML 모두 적용)
  • 인라인 스타일**굵게**, *기울임*, ~~취소선~~ 라운드트립
  • DocInfo IR mutation — 정렬·글자 크기·색상·강조 같은 변경이 HWPX 출력에 반영됨 (안 건드린 영역은 verbatim 통과)

미리보기·데모

  • 구조형 HTML 뷰 — ParaShape 정렬·종횡비·인라인 그림 모두 반영, 의미 단위로 ID 부여
  • 픽셀 fidelity 뷰@rhwp/editor iframe 임베드로 한컴 그대로
  • 62MB+ 파일 처리 — handle-based registry로 큰 파일도 OK
  • PDF / HTML 다운로드

검증 통과 자료

  • TRL R&D 계획서 fixture (5MB, 표 53개, 그림 9개)
  • 실 사업계획서 HWPX (3MB, 그림 다수)
  • 라운드트립 + 모든 export 통과

❌ 아직 못 하는 것 (솔직하게)

  • 옛날 .hwp 파일로 직접 시작하는 라운드트립의 픽셀 충실도 — 표 테두리·문단 줄높이·셀 너비·스타일 테이블(itemCnt)까지는 복원되지만, .hwp 의 페이지 여백 정보(PAGE_DEF)를 아직 파싱하지 않아 본문 폭/페이지 흐름이 원본과 미세하게 다릅니다. 권장 우회: .hwp 는 한컴에서 한 번 .hwpx 로 저장한 뒤 hwpx ↔ md 로 편집·복원하세요 — 이 경로는 원본 헤더(여백·스타일·테두리)를 그대로 보존해 한컴 렌더가 원본과 사실상 동일합니다 (위 ✅ 참고).
  • 법조문 사용자 정의 스타일 (조·항·호) — IR로는 읽지만 마크다운 emit 측에서 스타일 이름이 빠져 라운드트립 시 본문 스타일로 떨어짐.
  • HWPX writer의 그라데이션·이미지 채우기 변경 — 단색 채우기만 IR로 노출, 그라데이션·이미지 fill 은 verbatim 통과만 가능 (읽고 쓸 수는 있지만 수정 불가).
  • 이미지 손실 압축 옵션 — 라운드트립 안전성 위해 일부러 미지원. 파일 크기는 DPI 36 옵션으로 절반.
  • 각주·변경 이력 마크다운 표면화 — 파일 안에는 verbatim 보존되어 HWPX 라운드트립은 OK 지만 마크다운 export 측에선 의미 단위로 surface 하지 않음.
  • 원본 페이지 픽셀 fidelity 자체 렌더러 — 의도적으로 안 만듭니다. 필요할 땐 @rhwp/editor iframe 임베드로 대체.

더 깊이 알고 싶다면

  • 엔지니어링 히스토리, 기술 결정, 어떤 함정을 피했는지: docs/PROJECT-HISTORY.md
  • 지금 상태(라이브 레퍼런스): docs/memory/CURRENT.md
  • HWP5 바이너리 포맷 노트: docs/memory/hwp5-spec-notes.md
  • 설계 결정 저널: docs/journal/

라이선스

미정 (TBD).

About

Bidirectional HWP/HWPX ↔ Markdown transpiler with browser-native preview (Rust + WASM).

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages