compose · don’t invent

DWG · DXF 모듈 조합 레시피

전체 제품이 아니라, 지도에 있는 재사용 모듈만 골라 조립하면 2D CAD 뷰어가 됩니다. 아래 카드 → 파이프라인 → 샘플 코드 순으로 옮기면 다른 프로젝트에서도 동일하게 동작합니다.

▶ 실행 샘플 · 이 프로젝트 루트 (npm run dev)

cd dwg-dxf-viewer-sample && npm i && npm run dev → http://localhost:5173

01 조합에 쓰는 모듈 (지도 카드)

WASM 파서 JS 모듈 · 렌더러
acadrust-dwg wasm
DWG 바이너리 → JSON parseResult. 외부 네트워크 없음.
src/viewer2d/acadrust-dwg/*.wasm (이 프로젝트)
dwgParser / acadrustParser wrap
WASM 1회 init + parseDwgBuffer(bytes).
dwgParser.ts · acadrustParser.ts
dxf-parser npm
DXF 텍스트 파싱 (MIT). HATCH 기본 미지원.
npm: dxf-parser
dxfHatchHandler patch
registerEntityHandler로 HATCH 보강.
dxfHatchHandler.js
dxfAdapter adapt
dxf-parser 출력 → Viewer2D 공통 스키마.
dxfAdapter.js
Viewer2D render
Orthographic three 씬. LINE/ARC/HATCH/TEXT/INSERT…
Viewer2D.js
three peer
WebGLRenderer + OrbitControls (pan/zoom).
npm: three ≥0.160
slugText + font text
opentype.js → GPU 텍스트. TTF를 호스트가 서빙.
slugText.ts · /fonts/*.ttf
ext2d util
isDwg / isDxf / is2D — 의존 zero.
ext2d.ts

02 조립 파이프라인

Host
File · URL · Drop
.dwg / .dxf
ext2d
isDwg / isDxf
분기
Parser A or B
acadrust · dxf-parser
(+ hatch · adapter)
Contract
CadParseResult
공통 JSON
Viewer2D
.load(result)
three 씬
핵심 계약: 파서는 파일을 안 열고, 렌더러는 바이트를 안 연다. 중간은 항상 CadParseResult 하나.

03 다른 프로젝트에 옮기는 순서

1

모듈 소스 복사

이 샘플의 src/viewer2d/ 전체를 복사. npm: three, dxf-parser, opentype.js. (원본 소스는 형제 폴더 hmwebviewer/src/viewer2d.)

2

정적 자산

public/fonts/NanumGothic-Regular.ttf (한글 TEXT). WASM은 소스가 ?url로 import — Vite면 assetsInclude: ['**/*.wasm'].

3

아래 스니펫처럼 조합

래퍼 클래스 없이 모듈을 직접 import 해도 됩니다. 실행 가능한 전체 예: 이 프로젝트 src/main.ts.

4

호스트 UI만 붙이기

드롭존 · 툴바 · 레이어 패널은 모듈이 아님. 샘플의 ⑤ 영역만 교체하면 디자인 시스템에 맞게 붙일 수 있음.

04 최소 조합 코드 (샘플과 동일 패턴)

// ① 모듈 지도 카드 → import
import { Viewer2D } from './viewer2d/Viewer2D.js';
import { parseDwgBuffer } from './viewer2d/dwgParser';       // acadrust-dwg
import { parseDxfBuffer } from './viewer2d/parseDxf';         // dxf-parser+hatch+adapter
import { isDwg, isDxf } from './viewer2d/ext2d';
import { setDefaultFontUrl } from './viewer2d/slugText';

setDefaultFontUrl('/fonts/NanumGothic-Regular.ttf');

// ② 렌더러
const viewer = new Viewer2D(document.getElementById('app')!);

// ③ 파서 조합
async function parseCad(buf: ArrayBuffer, name: string) {
  if (isDxf(name)) return parseDxfBuffer(buf);                 // dxf-parser 경로
  if (isDwg(name)) return parseDwgBuffer(new Uint8Array(buf)); // WASM 경로
  throw new Error('need .dwg or .dxf name');
}

// ④ 계약: parseResult → load
async function open(file: File) {
  const result = await parseCad(await file.arrayBuffer(), file.name);
  viewer.load(result);
  viewer.resize();
  viewer.fit();
}

05 DWG 경로 vs DXF 경로

.dwg 경로 wasm
parseDwgBuffer
→ acadrustParser.init
parse_dwg(bytes)
→ CadParseResult
Sample DWG 버튼으로 검증
.dxf 경로 js
parseDxfBuffer
→ decodeDxf (UTF-8 / CP949…)
→ DxfParser + HatchHandler
→ dxfToParseResult
Sample DXF 버튼으로 검증

06 샘플 위치

dwg-dxf-viewer-sample/   ← hmwebviewer 형제 폴더
  src/main.ts              ← 모듈을 직접 import 해서 조립 (핵심)
  src/viewer2d/            ← acadrust-dwg · Viewer2D · dxf-*
  index.html               ← 툴바 + Module recipe 패널
  public/fonts/            ← NanumGothic (slugText)
  public/samples/          ← BasicSample.dwg · simple.dxf
  docs/modules-dwg-dxf.html

실행
  cd ../dwg-dxf-viewer-sample   # (hmwebviewer 기준 형제)
  npm install
  npm run dev              → http://localhost:5173