533 lines
32 KiB
Markdown
533 lines
32 KiB
Markdown
# dwg-dxf-viewer-sample
|
|
|
|
DWG/DXF 2D viewer module과 다중 포맷 3D viewer sample을 함께 관리하는
|
|
Three.js 기반 npm workspace입니다.
|
|
|
|
현재 구현은 파일을 브라우저에서 파싱하고 화면에 표시하는 기술 검증용입니다.
|
|
좌표, 단위, 원점, 형상 허용오차, topology와 CAD/BIM 의미 정보의 보존을
|
|
보장하는 운영용 engineering viewer로는 아직 검증되지 않았습니다.
|
|
|
|
## 검토 기준
|
|
|
|
| 항목 | 내용 |
|
|
|---|---|
|
|
| 기준일 | 2026-07-29 |
|
|
| 기준 commit | `cadbd5fb60d300dbb3fdc891fdbbabfbcd5b9109` |
|
|
| 기준 tree | 위 commit 이후 이 README 변경 포함 |
|
|
| 대상 | `kimminsung/dwg-dxf-viewer-sample` |
|
|
| 참조 | 형제 저장소 `hmwebviewer/README.md`의 분석 구조와 3D asset provenance |
|
|
| 검토 범위 | workspace 구조, 2D/3D 기능, source·test·build 설정, 입력 경계, npm dependency, WASM·font·decoder·fixture license |
|
|
| 기능 판정 | **내부 개발·기능 검증 정확도 및 품질 게이트 무시할 수 있으면 GO** |
|
|
| 외부 배포 판정 | **NO-GO — license·source 제공·asset provenance blocker 존재** |
|
|
|
|
외부 배포 판정은 기술적인 compliance 준비 상태를 뜻합니다. 법률 자문이 아니며,
|
|
실제 계약·특허·상표와 배포 승인은 조직의 법무·오픈소스 정책으로 확정해야 합니다.
|
|
업무용 프로젝트라기보다 취미용 개발 프로젝트에 가까운 성과물입니다.
|
|
|
|
## 현재 판정
|
|
|
|
운영 release에는 format별 정확도 contract, 3D 입력 제한·cancellation·Worker 격리,
|
|
프로젝트 license, MPL source 제공, third-party 고지와 sample provenance blocker가
|
|
남아 있습니다. 특히 “상업 사용 가능한 dependency”와 “현재 artifact를 조건 없이
|
|
상업 배포할 수 있음”은 같은 뜻이 아닙니다.
|
|
|
|
|
|
## Workspace 구성
|
|
|
|
| Workspace | 역할 | 주요 runtime |
|
|
|---|---|---|
|
|
| `apps/viewer-2d-sample` | DWG/DXF sample UI와 입력 정책 | `@hmwebviewer/viewer2d`, Three.js |
|
|
| `packages/viewer2d` | 재사용 가능한 2D parser·renderer module | `dxf-parser`, `opentype.js`, Three.js peer, acadrust WASM |
|
|
| `apps/viewer-3d` | 다중 포맷 3D static web application | Three.js, `web-ifc` |
|
|
|
|
```text
|
|
dwg-dxf-viewer-sample/
|
|
├─ apps/
|
|
│ ├─ viewer-2d-sample/ # 2D sample application
|
|
│ └─ viewer-3d/ # 3D sample application과 offline 도구
|
|
├─ packages/
|
|
│ └─ viewer2d/ # 2D public module
|
|
├─ tests/ # Vitest와 Playwright
|
|
├─ LICENSES/ # 현재 MPL-2.0, OFL-1.1 전문
|
|
├─ THIRD_PARTY_NOTICES.md
|
|
└─ docs/PROVENANCE.md
|
|
```
|
|
|
|
세 workspace는 `"private": true`이며 npm registry 배포용 package가 아닙니다.
|
|
`@hmwebviewer/viewer2d`의 export도 현재 TypeScript source를 직접 가리키므로,
|
|
독립 배포 package가 아니라 이 workspace 안에서 재사용하는 module입니다.
|
|
|
|
## 현재 제공 기능
|
|
|
|
### DWG/DXF 2D viewer
|
|
|
|
- `.dwg`, `.dxf` URL과 로컬 파일 load
|
|
- 파일 선택, Drag & Drop, `?model=<url>` 진입 경로
|
|
- DWG는 acadrust WebAssembly parser, DXF는 `dxf-parser`와 adapter 사용
|
|
- Three.js orthographic renderer와 pan·zoom
|
|
- Zoom Fit, dark/light theme, layer별 표시·숨김
|
|
- entity click 선택과 type·layer·handle 표시
|
|
- TEXT/MTEXT glyph용 NanumGothic TTF load
|
|
- module API의 grid, zoom speed, view-change 구독, entity/block 통계,
|
|
WebP snapshot, 2점 거리 측정, accent color
|
|
- page 종료 시 RAF, listener, WebGL resource와 canvas dispose
|
|
|
|
renderer에는 LINE, CIRCLE, ARC, ELLIPSE, POINT, POLYLINE/LWPOLYLINE,
|
|
SPLINE, TEXT/MTEXT/ATTRIB, INSERT, HATCH, DIMENSION, LEADER, XLINE/RAY 등
|
|
여러 entity 경로가 있습니다. 모든 DWG/DXF version과 entity 조합의 정확도를
|
|
보장한다는 의미는 아닙니다.
|
|
|
|
2D 입력 경계는 application layer에서 다음과 같이 제한합니다.
|
|
|
|
- URL은 HTTP(S)와 viewer 동일 origin만 허용
|
|
- `Content-Length`와 streaming 누적 크기를 모두 확인
|
|
- 로컬·URL 입력 최대 50 MiB
|
|
- URL fetch timeout 15초
|
|
|
|
### 다중 포맷 3D viewer
|
|
|
|
- `?model=<url>` server asset load와 로컬 Drag & Drop
|
|
- GLB, GLTF, OBJ, FBX, DAE, IFC, PLY load
|
|
- OBJ와 함께 드롭한 MTL 및 PNG/JPEG/BMP/GIF/WebP/TGA texture 연결
|
|
- 300 MiB 초과 OBJ의 2-pass streaming parser
|
|
- 큰 절대 좌표를 가진 OBJ의 float64 source 단계 재중심화
|
|
- Draco geometry와 KTX2/Basis texture runtime decode
|
|
- IFC single-thread WebAssembly parse와 geometry 변환
|
|
- PLY mesh·point cloud 처리 및 Float64 attribute의 Float32 정규화
|
|
- OrbitControls, Zoom Fit, 원근·직교 projection, outline 표시
|
|
- FPS overlay와 지속적인 저 FPS에서 pixel ratio를 낮추는 adaptive quality
|
|
- model URL과 이름이 같은 360° WebP preview를 먼저 표시한 뒤 canvas로 전환
|
|
- Vite `BASE_URL`을 따르는 decoder·preview 경로와 subpath 배포
|
|
- 교체 model의 geometry·material·texture와 Blob URL 정리
|
|
|
|
WebP preview는 미리 생성된 정적 파일입니다. Vite가 HTML shell을 제공한 뒤
|
|
브라우저에서 preview와 model을 load하므로 server-side 3D rendering 또는 SSR
|
|
구현은 없습니다.
|
|
|
|
## 실행 구조
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A["2D File / same-origin URL"] --> B["cadInputPolicy"]
|
|
B --> C["parseCad"]
|
|
C --> D["acadrust WASM<br/>DWG"]
|
|
C --> E["dxf-parser + adapter<br/>DXF"]
|
|
D --> F["CadParseResult"]
|
|
E --> F
|
|
F --> G["Viewer2D / Three.js"]
|
|
|
|
H["3D File / ?model URL"] --> I["ThreeDViewer"]
|
|
I --> J["modelLoader"]
|
|
J --> K["Three.js format loaders"]
|
|
J --> L["web-ifc JS + WASM"]
|
|
K --> M["THREE.Object3D"]
|
|
L --> M
|
|
M --> N["WebGLRenderer"]
|
|
```
|
|
|
|
2D application은 `packages/viewer2d` 내부 파일을 직접 import하지 않고
|
|
`@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`만 사용합니다.
|
|
|
|
## 지원 범위와 알려진 제한
|
|
|
|
### 2D
|
|
|
|
| 포맷 | URL | 로컬 파일 | 현재 검증과 제한 |
|
|
|---|---:|---:|---|
|
|
| DWG | 동일 origin 지원 | 지원 | `BasicSample.dwg` 1개 fixture 중심. acadrust WASM wrapper의 재현 build source가 없음 |
|
|
| DXF | 동일 origin 지원 | 지원 | `simple.dxf`와 public parser contract 검증. binary DXF 및 전체 entity fidelity 미검증 |
|
|
|
|
### 3D
|
|
|
|
| 포맷 | `?model` URL | 로컬 파일 | 알려진 제한 |
|
|
|---|---:|---:|---|
|
|
| GLB | 지원 | 지원 | Draco/KTX2 지원. 손실 압축 허용오차와 원본 대비 fidelity 기준 없음 |
|
|
| GLTF | 지원 | 제한적 | 로컬 `.bin`·texture sidecar를 함께 해석하는 file-set session 없음 |
|
|
| OBJ | 지원 | 지원 | URL 경로의 MTL 자동 load 없음. 로컬만 MTL·texture sidecar 지원 |
|
|
| OBJ > 300 MiB | 제한적 | 지원 | URL에는 size 기반 streaming 분기가 없음. 로컬 streaming path는 smooth normal과 MTL `Kd` color만 사용하고 texture·hard edge fidelity를 포기 |
|
|
| FBX | 지원 | 지원 | 축·단위·animation·외부 texture 보존 계약 없음 |
|
|
| DAE | 지원 | 제한적 | 로컬 외부 texture sidecar 미지원 |
|
|
| IFC | 지원 | 지원 | geometry와 color만 Three.js object로 변환. property/semantic API와 원점 이동 기록 미보존 |
|
|
| PLY | 지원 | 지원 | mesh 또는 point cloud. double attribute는 GPU용 Float32로 변환되어 정밀도 손실 가능 |
|
|
|
|
여기서 “지원”은 sample을 파싱해 renderable object를 만들 수 있다는 뜻입니다.
|
|
CAD/BIM 원본과의 좌표·단위·원점·topology·재질·속성 일치를 의미하지 않습니다.
|
|
|
|
## 신뢰 경계와 운영 위험
|
|
|
|
2D 경로는 same-origin, 50 MiB, 15초 제한을 적용하지만 magic bytes, MIME,
|
|
압축 해제 후 entity 수와 geometry 복잡도 quota는 없습니다.
|
|
|
|
3D `?model`은 URL scheme·origin·크기·timeout을 제한하지 않습니다. browser CORS가
|
|
허용하면 외부 origin도 요청할 수 있고, GLTF/DAE/FBX/OBJ가 참조하는 URI가 추가
|
|
network request를 만들 수 있습니다. 로컬 3D 파일에도 최대 크기와 decode 후
|
|
vertex·texture·memory quota가 없습니다.
|
|
|
|
두 viewer 모두 parser와 상당한 geometry 처리를 browser main thread에서 수행합니다.
|
|
운영 배포에는 format별 Worker 격리, URL allowlist, CSP, MIME·signature 검사,
|
|
streaming byte limit, decode complexity quota, timeout과 cancellation이 필요합니다.
|
|
|
|
동시에 여러 load를 시작했을 때 이전 요청을 취소하거나 latest-wins를 보장하는
|
|
session 규약도 없습니다. 느린 이전 요청이 나중 요청 뒤에 완료되어 화면을
|
|
덮을 수 있습니다.
|
|
|
|
현재 E2E는 sample render, finite vertex, canvas lifecycle과 subpath decoder URL을
|
|
검사합니다. 공식 validator, golden geometry, 좌표·단위 왕복, topology,
|
|
material·IFC property contract와 장시간 memory soak는 release gate에 없습니다.
|
|
|
|
## 외부 의존성·라이선스 감사
|
|
|
|
> **배포 준비 판정: 외부 demo·고객 전달·public CDN·commercial SaaS `NO-GO`,
|
|
> 조직 내부 개발·검증 조건부 `GO`**
|
|
>
|
|
> dependency 자체는 대부분 상업 사용 가능한 license이지만, 프로젝트 소유 코드의
|
|
> license, MPL source 제공, Apache/MIT 고지와 sample provenance가 완결되지 않았습니다.
|
|
|
|
감사 범위는 `package-lock.json`의 `node_modules/*` entry, 실제 browser bundle,
|
|
`public` 정적 파일, bundled WASM·font, sample과 파생 preview, repository가
|
|
호출하거나 언급하는 system tool입니다.
|
|
|
|
lockfile에는 142개 `node_modules/*` entry가 있습니다. 이 중 3개는 이 저장소의
|
|
workspace link이고 제3자 package는 139개입니다. 제3자 entry의 license metadata
|
|
누락은 0개입니다. runtime entry는 5개, build/dev entry는 134개이며 그중 57개는
|
|
platform별 optional package입니다.
|
|
|
|
### Browser runtime과 직접 배포되는 구성요소
|
|
|
|
| 구성요소 | 버전·출처 | 역할·배포 위치 | License | 현재 compliance 상태 |
|
|
|---|---|---|---|---|
|
|
| Three.js | `0.185.1` | 두 viewer의 JS bundle, loader·controls | MIT | package license는 확인. 배포 artifact에 통합 MIT notice 없음 |
|
|
| dxf-parser | `1.1.2` | DXF parser JS bundle | MIT | package license는 확인. 통합 notice 없음 |
|
|
| loglevel | `1.9.2`, `dxf-parser` transitive | DXF runtime logging | MIT | lockfile·package license 확인 |
|
|
| opentype.js | `2.0.0` | TTF glyph 처리 JS bundle | MIT | package license는 확인. 통합 notice 없음 |
|
|
| 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에 없음 |
|
|
|
|
저장소의 [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md)는 acadrust,
|
|
NanumGothic과 주요 runtime library를 기록하고, [`LICENSES/`](./LICENSES/)에는
|
|
MPL-2.0과 OFL-1.1 전문이 있습니다. 그러나 이 파일들은 두 Vite application의
|
|
`public` 아래에 있지 않아 현재 `npm run build` 결과에는 포함되지 않습니다.
|
|
|
|
### 전체 npm license 집계
|
|
|
|
| License | 제3자 package entry 수 | 주 사용 범위 | 상업 사용 | source 공개 영향 |
|
|
|---|---:|---|---:|---|
|
|
| MIT | 86 | runtime 4개와 build/dev | 가능 | 프로젝트 source 공개 의무 없음. copyright·license notice 보존 |
|
|
| Apache-2.0 | 31 | TypeScript, Playwright, Puppeteer와 platform package | 가능 | 프로젝트 source 공개 의무 없음. license·변경·NOTICE·patent 조건 적용 |
|
|
| MPL-2.0 | 13 | `web-ifc` runtime 1개, Lightning CSS 계열 dev 12개 | 가능 | 외부 executable 배포 시 covered source와 취득 안내 필요 |
|
|
| ISC | 6 | build/dev | 가능 | copyright·permission notice 보존 |
|
|
| BSD-3-Clause | 2 | build/dev | 가능 | notice·면책 보존, 이름을 홍보에 사용하지 않음 |
|
|
| 0BSD | 1 | optional build/dev | 가능 | source 공개와 attribution 의무 없음 |
|
|
|
|
위 집계에는 npm 밖의 acadrust WASM, NanumGothic, Draco, Basis와 sample asset
|
|
license가 포함되지 않습니다. `UNKNOWN` 3개처럼 보이는 lockfile entry는
|
|
`@hmwebviewer/*` first-party workspace link이며 제3자 license 누락이 아닙니다.
|
|
|
|
#### MPL-2.0 npm package 전체 목록
|
|
|
|
`package-lock.json`에서 `license: "MPL-2.0"`으로 선언된 13개 entry를 전부
|
|
나열하면 다음과 같습니다. 이는 **13개의 독립 codebase**를 의미하지 않습니다.
|
|
`web-ifc` 1개와, 동일한 Lightning CSS source에서 배포되는 core package 1개 및
|
|
platform별 optional native package 11개로 구성됩니다.
|
|
|
|
| npm package | Version | 설치·실행 범위 | 공식 source repository |
|
|
|---|---:|---|---|
|
|
| `web-ifc` | `0.0.77` | production runtime. IFC parser JS가 bundle되고 single-thread WASM이 application public asset으로 staging됨 | [ThatOpen/engine_web-ifc](https://github.com/ThatOpen/engine_web-ifc) |
|
|
| `lightningcss` | `1.33.0` | Vite build dependency. CSS parse·transform·minify core와 현재 platform용 native binding 선택 | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-android-arm64` | `1.33.0` | optional dev package, Android ARM64 native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-darwin-arm64` | `1.33.0` | optional dev package, macOS ARM64 native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-darwin-x64` | `1.33.0` | optional dev package, macOS x86_64 native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-freebsd-x64` | `1.33.0` | optional dev package, FreeBSD x86_64 native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-linux-arm-gnueabihf` | `1.33.0` | optional dev package, Linux ARM hard-float GNU native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-linux-arm64-gnu` | `1.33.0` | optional dev package, Linux ARM64 glibc native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-linux-arm64-musl` | `1.33.0` | optional dev package, Linux ARM64 musl native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-linux-x64-gnu` | `1.33.0` | optional dev package, Linux x86_64 glibc native binding. 현재 표준 container 대상 | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-linux-x64-musl` | `1.33.0` | optional dev package, Linux x86_64 musl native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-win32-arm64-msvc` | `1.33.0` | optional dev package, Windows ARM64 MSVC native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
| `lightningcss-win32-x64-msvc` | `1.33.0` | optional dev package, Windows x86_64 MSVC native binding | [parcel-bundler/lightningcss v1.33.0](https://github.com/parcel-bundler/lightningcss/tree/v1.33.0) |
|
|
|
|
Lightning CSS의 12개 entry는 모두 동일한 MPL-2.0 source tree와 release version을
|
|
가리키지만 lockfile 및 SBOM에서는 서로 다른 배포 package로 유지합니다. 실제 install
|
|
시 npm은 host OS·CPU·libc와 맞는 optional binding만 선택합니다. 이 project의
|
|
production browser artifact에는 Lightning CSS code가 포함되지 않지만, build
|
|
container 또는 `node_modules`를 제3자에게 전달한다면 선택된 binding과 covered
|
|
source 제공 방법을 함께 관리해야 합니다.
|
|
|
|
`web-ifc@0.0.77` package가 선언한 공식 repository는 위 root URL이며 package
|
|
metadata에는 exact source commit(`gitHead`)이 없습니다. 따라서 외부 배포 전에
|
|
registry tarball과 대응하는 source commit/archive를 별도로 고정하고, 수정 여부와
|
|
covered source 취득 방법을 배포 고지에 기록해야 합니다.
|
|
|
|
### Build·test·offline 도구
|
|
|
|
| 구성요소 | lockfile 기준 | 역할 | License·배포 판단 |
|
|
|---|---:|---|---|
|
|
| Vite | `8.1.5` | dev server와 production build | MIT. build output에는 runtime third-party notice를 별도로 넣어야 함 |
|
|
| TypeScript | `7.0.2` | typecheck | Apache-2.0. compiler를 고객에게 함께 전달하지 않으면 제품 source 공개 영향 없음 |
|
|
| Vitest | `4.1.10` | unit test | MIT, 제품 runtime 아님 |
|
|
| Playwright | `1.62.0` | browser E2E | Apache-2.0, 제품 runtime 아님 |
|
|
| Puppeteer Core | `25.4.0` resolved | 3D smoke·preview capture | Apache-2.0. Chrome binary를 포함하지 않음 |
|
|
| Lightning CSS | `1.33.0` 계열 12 entry | Vite build transitive | MPL-2.0. build host에서만 사용하며 browser runtime에는 포함되지 않음 |
|
|
| Node.js·npm | Node >=24, npm >=11 요구 | install, build, tool runtime | 함께 재배포하면 각 runtime과 bundled dependency license를 별도 감사 |
|
|
| Chrome | system executable | Playwright/Puppeteer 실행 | repository가 bundle하지 않음. CI image·설치형 배포에 포함하면 vendor 조건 별도 검토 |
|
|
| ffmpeg | optional, lockfile 밖 | PNG frame을 animated WebP로 결합 | binary를 bundle할 때 실제 build option의 LGPL/GPL/nonfree 조건 확인 |
|
|
| KTX-Software `toktx` | 도입 안내만 존재 | 선택적 KTX2 encoding | 현재 dependency가 아님. 도입 시 exact binary BOM과 license 재검토 |
|
|
|
|
`apps/viewer-3d/tools/preprocess.mjs`는 `@gltf-transform/core`,
|
|
`@gltf-transform/functions`, `@gltf-transform/extensions`, `draco3d`를 import하지만
|
|
현재 `package.json`과 lockfile에는 이 package들이 없습니다. 따라서 clean install의
|
|
정식 toolchain으로 재현되지 않습니다.
|
|
|
|
현재 script가 구현한 texture output은 WebP/JPEG/PNG이며 KTX2 encoding은 하지
|
|
않습니다. KTX2는 별도 glTF Transform CLI와 `toktx`가 필요합니다.
|
|
하위 `tools/README.md`의 “KTX2 default” 설명은 현재 code와 일치하지 않습니다.
|
|
|
|
### MPL·Apache·OFL 적용 범위
|
|
|
|
MPL-2.0은 file-level copyleft입니다. 별도 파일로 결합한 이 application 전체를
|
|
MPL로 공개할 필요는 없지만, 조직 밖으로 browser JS/WASM executable을 전달하면
|
|
수령자가 해당 MPL covered source와 수정분을 합리적인 방법으로 얻을 수 있게
|
|
알려야 합니다. browser로 전송되는 client code도 배포에 해당합니다.
|
|
|
|
- `web-ifc@0.0.77`: exact source archive 또는 고정 commit/tag URL과 수정 여부,
|
|
build 가능한 covered source 취득 안내가 필요
|
|
- acadrust DWG WASM: crate source만으로는 현재 binary wrapper를 재현할 수 없으므로
|
|
wrapper source·Cargo/wasm-bindgen 설정·toolchain을 복구하기 전 외부 배포 보류
|
|
- Lightning CSS: `node_modules`나 build container를 외부에 전달하지 않고 build
|
|
host에서만 실행하면 application source 공개 범위를 만들지 않음
|
|
|
|
Apache-2.0의 Draco와 Basis는 source 공개 의무는 없지만 license 사본, 기존
|
|
attribution과 upstream NOTICE, 수정 시 변경 고지를 보존해야 합니다. OFL font는
|
|
software와 bundle할 수 있지만 copyright와 OFL 전문을 함께 제공해야 하며,
|
|
Reserved Font Name 조건을 지켜야 합니다.
|
|
|
|
참조:
|
|
|
|
- [Mozilla MPL 2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/)
|
|
- [acadrust upstream](https://github.com/hakanaktt/acadrust)
|
|
- [web-ifc upstream](https://github.com/ThatOpen/engine_web-ifc)
|
|
- [Three.js r185 MIT license](https://github.com/mrdoob/three.js/blob/r185/LICENSE)
|
|
- [Google Draco Apache-2.0 license](https://github.com/google/draco/blob/main/LICENSE)
|
|
- [Basis Universal](https://github.com/BinomialLLC/basis_universal)
|
|
- [NanumGothic OFL](https://github.com/google/fonts/blob/main/ofl/nanumgothic/OFL.txt)
|
|
|
|
### Sample asset과 파생 preview
|
|
|
|
Sample과 preview는 software dependency license와 별개의 저작물입니다.
|
|
optimized model과 회전 preview도 원본 asset의 license·attribution·변경 표시를
|
|
계승해야 합니다.
|
|
|
|
| 자산 | 확인된 출처·license | 현재 판단 |
|
|
|---|---|---|
|
|
| `BasicSample.dwg` | 2D standalone initial commit에서 이관, 원출처 불명 | 내부 회귀 test 전용. 외부 demo 배포 보류 |
|
|
| `simple.dxf` | 2D standalone initial commit의 최소 fixture | 권리자·license 명시가 없어 외부 재배포 승인 필요 |
|
|
| `Box.glb` | Khronos sample, Cesium 제공, CC BY 4.0 | 상업 사용 가능하나 Cesium attribution, license link와 변경 여부 고지가 현재 배포물에 없음 |
|
|
| `Duck.glb` | Copyright 2006 Sony Computer Entertainment Inc., SCEA Shared Source License 1.0 | 비표준 license. 내부 법무 승인 전 외부 배포 보류 |
|
|
| `Duck.optimized.glb`, `Duck.webp` | Duck의 Draco/WebP·preview 파생물 | 원본 SCEA 승인과 derivative 변경 표시에 종속 |
|
|
| `Cube.obj`, `Cube.dae`, `Cube.ifc`, `DoublePrecision.ply` | 파일·commit에 hand-authored/project fixture 정황 | 프로젝트 권리자와 first-party license가 선언되지 않아 외부 배포 보류 |
|
|
| `Cube.fbx`, `sample.mtl` | history에는 Three.js `morph_test`와 Blender 정황만 있고 exact 원본 URL·asset license 없음 | provenance 복구 또는 제거 전 외부 배포 보류 |
|
|
| `Cube.*.webp` | 각 Cube model에서 생성한 24-frame preview | 원본 model의 권리·license와 변경 표시에 종속 |
|
|
|
|
Box와 Duck의 upstream license:
|
|
|
|
- [Khronos Box — CC BY 4.0](https://github.com/KhronosGroup/glTF-Sample-Models/blob/main/2.0/Box/README.md)
|
|
- [Khronos Duck — SCEA Shared Source License 1.0](https://github.com/KhronosGroup/glTF-Sample-Models/blob/main/2.0/Duck/README.md)
|
|
|
|
fixture checksum과 source history는 [`docs/PROVENANCE.md`](./docs/PROVENANCE.md),
|
|
acadrust·font checksum은 [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md)를
|
|
기준으로 관리합니다. 현재 provenance 문서는 2D fixture 중심이며 3D asset과
|
|
preview derivative chain은 아직 통합되지 않았습니다.
|
|
|
|
### 프로젝트 license와 외부 release gate
|
|
|
|
루트에는 프로젝트 소유 코드에 적용되는 `LICENSE`와 copyright holder 선언이
|
|
없습니다. `package.json`의 `"private": true`는 npm publish 방지 설정일 뿐
|
|
외부 이용·수정·재배포 권한을 부여하지 않습니다. 하위 과거 README의
|
|
“Viewer2D 포트·샘플 글루 MIT” 문구도 현재 repository의 license grant로 볼 수
|
|
없습니다.
|
|
|
|
다음 조건을 완료하기 전에는 외부 demo, 고객 전달, 설치형 package, public CDN과
|
|
commercial SaaS 배포를 승인하지 않습니다.
|
|
|
|
- 프로젝트 소유 코드의 권리자와 proprietary/open-source license 결정
|
|
- 2D·3D build artifact에 runtime `THIRD_PARTY_NOTICES`와 필요한 license 전문 포함
|
|
- acadrust wrapper source·toolchain 복구와 exact WASM 재현 build
|
|
- acadrust 및 `web-ifc@0.0.77` covered source의 고정 archive/URL과 취득 안내 제공
|
|
- Draco·Basis Apache license와 upstream NOTICE 보존
|
|
- 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
|
|
|
|
|
|
## 개발 스택 및 구성 정책
|
|
|
|
이 저장소의 표준 개발 대상은 **Linux x86_64 container**입니다. Windows host에서는
|
|
Docker Desktop 또는 WSL2를 container runtime 진입점으로만 사용하며, Windows drive
|
|
path와 host의 `node_modules`를 표준 build 입력으로 사용하지 않습니다.
|
|
|
|
| 구분 | 표준 stack | 구성 정책 |
|
|
|---|---|---|
|
|
| Host·container | Linux x86_64, glibc 기반 image | Chrome과 native npm package 호환성이 확인될 때까지 Debian/Ubuntu 계열을 기준으로 하며 Alpine/musl은 별도 검증 없이 사용하지 않음 |
|
|
| JavaScript runtime | Node.js 24 이상, npm 11 이상 | `package.json#engines`가 지원 하한이며 container와 CI에서는 24.x·11.x의 exact version 및 base image digest를 고정 |
|
|
| Package 관리 | npm workspaces, `package-lock.json` | clean environment는 `npm ci`만 사용하고 lockfile을 canonical dependency graph로 취급하며 host `node_modules`를 container에 mount하지 않음 |
|
|
| 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 절차로 사용하지 않음 |
|
|
| Optional asset tool | Puppeteer Core, ffmpeg, Blender, `toktx` | application build의 필수 dependency가 아니며 별도 asset-tool image/profile과 별도 license BOM으로 격리 |
|
|
|
|
공통 구성 원칙은 다음과 같습니다.
|
|
|
|
- tracked text file과 shell script는 LF를 사용하고 canonical command는 POSIX shell
|
|
문법과 repository-relative path로 작성합니다.
|
|
- development, production build, E2E, optional asset processing은 서로 다른
|
|
container target 또는 profile로 분리합니다. production artifact에 compiler,
|
|
browser, fixture와 asset tool을 포함하지 않습니다.
|
|
- container process는 non-root user로 실행하고 source는 read-only mount를
|
|
우선합니다. dependency cache와 build output만 별도 writable volume을 사용합니다.
|
|
- host에서 직접 실행할 때 Vite는 loopback에만 bind합니다. container에서 port를
|
|
publish할 때만 container 전용 설정으로 `0.0.0.0`에 bind하고 공개 network에
|
|
노출하지 않습니다.
|
|
- Node.js, npm, Chrome/Chromium과 base image는 floating tag가 아니라 exact
|
|
version으로 고정합니다. Renovate 같은 자동 갱신을 사용하더라도 `npm run verify`
|
|
통과 후에만 lock과 image pin을 갱신합니다.
|
|
- source build/test image와 외부 배포 artifact의 license·provenance gate는
|
|
동일하지 않습니다. 아래 `외부 의존성·라이선스 감사`의 `NO-GO` 항목을 container
|
|
전환만으로 해소된 것으로 간주하지 않습니다.
|
|
|
|
## Linux 컨테이너 전환 검증
|
|
|
|
2026-07-29 기준 installed dependency 상태에서 typecheck, unit test 6개와 production
|
|
build는 Linux/WSL2 x86_64에서 다시 통과했습니다. 기존 검증 기록의 Playwright E2E
|
|
16개 통과 결과는 있으나 이번 문서 변경에 대한 E2E 재실행은 요청에 따라 뒤로
|
|
미뤘습니다. tracked text file은 LF이며 lockfile에는 Linux glibc와 musl용 native
|
|
optional package가 포함되어 있습니다. 따라서 application code를 Windows 전용
|
|
구현에서 이식하는 작업은 거의 끝났지만, clean `npm ci`부터 시작하는 재현 가능한
|
|
container 개발 환경의 정의와 현재 E2E 재검증은 아직 완료되지 않았습니다.
|
|
|
|
| 항목 | 현재 상태 | container 전환 판단 |
|
|
|---|---|---|
|
|
| Container 정의 | Dockerfile, `.dockerignore`, Compose/devcontainer 없음 | **Blocker** — 동일 image를 개발·CI에서 재현할 수 없음 |
|
|
| Dev server network | 2D·3D Vite가 `127.0.0.1`에 고정 | **Blocker** — container port publish 후 host에서 접근할 별도 bind 설정 필요 |
|
|
| E2E browser | `/usr/bin/google-chrome`을 기본 경로로 가정 | **Blocker** — Chrome/Chromium과 shared library를 image에 설치·고정해야 함 |
|
|
| Native ABI | Linux glibc/musl package가 lockfile에 모두 존재 | **Decision** — 우선 glibc를 baseline으로 고정하고 musl은 별도 test matrix로 검증 |
|
|
| Clean container gate | 현재 container CI 없음 | **Blocker** — clean `npm ci && npm run verify`를 release gate로 추가해야 함 |
|
|
| File·path 규칙 | tracked text는 LF, runtime code는 Node path API 사용 | 통과. 단, 하위 2D README의 Windows drive path는 정리 필요 |
|
|
| Offline asset pipeline | ffmpeg·Blender·`toktx`가 core lockfile 밖에 있음 | core 개발은 통과. asset-tool image와 version/license pin은 후속 작업 |
|
|
|
|
권장 구현 순서는 다음과 같습니다.
|
|
|
|
1. Node.js 24 기반 glibc image의 digest와 non-root user를 고정한 multi-stage
|
|
Dockerfile 및 `.dockerignore`를 추가합니다.
|
|
2. host loopback 기본값은 유지하고 container script에서만 2D `5173`, 3D `3333`
|
|
port를 `0.0.0.0`에 bind합니다.
|
|
3. Chrome/Chromium과 필요한 Linux library를 포함한 E2E target을 만들고
|
|
`PLAYWRIGHT_CHROMIUM_EXECUTABLE`을 명시합니다.
|
|
4. container 안에서 `npm ci`, `npm run verify`를 수행하는 CI job을 추가하고
|
|
host `node_modules`가 섞이지 않는지 확인합니다.
|
|
5. ffmpeg·Blender·`toktx`가 필요한 3D asset pipeline은 별도 image/profile로
|
|
분리하고 core application image에는 포함하지 않습니다.
|
|
6. `apps/viewer-2d-sample/README.md`의 standalone Windows layout과 실행 명령을
|
|
현재 npm workspace 및 Linux container 기준으로 갱신합니다.
|
|
|
|
|
|
## 설치와 실행
|
|
|
|
요구 환경은 Node.js 24 이상, npm 11 이상과 WebGL을 지원하는 browser입니다.
|
|
|
|
```bash
|
|
npm ci
|
|
```
|
|
|
|
`npm ci`는 workspace dependency를 설치한 뒤 3D decoder와 WASM을 staging합니다.
|
|
|
|
```bash
|
|
npm run dev:2d
|
|
# http://127.0.0.1:5173
|
|
|
|
npm run dev:3d
|
|
# http://127.0.0.1:3333
|
|
```
|
|
|
|
URL load 예시:
|
|
|
|
```text
|
|
http://127.0.0.1:5173/?model=/samples/simple.dxf
|
|
http://127.0.0.1:3333/?model=/samples/Box.glb
|
|
```
|
|
|
|
Production build와 preview:
|
|
|
|
```bash
|
|
npm run build
|
|
npm --workspace @hmwebviewer/viewer-2d-sample run preview
|
|
npm --workspace @hmwebviewer/viewer-3d run preview
|
|
```
|
|
|
|
## 검증
|
|
|
|
```bash
|
|
npm run typecheck
|
|
npm run test:unit
|
|
npm run build
|
|
npm run test:e2e
|
|
```
|
|
|
|
전체 순차 검증:
|
|
|
|
```bash
|
|
npm run verify
|
|
```
|
|
|
|
2026-07-29 실제 검증 결과:
|
|
|
|
- workspace typecheck 통과
|
|
- Vitest 5개 file, 6개 test 통과
|
|
- 2D·3D production build 통과
|
|
- Playwright 16개 E2E 통과, 29.3초
|
|
- build 실패는 없지만 2D main bundle, Three.js, web-ifc와 decoder JS에
|
|
500 kB 초과 chunk 경고가 있음
|
|
|
|
현재 test가 확인하는 범위:
|
|
|
|
- 2D public package interface의 DXF parse
|
|
- 2D same-origin·50 MiB 입력 정책
|
|
- canonical module map 문서 drift
|
|
- decoder WASM의 installed dependency 대비 checksum과 실행 권한
|
|
- Vite subpath의 public asset URL
|
|
- 2D DWG/DXF sample과 local file load
|
|
- 3D GLB, Draco GLB, OBJ, FBX, DAE, IFC, PLY sample render
|
|
- 2D/3D canvas dispose와 반복 page transition
|
|
- production subpath의 Draco·IFC decoder request
|
|
- 2D DWG/DXF와 3D GLB/PLY evidence screenshot
|
|
|
|
이 검증은 sample이 화면에 나타나고 runtime error가 없다는 smoke/contract 수준입니다.
|
|
engineering 정확도와 외부 배포 compliance를 승인하는 test는 아닙니다.
|
|
|
|
## 문서
|
|
|
|
- [Third-party notices](./THIRD_PARTY_NOTICES.md)
|
|
- [Source와 fixture provenance](./docs/PROVENANCE.md)
|
|
- [DWG/DXF module map](./docs/modules-dwg-dxf.html)
|
|
- [2D sample 안내](./apps/viewer-2d-sample/README.md)
|
|
- [3D architecture](./apps/viewer-3d/docs/architecture.html)
|
|
- [3D 구현 계획](./apps/viewer-3d/PLAN.md)
|
|
- [3D 검증 기록](./apps/viewer-3d/PROGRESS.md)
|
|
- [3D asset 도구](./apps/viewer-3d/tools/README.md)
|
|
- [초기 3D 설계서](./apps/viewer-3d/3d_viewer_architecture_spec.pdf)
|
|
|
|
하위 2D README에는 통합 전 standalone layout이, 3D tools README에는 과거 KTX2
|
|
계획이 남아 있습니다. 현재 workspace의 canonical 개요와 배포 판단은 이 문서를
|
|
기준으로 하며, 하위 문서는 후속 정합성 정리가 필요합니다.
|