LLM이 읽고 편집하는 Markdown 으로 바꾸고, 표·서식·양식을 그대로 보존한 채 다시 한글로 되돌립니다. 한글(HWP/HWPX) ⇄ Markdown 양방향 트랜스파일러 — 전부 브라우저 안에서, 파일 업로드 0.
.hwp / .hwpx 파일을 드래그하면 끝입니다.
한글(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 편집이 실제로 반영됩니다. 원본에서 실어 나른 스타일·줄높이·셀 너비·페이지 메타로 레이아웃을 복원 — 바이트 동일은 아니지만 표·서식을 재현합니다.
이게 열어주는 워크플로:
- 한글 문서를 LLM이 읽고 고칠 수 있는 깔끔한 Markdown으로 변환
- AI 에이전트에게 "시험평가 방법 섹션만 고쳐줘" (규칙 프롬프트는
docs/llm-edit-prompt.md) - 편집 모드로 다시
.hwpx복원 — 고친 곳만 바뀌고 나머지 양식은 재현.--edit-color를 켜면 AI가 고친 문단이 지정색으로 표시됩니다.
즉 "양식이 곧 규칙인" 공공·제안 문서를 AI로 편집하는 워크플로가 실제로 성립합니다. (경쟁 비교는 아래 비슷한 도구와 무엇이 다른가 참고.)
한글 파일을 마크다운/텍스트로 바꾸는 도구는 이미 많습니다. 하지만 국가과제 계획서, 사업계획서, 공공기관 제출 양식처럼 표가 많은 문서를 변환하면 거의 항상 이런 일이 벌어집니다.
- 표가 무너져서 어디가 라벨이고 어디가 값인지 알 수 없게 됨
- 병합된 셀이 사라짐
- 그림과 캡션의 연결이 끊어짐
- 다시 한글 파일로 되돌리는 게 불가능해짐
이 도구는 그 반대 방향을 노립니다. "예쁘게 평탄화"하지 않고, 표
구조·병합 셀·그림·캡션 관계를 그대로 보존한 채 마크다운으로
옮기고, 필요하면 다시 .hwpx 파일로 복원합니다.
브라우저에서 파일을 올리면 화면이 좌우로 갈라집니다.
- HTML — 이 프로젝트가 만든 깔끔한 구조형 미리보기
- 에디터 — 한컴 그대로의 화면 + 편집 UI (외부 라이브러리 임베드)
- Markdown — 지금 옵션대로 다운로드하면 어떤 마크다운이 나올지 실시간으로 보여줍니다
체크박스로 어떻게 변환할지 고를 수 있습니다.
- LLM 구조화 모드 — 각 섹션·문단·표·셀에 ID를 붙여서 같은 문서를 여러 번 변환해도 ID가 안 바뀜. LLM에 보내서 일부만 수정하거나 diff를 떠야 할 때 유용.
- role / editable 태그 — "이 셀은 라벨, 이 셀은 값, 이 셀은 수정 가능" 정보를 같이 출력.
- 도메인 힌트 — 자주 등장하는 표(기관 정보·예산표·일정표 등)에 자동으로 종류 라벨을 붙임.
- 인라인 스타일 — 굵게·기울임·취소선을
**bold**같은 마크다운 표기로 살릴지 평문으로 풀지. - 그림 처리 — 셋 중 선택:
텍스트만— 그림 자리에[FIGURE]마커만 남김 (가장 가벼움)인라인 base64— 그림까지 한 파일 안에 모두 담음분리— 본문.md+ 그림 모음.assets.md두 파일로 나눠서 LLM 컨텍스트 절약
- DPI 72 / 36 — 그림 해상도. 36으로 낮추면 파일 크기 절반.
→ .md 다운로드 또는 복사 버튼.
지금 보고 있는 문서를 .hwpx로 저장. 원본의 그림과 메타데이터가
그대로 보존됩니다.
왼쪽 HTML 미리보기를 그대로 정적 HTML 파일 또는 인쇄용 PDF로 저장.
.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 자동 해제), HWPXBinData/*둘 다 추출 → 마크다운 → HWPX 복원 시 동일 픽셀 - 레거시 포맷 자동 변환 — BMP/TIFF는 미리보기용 JPEG으로 자동 트랜스코딩 (브라우저가 못 띄우는 옛 포맷 대응)
- MIME 자동 결정
- 인라인 / 분리 모드 — 단일 자족
.md또는 본문+에셋 페어 선택 - DPI 72/36 리샘플 — LLM 컨텍스트 길이 절약 가능
- 안정적 ID —
sec-...,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/editoriframe 임베드로 한컴 그대로 - 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/editoriframe 임베드로 대체.
- 엔지니어링 히스토리, 기술 결정, 어떤 함정을 피했는지:
docs/PROJECT-HISTORY.md - 지금 상태(라이브 레퍼런스):
docs/memory/CURRENT.md - HWP5 바이너리 포맷 노트:
docs/memory/hwp5-spec-notes.md - 설계 결정 저널:
docs/journal/
미정 (TBD).