Silurus/ooxml: 브라우저에서 렌더링되는 픽셀 단위로 정확한 Office 문서
요약
Claude를 통해 100% 생성된 Rust 및 TypeScript 기반의 Office Open XML 뷰어 라이브러리입니다. 브라우저에서 DOCX, XLSX, PPTX 문서를 픽셀 단위로 정확하게 렌더링하며 WebAssembly를 활용합니다.
핵심 포인트
- Claude를 활용해 사람이 작성한 코드 없이 구현된 프로젝트
- Rust 파서와 WebAssembly를 통한 고성능 문서 처리
- Canvas 2D API 기반의 정밀한 브라우저 렌더링
- 헤드리스 엔진 지원으로 커스텀 UI 구성 가능
<p align="center"> <img src="docs/images/icon.png" alt="office-open-xml-viewer" width="160" height="160"> </p>이 코드베이스 전체 — Rust 파서 (parsers), TypeScript 렌더러 (renderers), 테스트, 그리고 툴링 (tooling) — 는 반복적인 프롬프팅 (prompting)을 통해 Claude (Anthropic의 AI 어시스턴트)에 의해 구현되었습니다. 이 저장소에는 사람이 작성한 애플리케이션 코드가 존재하지 않습니다.
office-open-xml-viewer
HTML Canvas 엘리먼트 (element)로 렌더링되는 Office Open XML 문서용 브라우저 기반 뷰어입니다.
파서 (parsers)는 Rust로 작성되어 WebAssembly로 컴파일되며, 렌더러 (renderers)는 Canvas 2D API를 사용합니다.
각 포맷은 또한 호출자가 제공하는 임의의 캔버스 (canvas)에 렌더링되는 헤드리스 엔진 (DocxDocument / XlsxWorkbook / PptxPresentation)을 노출하므로, 내장된 뷰어에 갇히지 않고 스크롤 뷰 (scroll views), 썸네일 그리드 (thumbnail grids), 마스터-디테일 창 (master-detail panes) 등 자신만의 UI를 구성할 수 있습니다. Storybook 데모의 Examples 섹션을 참조하세요.
| DOCX | XLSX | PPTX |
|---|---|---|
![]() | ![]() | ![]() |
npm install @silurus/ooxml
# 또는
pnpm add @silurus/ooxml
번들러 (Bundler) 참고 사항: 이 패키지는
.wasm파일을 포함하고 있습니다. Vite를 사용하는 경우vite-plugin-wasm을 추가하고, webpack을 사용하는 경우experiments.asyncWebAssembly를 사용하세요.
번들 크기 참고 사항: 이 패키지는 ESM 전용(
.mjs)입니다. npm의 Unpacked Size는 **선택 사항(opt-in)**인 수학 엔진(MathJax + STIX Two Math, ~3 MB)을 포함한 4개의 모든 엔트리 번들을 합산한 수치입니다. 실제로 앱에 포함되는 크기는 훨씬 작습니다. 필요한 형식만 임포트하세요 (예:@silurus/ooxml/pptx). 수학 엔진은 별도의 엔트리(@silurus/ooxml/math)입니다. 이 엔진은 사용자가 직접 임포트하여 뷰어(viewer)에 전달할 경우에만 번들에 포함됩니다 (수식 렌더링 참조).math엔진을 전달하면 수식이 렌더링되며, 전달하지 않으면 엔진이 어디에서도 참조되지 않으므로 번들러가 ~3 MB를 트리 쉐이킹(tree-shake)하여 완전히 제거합니다 (수식은 단순히 건너뛰어집니다). 이 엔진은 완전히 독립적입니다: 네트워크 통신이나 교차 출처(cross-origin) 요청이 필요하지 않습니다.
빠른 시작 (Quick Start)
import { DocxViewer } from '@silurus/ooxml/docx';
import { XlsxViewer } from '@silurus/ooxml/xlsx';
import { PptxViewer } from '@silurus/ooxml/pptx';
...
수식 렌더링 (Rendering equations)
.docx / .pptx 파일의 OMML 수식(m:oMath / m:oMathPara)은 MathJax + STIX Two Math를 사용하여 렌더링됩니다. 해당 엔진은 약 3 MB이므로 **선택 사항(opt-in)**으로 제공됩니다. 별도의 @silurus/ooxml/math 엔트리에서 math 엔진을 임포트하여 뷰어에 전달하십시오. 엔진을 전달하면 수식이 렌더링되지만, 전달하지 않으면 엔진이 어디에서도 참조되지 않으므로 번들러가 ~3 MB를 트리 쉐이킹(tree-shake)하여 완전히 제거합니다 (수식은 단순히 건너뛰어집니다). 이 엔진은 완전히 독립적입니다: 네트워크 통신이나 교차 출처(cross-origin) 요청이 필요하지 않습니다.
import { DocxViewer } from '@silurus/ooxml/docx';
import { math } from '@silurus/ooxml/math';
...
동일한 math 엔진은 PptxViewer 및 헤드리스(headless) DocxDocument / PptxPresentation API(옵션에서 math를 받음)에서도 작동합니다. xlsx는 수식 지원이 없으며 엔진을 참조하지 않습니다.
<details> <summary><strong>아키텍처 다이어그램 (Architecture diagram)</strong></summary>
flowchart TB
subgraph build["🦀 빌드 타임 (Build-time) (Rust → WebAssembly)"]
direction LR
...
세 가지 형식 모두 동일한 구조를 따릅니다: 워커(worker)가 WASM을 통해 .docx / .xlsx / .pptx 아카이브를 파싱(parse)하고, 메인 스레드(main thread)로 JSON 모델을 전달하면 렌더러(renderer)가 캔버스(canvas)에 그립니다. 렌더링은 메인 스레드에서 유지되어 캔버스가 문서의 FontFaceSet을 공유할 수 있습니다. 워커 내의 OffscreenCanvas는 자체적인 폰트 레지스트리(font registry)를 가지며, 설치된 테마 웹폰트(webfonts)와 미세하게 다른 텍스트 측정값(및 줄 바꿈 위치)을 생성하며 조용히 시스템 폰트로 폴백(fallback)하게 됩니다. @silurus/ooxml-core는 세 가지 렌더러가 모두 의존하는 교차 형식 프리미티브(cross-format primitives)를 보유하고 있습니다: 통합 차트 렌더러(막대 / 선 / 영역 / 레이더 / 폭포형), 도형 헬퍼(resolveFill, applyStroke, buildCustomPath, hexToRgba), autoResize 뷰어 유틸리티, 그리고 공유된 타입 정의(type definitions)입니다.
주요 파일
| 파일 | 역할 |
|---|---|
packages/docx/parser/src/lib.rs | Rust WASM 파서 — DOCX ZIP → Document JSON |
| ... |
프레임워크 예시 (Framework Examples)
<details> <summary><strong>React 19</strong></summary>// React 19.1 — vite.config.ts에 vite-plugin-wasm 필요
import { useEffect, useRef, useState } from 'react';
import { PptxViewer } from '@silurus/ooxml/pptx';
...
</details>
<details>
<summary><strong>Vue 3.5</strong></summary>
<!-- Vue 3.5 — useTemplateRef는 3.5+ 기능입니다 -->
<script setup lang="ts">
import { useTemplateRef, onMounted, ref } from 'vue';
...
</details>
<details>
<summary><strong>Angular 19</strong></summary>
// Angular 19 — 시그널(signal) 기반 상태를 사용하는 독립형 컴포넌트(standalone component)
import {
Component, ElementRef, viewChild,
...
</details> <details> <summary><strong>Svelte 5</strong></summary>Angular 워크스페이스에서
"allowSyntheticDefaultImports": true를 추가하고,@angular-builders/custom-webpack을 구성하거나(또는esbuild빌더를 사용) WASM 지원을 설정하세요.
<!-- Svelte 5 — 룬(runes) 구문 ($props, $state) -->
<script lang="ts">
import { onMount } from 'svelte';
...
</details>
<details>
<summary><strong>SolidJS 1.9</strong></summary>
// SolidJS 1.9
import { createSignal, onMount, onCleanup } from 'solid-js';
import { PptxViewer } from '@silurus/ooxml/pptx';
...
</details>
<details>
<summary><strong>Qwik 2</strong></summary>
// Qwik 2.0 — dynamic import to keep WASM out of SSR bundle
import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik';
import type { PptxViewer as PptxViewerType } from '@silurus/ooxml/pptx';
...
</details>
기능 지원 (Feature Support)
Word (.docx)
| 카테고리 | 기능 | 상태 |
|---|---|---|
| 문서 | 페이지 렌더링 | ✅ |
| ... |
Excel (.xlsx)
| 카테고리 | 기능 | 상태 |
|---|---|---|
| 통합 문서 | 여러 시트, 시트 이름 | ✅ |
| ... |
PowerPoint (.pptx)
| 카테고리 | 기능 | 상태 |
|---|---|---|
| 슬라이드 | 슬라이드 렌더링 | ✅ |
| ... |
텍스트 선택에 대한 참고 사항. DOCX / PPTX / XLSX 전반에 걸쳐, 텍스트 선택은 현재 글리프(glyph)를 캔버스에 렌더링하고 투명한 DOM 레이어를 오버레이하여 캔버스 텍스트 위치를 미러링함으로써 네이티브 브라우저 선택을 구현합니다. 이 이중 레이어 접근 방식은 의도적인 임시 방편입니다: 캔버스
drawElementAPI가 (WICG/html-in-canvas에서 제안되었으며, 현재 Chromium Origin Trial에 있음) 브라우저 전반으로 배포되면, 프로젝트는 캔버스가 DOM을 직접 미러링하는 단일 DOM-as-source-of-truth 파이프라인으로 마이그레이션할 계획이며 — z-order 정확도와 네이티브 선택/a11y를 유지하면서 중복을 제거합니다.
동반 패키지 (Companion packages)
동반 패키지 (Companion packages)
packages/markdown/—@silurus/ooxml-markdown및ooxml-mdCLI는 워크스페이스 WASM 파서(parsers)를 통해.pptx/.docx/.xlsx파일을 GitHub 스타일 마크다운(GitHub-flavoured markdown)으로 변환합니다. MCP 서버와 동일한 프로젝션(projection)을 사용합니다 (데모 슬라이드 기준 원본 XML보다 약 21배 작으며, 일반 텍스트 추출기보다는 약 8% 큽니다). 저장소 전체의 대량 변환을 위한 Node20 기반의 GitHub Action을 포함합니다.packages/node/— DOM이나 Web Worker 의존성 없이 워크스페이스 WASM 아티팩트(artifacts)를 대상으로parsePptx/parseDocx/parseXlsx/parseXlsxAllSheets를 노출하는 Node 측 파서(@silurus/ooxml-node)입니다. CI 체크, 헤드리스 렌더링 파이프라인(headless rendering pipelines), CLI 도구에 유용합니다.ooxml-thumbnailCLI를 포함합니다 (첫 번째 단계는 pptx 전용이며,skia-canvas가 필요합니다).packages/vscode-extension/—.docx,.xlsx,.pptx에 대한CustomEditorProvider를 등록하는 VS Code 확장 프로그램(ooxml-viewer)입니다. 또한 (선택 사항으로)ooxml-mcp-server를 자동 설치 및 등록하여, 동일한 창 내의 AI 코딩 에이전트(Copilot Agent 모드, Claude 등)가 전용 도구를 통해 해당 파일들을 읽을 수 있도록 합니다.packages/mcp-server/— AI 에이전트(Claude, Copilot, Codex 등)를 위해 파서를 도구(tools)로 노출하는 Rust 기반 MCP 서버(ooxml-mcp-server)입니다. 에이전트가unzip명령어를 실행하지 않고도 OOXML 파일을 검사할 수 있도록 구조화된 쿼리(docx_get_structure,xlsx_get_cell_range,pptx_get_slide_structure등)를 제공합니다. macOS / Linux / Windows용 사전 빌드된 바이너리가 각 GitHub Release에 첨부되어 있으며, VS Code 확장 프로그램이 필요할 때 이를 다운로드합니다.
개발 (Development)
# 의존성 설치
pnpm install
...
WASM 빌드 (개별 패키지)
cd packages/docx/parser && wasm-pack build --target web && cp pkg/docx_parser_bg.wasm pkg/docx_parser.js ../src/wasm/
cd packages/xlsx/parser && wasm-pack build --target web && cp pkg/xlsx_parser_bg.wasm pkg/xlsx_parser.js ../src/wasm/
cd packages/pptx/parser && wasm-pack build --target web && cp pkg/pptx_parser_bg.wasm pkg/pptx_parser.js ../src/wasm/
보안 및 개인 정보 보호 (Security & Privacy)
- Canvas 전용 렌더링. 문서는 디코딩되어
HTMLCanvasElement에 그려집니다. 소스 파일에서 스크립트, 링크, 폼 또는 기타 활성 콘텐츠는 실행되거나 DOM에 주입되지 않습니다. - ZIP 압축 해제 용량 제한 (cap). 소스 아카이브의 각 항목은 기본적으로 512 MiB의 압축 해제된 출력이 제한되어 zip-bomb DoS를 방지합니다.
maxZipEntryBytes(바이트)로 개별 뷰어에서 재정의할 수 있습니다. 이는 대용량 임베디드 미디어가 포함된 합법적인 프레젠테이션을 위해 값을 높이거나, 신뢰할 수 없는 입력에 대한 예산을 강화하기 위해 낮출 수 있습니다:new PptxViewer(canvas, { maxZipEntryBytes: 64 * 1024 * 1024 }); // 64 MiBDocxViewer,PptxViewer, 및XlsxViewer에서 통일적으로 지원됩니다. 0 또는 음수 값은 기본값으로 폴백(fallback)합니다. - 기본적으로 네트워크 사용 안 함. 이 라이브러리는 원격 측정(telemetry)이나 분석을 전송하지 않으며, 요청하지 않는 한 타사 서비스와 통신하지 않습니다. 특히, 테마 웹폰트(XLSX의 Office 폰트 메트릭 대체용)는 관련
Viewer/load(...)옵션에useGoogleFonts: true를 전달하지 않는 한 Google Fonts에서 로드되지 않습니다 — 이는DocxViewer,PptxViewer, 및XlsxViewer에서 통일적으로 지원됩니다. 이 옵션을 활성화하면 최종 사용자 브라우저가fonts.googleapis.com으로 HTTP 요청(IP 및 User-Agent)을 보내게 되며, 이는 귀하의 애플리케이션에 GDPR 영향을 미칠 수 있으므로 대신@font-face를 통해 필요한 폰트를 자체 호스팅하는 것을 고려하십시오. - XML 파싱. 외부 엔티티를 해결하지 않는
roxmltree를 사용합니다 (기본적으로 XXE-안전).
라이선스 (License)
MIT
AI 자동 생성 콘텐츠
본 콘텐츠는 HN AI Posts의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기

