Linux container 전환과 함께 dependency graph와 production artifact를 경량화합니다. 동일 package의 복수 version은 호환성이 확인되는 범위에서 통합하고, source·build·runtime 어느 경로에서도 사용되지 않는 library와 정적 artifact는 제거합니다.
incompatible/optional transitive 중복은 강제 override하지 않고 근거를 comment에 기록
3D dist: 24,945,531 → 8,149,402 bytes(-67.3%)
2D dist: 4,302,677 bytes, 4.5 MB budget 추가
source map, public decoder 중복, multi-thread IFC WASM 제거
실제 Draco·Basis KTX2·IFC production subpath E2E 포함 npm run verify 통과
마일스톤
현재 저장소에 마일스톤이 없습니다. 본 이슈는 독립적으로 완료했으며, #8/#9를 묶을 경우 목표 Due Date가 있는 performance/compliance milestone 생성을 제안합니다.
> **Estimate Time: 8h**
## 배경
Linux container 전환과 함께 dependency graph와 production artifact를 경량화합니다. 동일 package의 복수 version은 호환성이 확인되는 범위에서 통합하고, source·build·runtime 어느 경로에서도 사용되지 않는 library와 정적 artifact는 제거합니다.
## 원칙
- browser 공개 동작과 지원 format은 변경하지 않음
- lockfile entry 수와 실제 install/runtime 포함 여부를 구분함
- build-time dependency를 browser runtime dependency로 오분류하지 않음
- transitive dependency는 강제 `overrides`보다 상위 package 갱신·npm dedupe를 우선함
- native optional package는 현재 Linux target 외 entry를 lockfile에서 임의 삭제하지 않음
- 제거마다 public artifact/dependency 계약 test를 먼저 RED로 확인함
## 범위
- [x] `package-lock.json`에서 동일 package의 복수 version과 원인을 전수 조사
- [x] direct dependency와 workspace version 선언 정합성 확인
- [x] source import, tool import, postinstall staging, production `dist`를 대조해 미사용 dependency/artifact 식별
- [x] 안전한 version 통합 및 미사용 dependency/artifact 제거
- [x] 2D·3D production artifact 전후 크기와 file 목록 비교
- [x] unit, typecheck, build, Playwright E2E 검증
- [x] README와 third-party/license 문서 영향 확인
## 완료 결과
- incompatible/optional transitive 중복은 강제 override하지 않고 근거를 comment에 기록
- 3D dist: 24,945,531 → 8,149,402 bytes(-67.3%)
- 2D dist: 4,302,677 bytes, 4.5 MB budget 추가
- source map, public decoder 중복, multi-thread IFC WASM 제거
- 실제 Draco·Basis KTX2·IFC production subpath E2E 포함 `npm run verify` 통과
## 마일스톤
현재 저장소에 마일스톤이 없습니다. 본 이슈는 독립적으로 완료했으며, #8/#9를 묶을 경우 목표 Due Date가 있는 performance/compliance milestone 생성을 제안합니다.
npm find-dupes와 npm dedupe --dry-run에서 안전한 hoist/dedupe 변경이 나오지 않았습니다. 따라서 이번 이슈에서는 강제 overrides를 추가하지 않습니다. direct runtime의 Three.js는 모든 workspace에서 0.185.1로 이미 통일되어 있습니다.
미사용·중복 production artifact
현재 3D dist 약 24 MiB 중 다음 절감 후보를 확인했습니다.
production source map: 14,132,113 bytes
사용하지 않는 web-ifc-mt.wasm: 1,314,227 bytes
Three.js import가 생성한 hashed decoder와 public/draco, public/basis 복사본의 byte-for-byte 중복: 최소 835,738 bytes, public decoder directory 전체 약 1.35 MiB
web-ifc code path는 명시적으로 single-thread WASM만 초기화합니다. Draco/Basis는 Three.js r185 loader가 자체 new URL(..., import.meta.url) asset을 제공하므로 public 복사본 대신 Vite hashed asset을 사용할 수 있습니다.
RED→GREEN 순서
single-thread IFC staging 계약 test를 RED로 추가하고 MT WASM 제거
public decoder 중복 금지 계약 test를 RED로 추가하고 Three.js bundled decoder URL로 전환
production artifact checker를 먼저 현재 dist에 실행해 RED 확인 후 source map 비활성화와 size/file gate 추가
unit → typecheck → build/artifact gate → E2E 순으로 검증
Puppeteer Core는 여러 offline smoke/prerender 도구에서 실제 사용하므로 제거하지 않습니다.
## 감사 결과 및 구현 계획
### 동일 package 복수 version
lockfile에서 복수 version은 5종입니다.
- `string-width` `7.2.0` / `8.2.2`: Puppeteer의 `yargs`와 `cliui`가 서로 다른 major range를 요구
- `fsevents` `2.3.2` / `2.3.3`: Playwright와 Vite가 요구하는 macOS 전용 optional package이며 Linux에는 설치되지 않음
- `@emnapi/core`, `@emnapi/runtime`, `@emnapi/wasi-threads`: Rolldown WASI fallback의 `1.x`와 N-API WASM runtime의 `2.0 alpha` peer가 공존하며 현재 Linux x64 native build에는 설치되지 않음
`npm find-dupes`와 `npm dedupe --dry-run`에서 안전한 hoist/dedupe 변경이 나오지 않았습니다. 따라서 이번 이슈에서는 강제 `overrides`를 추가하지 않습니다. direct runtime의 Three.js는 모든 workspace에서 `0.185.1`로 이미 통일되어 있습니다.
### 미사용·중복 production artifact
현재 3D `dist` 약 24 MiB 중 다음 절감 후보를 확인했습니다.
1. production source map: 14,132,113 bytes
2. 사용하지 않는 `web-ifc-mt.wasm`: 1,314,227 bytes
3. Three.js import가 생성한 hashed decoder와 `public/draco`, `public/basis` 복사본의 byte-for-byte 중복: 최소 835,738 bytes, public decoder directory 전체 약 1.35 MiB
`web-ifc` code path는 명시적으로 single-thread WASM만 초기화합니다. Draco/Basis는 Three.js r185 loader가 자체 `new URL(..., import.meta.url)` asset을 제공하므로 public 복사본 대신 Vite hashed asset을 사용할 수 있습니다.
### RED→GREEN 순서
1. single-thread IFC staging 계약 test를 RED로 추가하고 MT WASM 제거
2. public decoder 중복 금지 계약 test를 RED로 추가하고 Three.js bundled decoder URL로 전환
3. production artifact checker를 먼저 현재 `dist`에 실행해 RED 확인 후 source map 비활성화와 size/file gate 추가
4. unit → typecheck → build/artifact gate → E2E 순으로 검증
Puppeteer Core는 여러 offline smoke/prerender 도구에서 실제 사용하므로 제거하지 않습니다.
incompatible/optional transitive duplicate 5종(@emnapi/*, fsevents, string-width)은 npm find-dupes/dry-run dedupe 결과 안전한 통합 경로가 없어 override하지 않음
lightningcss-* platform package는 lockfile의 optional compatibility metadata이며 Linux x64 clean install에는 해당 binding만 설치됨. production browser artifact에는 포함되지 않음
첫 전체 verify의 3D subpath 실패는 fixture route glob이 ?model=...gltf를 포함한 메인 document까지 가로챈 test harness 문제였습니다. 실제 pathname만 일치하도록 route 정규식을 제한한 뒤 targeted E2E는 1 passed로 복구했습니다. 최종 전체 verify 결과를 이어서 기록하겠습니다.
## RED→GREEN 및 리뷰 보완 기록
### 실제 RED 확인
1. `tests/decoder-staging.test.ts`에 single-thread IFC staging 요구사항 추가 → 기존 `public/web-ifc/web-ifc-mt.wasm` 때문에 실패 확인
2. public Draco/Basis 복사본 배제 요구사항 추가 → 기존 `public/draco`, `public/basis` 때문에 실패 확인
3. production artifact gate 초안 실행 → source map, decoder 중복, MT IFC WASM, 9 MB 초과로 실패 확인
4. production subpath E2E를 hashed Draco 경로로 변경 → 기존 `/viewer-3d/draco/` assertion 실패 확인
5. KTX2/Basis 실제 decode E2E 추가 → fixture 부재로 model-ready timeout 실패 확인
### 구현 및 GREEN
- Three.js loader import가 생성하는 hashed Draco/Basis JS·WASM으로 통합
- `postinstall`은 single-thread `web-ifc.wasm`만 staging하고 stale MT 파일 제거
- production source map, `public/draco`, `public/basis`, `web-ifc-mt.wasm` 제거
- 2D/3D artifact gate 추가
- 2D: 4.5 MB budget, source map/50 kB 이상 중복/필수 acadrust WASM 검사
- 3D: 9 MB budget, source map/decoder 중복/MT IFC/필수 Draco·Basis·IFC WASM 검사
- Three.js 고정 commit의 966-byte ETC1S KTX2를 E2E 전용 fixture로 추가하고 production artifact에는 미포함
- production subpath에서 `basis_transcoder-*.wasm` request와 model-ready를 확인하는 E2E 통과
### 측정 결과
- 2D dist: 8 files, 4,302,677 bytes, duplicate 0
- 3D dist: 24,945,531 → 8,149,402 bytes (-16,796,129 bytes, -67.3%), 27 files, duplicate 0
- incompatible/optional transitive duplicate 5종(`@emnapi/*`, `fsevents`, `string-width`)은 `npm find-dupes`/dry-run dedupe 결과 안전한 통합 경로가 없어 override하지 않음
- `lightningcss-*` platform package는 lockfile의 optional compatibility metadata이며 Linux x64 clean install에는 해당 binding만 설치됨. production browser artifact에는 포함되지 않음
첫 전체 verify의 3D subpath 실패는 fixture route glob이 `?model=...gltf`를 포함한 메인 document까지 가로챈 test harness 문제였습니다. 실제 pathname만 일치하도록 route 정규식을 제한한 뒤 targeted E2E는 1 passed로 복구했습니다. 최종 전체 verify 결과를 이어서 기록하겠습니다.
KTX2 production subpath case에서 basis_transcoder-*.wasm 실제 request 및 model-ready 확인
커밋:
0c65680 perf: reduce 3D runtime artifacts (#7)
49d6b0e test: verify bundled decoders and artifact budgets (#7)
500 kB 초과 chunk warning은 남지만 build/test 실패가 아니며, 동적 import나 web-ifc 분할 최적화는 별도 성능 범위로 취급합니다. standards 재검토는 Blocker 없이 통과했고, spec 재검토 후 Blocker가 없으면 이슈를 완료 상태로 닫겠습니다.
## 최종 연속 검증
`npm run verify` 전체 통과:
- workspace typecheck: 통과
- Vitest: 5 files, 8 tests 통과
- 2D/3D production build: 통과
- artifact gate:
- 2D 8 files / 4,302,677 bytes / duplicate 0
- 3D 27 files / 8,149,402 bytes / duplicate 0
- Playwright: 17 tests 통과 / 24.5초
- KTX2 production subpath case에서 `basis_transcoder-*.wasm` 실제 request 및 model-ready 확인
커밋:
- `0c65680 perf: reduce 3D runtime artifacts (#7)`
- `49d6b0e test: verify bundled decoders and artifact budgets (#7)`
500 kB 초과 chunk warning은 남지만 build/test 실패가 아니며, 동적 import나 web-ifc 분할 최적화는 별도 성능 범위로 취급합니다. standards 재검토는 Blocker 없이 통과했고, spec 재검토 후 Blocker가 없으면 이슈를 완료 상태로 닫겠습니다.
현재 repository에는 milestone이 없어 연결하지 않았습니다. #8/#9의 목표 일정이 정해지면 due date가 있는 performance/compliance milestone 생성을 제안합니다.
완료 조건과 전체 검증이 충족되어 #7을 완료 상태로 닫습니다.
## 리뷰 판정 및 종료
- standards review: 이전 5개 finding 해소, 새 Blocker 0
- spec review: KTX2 실제 decode, 2D artifact guard, RED→GREEN 기록, Draco/Basis notice 해소, 새 Blocker 0
- `git diff --check`: 통과
- worktree: clean
Scope-out은 이 이슈를 확장하지 않고 분리했습니다.
- #8 — 500 kB 초과 runtime chunk의 지연 로드·분할 검증
- #9 — application dist에 third-party license·NOTICE 자동 포함
- clean container 재현성은 기존 #6 범위
현재 repository에는 milestone이 없어 연결하지 않았습니다. #8/#9의 목표 일정이 정해지면 due date가 있는 performance/compliance milestone 생성을 제안합니다.
완료 조건과 전체 검증이 충족되어 #7을 완료 상태로 닫습니다.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
배경
Linux container 전환과 함께 dependency graph와 production artifact를 경량화합니다. 동일 package의 복수 version은 호환성이 확인되는 범위에서 통합하고, source·build·runtime 어느 경로에서도 사용되지 않는 library와 정적 artifact는 제거합니다.
원칙
overrides보다 상위 package 갱신·npm dedupe를 우선함범위
package-lock.json에서 동일 package의 복수 version과 원인을 전수 조사dist를 대조해 미사용 dependency/artifact 식별완료 결과
npm run verify통과마일스톤
현재 저장소에 마일스톤이 없습니다. 본 이슈는 독립적으로 완료했으며, #8/#9를 묶을 경우 목표 Due Date가 있는 performance/compliance milestone 생성을 제안합니다.
감사 결과 및 구현 계획
동일 package 복수 version
lockfile에서 복수 version은 5종입니다.
string-width7.2.0/8.2.2: Puppeteer의yargs와cliui가 서로 다른 major range를 요구fsevents2.3.2/2.3.3: Playwright와 Vite가 요구하는 macOS 전용 optional package이며 Linux에는 설치되지 않음@emnapi/core,@emnapi/runtime,@emnapi/wasi-threads: Rolldown WASI fallback의1.x와 N-API WASM runtime의2.0 alphapeer가 공존하며 현재 Linux x64 native build에는 설치되지 않음npm find-dupes와npm dedupe --dry-run에서 안전한 hoist/dedupe 변경이 나오지 않았습니다. 따라서 이번 이슈에서는 강제overrides를 추가하지 않습니다. direct runtime의 Three.js는 모든 workspace에서0.185.1로 이미 통일되어 있습니다.미사용·중복 production artifact
현재 3D
dist약 24 MiB 중 다음 절감 후보를 확인했습니다.web-ifc-mt.wasm: 1,314,227 bytespublic/draco,public/basis복사본의 byte-for-byte 중복: 최소 835,738 bytes, public decoder directory 전체 약 1.35 MiBweb-ifccode path는 명시적으로 single-thread WASM만 초기화합니다. Draco/Basis는 Three.js r185 loader가 자체new URL(..., import.meta.url)asset을 제공하므로 public 복사본 대신 Vite hashed asset을 사용할 수 있습니다.RED→GREEN 순서
dist에 실행해 RED 확인 후 source map 비활성화와 size/file gate 추가Puppeteer Core는 여러 offline smoke/prerender 도구에서 실제 사용하므로 제거하지 않습니다.
RED→GREEN 및 리뷰 보완 기록
실제 RED 확인
tests/decoder-staging.test.ts에 single-thread IFC staging 요구사항 추가 → 기존public/web-ifc/web-ifc-mt.wasm때문에 실패 확인public/draco,public/basis때문에 실패 확인/viewer-3d/draco/assertion 실패 확인구현 및 GREEN
postinstall은 single-threadweb-ifc.wasm만 staging하고 stale MT 파일 제거public/draco,public/basis,web-ifc-mt.wasm제거basis_transcoder-*.wasmrequest와 model-ready를 확인하는 E2E 통과측정 결과
@emnapi/*,fsevents,string-width)은npm find-dupes/dry-run dedupe 결과 안전한 통합 경로가 없어 override하지 않음lightningcss-*platform package는 lockfile의 optional compatibility metadata이며 Linux x64 clean install에는 해당 binding만 설치됨. production browser artifact에는 포함되지 않음첫 전체 verify의 3D subpath 실패는 fixture route glob이
?model=...gltf를 포함한 메인 document까지 가로챈 test harness 문제였습니다. 실제 pathname만 일치하도록 route 정규식을 제한한 뒤 targeted E2E는 1 passed로 복구했습니다. 최종 전체 verify 결과를 이어서 기록하겠습니다.최종 연속 검증
npm run verify전체 통과:basis_transcoder-*.wasm실제 request 및 model-ready 확인커밋:
0c65680 perf: reduce 3D runtime artifacts (#7)49d6b0e test: verify bundled decoders and artifact budgets (#7)500 kB 초과 chunk warning은 남지만 build/test 실패가 아니며, 동적 import나 web-ifc 분할 최적화는 별도 성능 범위로 취급합니다. standards 재검토는 Blocker 없이 통과했고, spec 재검토 후 Blocker가 없으면 이슈를 완료 상태로 닫겠습니다.
리뷰 판정 및 종료
git diff --check: 통과Scope-out은 이 이슈를 확장하지 않고 분리했습니다.
현재 repository에는 milestone이 없어 연결하지 않았습니다. #8/#9의 목표 일정이 정해지면 due date가 있는 performance/compliance milestone 생성을 제안합니다.
완료 조건과 전체 검증이 충족되어 #7을 완료 상태로 닫습니다.