perf: reduce 3D runtime artifacts (#7)

This commit is contained in:
2026-07-29 11:04:42 +09:00
parent fc2871ce4c
commit 0c656808e0
20 changed files with 148 additions and 309 deletions
+18 -13
View File
@@ -129,10 +129,10 @@ flowchart TD
`@hmwebviewer/viewer2d` public interface를 사용합니다. 3D `modelLoader`
확장자로 loader를 선택하고 결과를 `THREE.Object3D`로 정규화합니다.
`npm ci`의 root `postinstall`은 Three.js의 Draco·Basis 파일과 `web-ifc` WASM을
`apps/viewer-3d/public` 아래에 staging합니다. runtime에서는 설치된 Three.js와
동일한 decoder를 사용합니다. `web-ifc-mt.wasm`도 복사되지만 현재 code path는
single-thread `web-ifc.wasm`만 사용합니다.
Three.js의 Draco·Basis decoder는 loader import가 생성하는 version 일치 Vite
hashed asset을 사용합니다. `npm ci`의 root `postinstall`은 현재 code path가
사용하는 single-thread `web-ifc.wasm``apps/viewer-3d/public/web-ifc` 아래에
staging합니다. COOP/COEP가 필요한 `web-ifc-mt.wasm`은 배포하지 않습니다.
## 지원 범위와 알려진 제한
@@ -209,8 +209,8 @@ platform별 optional package입니다.
| acadrust | WASM 내부 `0.4.1` | `acadrust_dwg_bg.wasm`, DWG parse | MPL-2.0 | MPL 전문과 checksum은 있음. wrapper source·toolchain과 재현 build가 없음 |
| NanumGothic | Google Fonts 원본 checksum 일치 | `NanumGothic-Regular.ttf` | OFL-1.1 | 전문과 checksum은 있음. root license 파일이 app dist에는 자동 포함되지 않음 |
| web-ifc | `0.0.77` | dynamic JS bundle, `/web-ifc/*.wasm` | MPL-2.0 | package 전문은 확인. exact covered source 취득 안내가 배포물에 없음 |
| Draco decoder | Three.js r185 배포본 | `/draco/*.js`, `/draco/*.wasm` | Apache-2.0 | source와 byte-for-byte staging test 있음. Apache 전문·NOTICE가 app dist에 없음 |
| Basis Universal transcoder | Three.js r185 배포본 | `/basis/*.js`, `/basis/*.wasm` | Apache-2.0 | `basis/README.md`에 upstream link만 있음. Apache 전문·NOTICE가 app dist에 없음 |
| Draco decoder | Three.js r185 배포본 | Vite `/assets/draco_*` hashed asset | Apache-2.0 | 설치된 Three.js source에서 build. Apache 전문·NOTICE가 app dist에 없음 |
| Basis Universal transcoder | Three.js r185 배포본 | Vite `/assets/basis_*` hashed asset | Apache-2.0 | 설치된 Three.js source에서 build. Apache 전문·NOTICE가 app dist에 없음 |
저장소의 [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md)는 acadrust,
NanumGothic과 주요 runtime library를 기록하고, [`LICENSES/`](./LICENSES/)에는
@@ -366,7 +366,6 @@ commercial SaaS 배포를 승인하지 않습니다.
- Box attribution과 sample별 원본 URL·권리자·license·checksum·derivative chain 기록
- Duck의 내부 법무 승인 또는 승인된 CC0/CC BY asset으로 교체
- `BasicSample.dwg`, `Cube.fbx`, `sample.mtl` 등 출처 미완료 fixture의 승인 또는 제거
- 미사용 `web-ifc-mt.wasm`과 중복 decoder artifact의 배포 필요성 결정
- runtime/build/sample을 구분한 SBOM과 CI의 unknown-license/provenance gate
@@ -384,7 +383,7 @@ path와 host의 `node_modules`를 표준 build 입력으로 사용하지 않습
| Application | Vite 8, TypeScript 7, Three.js r185 | `apps/*`는 실행 application, `packages/*`는 workspace 내부 module로 유지하며 browser runtime asset은 Vite `BASE_URL`을 따름 |
| Unit·contract test | Vitest 4 | root `tests/**/*.test.ts`를 기준으로 하고 변경 시 관련 test부터 실행한 뒤 전체 suite를 실행 |
| Browser E2E | Playwright 1.62, system Chrome/Chromium | browser binary와 Linux system library를 E2E image에 고정하고 `PLAYWRIGHT_CHROMIUM_EXECUTABLE`로 경로를 주입 |
| Runtime decoder | acadrust DWG WASM, Draco, Basis, web-ifc | `npm ci``postinstall`로 설치 dependency와 version이 맞는 artifact를 staging하며 수동 복사를 canonical 절차로 사용하지 않음 |
| Runtime decoder | acadrust DWG WASM, Draco, Basis, web-ifc | Draco·Basis는 Three.js import의 hashed asset을 사용하고 `postinstall`은 single-thread `web-ifc.wasm`만 staging함 |
| Optional asset tool | Puppeteer Core, ffmpeg, Blender, `toktx` | application build의 필수 dependency가 아니며 별도 asset-tool image/profile과 별도 license BOM으로 격리 |
공통 구성 원칙은 다음과 같습니다.
@@ -408,7 +407,7 @@ path와 host의 `node_modules`를 표준 build 입력으로 사용하지 않습
## Linux 컨테이너 전환 검증
2026-07-29 기준 installed dependency 상태에서 typecheck, unit test 6개와 production
2026-07-29 기준 installed dependency 상태에서 typecheck, unit test 8개와 production
build는 Linux/WSL2 x86_64에서 다시 통과했습니다. 기존 검증 기록의 Playwright E2E
16개 통과 결과는 있으나 이번 문서 변경에 대한 E2E 재실행은 요청에 따라 뒤로
미뤘습니다. tracked text file은 LF이며 lockfile에는 Linux glibc와 musl용 native
@@ -450,7 +449,9 @@ container 개발 환경의 정의와 현재 E2E 재검증은 아직 완료되지
npm ci
```
`npm ci`는 workspace dependency를 설치한 뒤 3D decoder와 WASM을 staging합니다.
`npm ci`는 workspace dependency를 설치한 뒤 single-thread IFC WASM을 staging합니다.
Draco·Basis decoder는 production build가 설치된 Three.js에서 hashed asset으로
생성합니다.
```bash
npm run dev:2d
@@ -481,6 +482,7 @@ npm --workspace @hmwebviewer/viewer-3d run preview
npm run typecheck
npm run test:unit
npm run build
npm run test:artifact
npm run test:e2e
```
@@ -493,9 +495,11 @@ npm run verify
2026-07-29 실제 검증 결과:
- workspace typecheck 통과
- Vitest 5개 file, 6개 test 통과
- Vitest 5개 file, 8개 test 통과
- 2D·3D production build 통과
- Playwright 16개 E2E 통과, 29.3초
- production artifact gate 통과: 27개 file, 8,149,402 bytes, 50 kB 이상 중복 0개
- 3D `dist`는 경량화 전 24,945,531 bytes에서 16,796,129 bytes(67.3%) 감소
- Playwright 17개 E2E 통과, 21.9초
- build 실패는 없지만 2D main bundle, Three.js, web-ifc와 decoder JS에
500 kB 초과 chunk 경고가 있음
@@ -504,7 +508,8 @@ npm run verify
- 2D public package interface의 DXF parse
- 2D same-origin·50 MiB 입력 정책
- canonical module map 문서 drift
- decoder WASM의 installed dependency 대비 checksum과 실행 권한
- single-thread IFC WASM의 installed dependency 대비 checksum과 실행 권한
- production source map, MT IFC WASM, public decoder 중복과 9 MB artifact budget
- Vite subpath의 public asset URL
- 2D DWG/DXF sample과 local file load
- 3D GLB, Draco GLB, OBJ, FBX, DAE, IFC, PLY sample render