13 KiB
OrgChart 선택형 UI 의존성 및 최소 설치 검증
RESULT: PASS — 이번 최소 설치·선택형 Adapter 개선 범위. 기존 P10 전체 판정 PARTIAL과 기존 Guard FAIL 10건은 유지한다. 전체 회귀·디자인 승인 결과로 확장하지 않는다.
1. 실제 실패 원인
원본 외부 로그: D:\디자인시스템\조직도 테스트\evidence\consumer-build-without-ui.log.
기준 Feature/HEAD: feature/orgchart-package, 5acaf8a29596317133e54e8ad437ee00beba1cf0.
기본 React Entry → OrgChart.tsx → lazy(() => import('./HMEmployeeDialog.js')) → Dialog 청크 → @hm-design/ui 순으로 연결됐다. UI가 없는 소비자도 Vite 8.3.0이 dynamic import 청크를 Production Build에서 해석했다. optional peer stub에는 named export가 없어 다음 오류를 포함한 12건의 MISSING_EXPORT로 실패했다.
[MISSING_EXPORT] "Avatar" is not exported by "__vite-optional-peer-dep:@hm-design/ui:@hm-design/org-chart-react".
node_modules/@hm-design/org-chart-react/dist/HMEmployeeDialog-gdk9Uddu.js:3:10
React.lazy는 실행 시 로딩을 늦추지만 소비자의 빌드 의존성 그래프에서 해당 Import를 제거하지 않는다. 원인을 확인한 후에만 Entry를 분리했다.
2. 의존성·Import·공개 API
- Core dependencies는 기존
orgchart: 6.0.0그대로다. React/HM UI dependency, peer, Import를 추가하지 않았다. - Wrapper dependencies는
@hm-design/org-chart: 0.1.0그대로다.react: ^19.0.0peer 및@hm-design/ui: 0.1.0optional peer 선언도 그대로다. 신규 런타임 라이브러리·lockfile 변경이 없다. - 기본
@hm-design/org-chart-react는 UI-independent 공유 Wrapper만 Import한다. runtime JS와.d.ts의 전이 그래프에 UI Import/참조가 없다. - 신규 공개
@hm-design/org-chart-react/hm-dialog는 같은 Props의OrgChart와HMEmployeeDialog를 제공한다. 이 Entry만 HM UI 공개 API를 Import한다. package exports의 JS/타입 경로와 실제 tarball 산출물이 일치한다. - 기존
OrgChart, 기존 Props, Core type-only re-export,'core' | 'hm-dialog' | 'none'값을 유지했다.'adapter',employeePopupAdapter,OrgChartEmployeeSelection,OrgChartEmployeePopupProps는 추가 API다. - 기본값은 항상 Core다. HM UI 설치, HM Entry Import 또는 Adapter 전달만으로 팝업을 전환하지 않는다.
employeePopup설정으로 사용자가 명시적으로 선택한다. - 기본 Entry에서
'hm-dialog'/'adapter'를 선택하고 Adapter를 제공하지 않으면 Core 팝업으로 유지하며onLifecycleError에 구성 오류를 전달한다.onEmployeeClick은 기존대로 우선한다. - HM Adapter의 직원 필드·Avatar·Dialog·닫기·Escape·focus 복귀 구현은 유지했다. 타입 계약만 공용 UI-independent 타입으로 이동했다.
- Auto에서 팝업 소유권 전환은 기존
setEmployeeClickHandler를 사용한다. Core 인스턴스와 데이터는 재생성·변경하지 않는다. Fixed의 기존 Core 팝업 정책은 유지하며, 다른 UI는 기존onEmployeeClick으로 연결할 수 있다. - Department Colors와 Overview의 별도 페이지 Export를 추가하지 않았다. AI 실험 페이지를 이관하지 않았다.
기존 HM 소비자의 설치/API 전환은 Import 한 줄이 필요하다. 기존 기본 Entry와 employeePopup="hm-dialog"만 사용한 코드는 다음 Entry를 선택하거나 HMEmployeeDialog를 명시적으로 주입해야 한다. 자동 HM 로딩은 더 이상 제공하지 않는다.
import { OrgChart } from '@hm-design/org-chart-react/hm-dialog';
<OrgChart dataSource={source} stylesheetUrls={stylesheets}
layoutMode="auto" employeePopup="hm-dialog" />;
다른 디자인 시스템은 기본 Entry에서 employeePopup="adapter" employeePopupAdapter={MyPopup}를 사용한다. Adapter는 { selection, onClose }를 받으며 직원/context 원본을 수정하지 않고 접근성·닫기·focus 복귀를 소유한다. Core와 조직도 JSON을 수정하지 않는다.
3. CSS·자산·설치 경계
Core의 공개 engine.css와 style.css 실제 배포 URL을 기존 stylesheetUrls로 Shadow DOM에 연결했다. Core CSS는 기존 빌드가 source-relative CSS를 inline한 자체 산출물이며 HM Theme/CSS를 Import하지 않는다. React Wrapper에는 자동 CSS Import나 새로운 자산 참조가 없다. HM Entry도 Theme를 자동 Import하지 않고 호스트의 실제 HM Theme/Tailwind 연결을 사용한다.
A/B에서는 HM Theme나 Tailwind를 설치하지 않았다. A에는 React도 없다. C는 선택 HM UI와 해당 peer/Theme를 소비 프로젝트에서 제공했다. 일반 콘텐츠 CSS나 Fixed/Expanded 디자인을 수정하지 않았다.
4. 실제 외부 프로젝트 A/B/C
세 프로젝트는 저장소 및 상위 node_modules 밖의 새 임시 폴더에 만들었다. 소비자 소스에는 저장소 내부 Import/alias/symlink가 없다. npm pack 실제 .tgz를 dependency로 설치했고 npm ls --all --json으로 설치 그래프를 기록했다. 프로젝트 절대경로는 projects.json에 보존했다.
- A Core + Vanilla: PASS. React·Wrapper·HM UI가 없는 실제 설치. strict Typecheck, Production Build, Fixed/Auto 렌더링 및 native Core 팝업·Enter·Escape·닫기·focus 복귀 PASS.
- B Core + React Wrapper: PASS. React/React DOM 19.3.0, HM UI·HM Theme·Tailwind 없음. 기본 선언 strict Typecheck, Production Build, Fixed/Auto 렌더링·Core 팝업 PASS. 다른 디자인 시스템의 팝업 Adapter 주입·callback 우선권·Adapter 미제공 시 Core 유지도 PASS.
- C Core + React Wrapper + HM UI: PASS. React 19.3.0, HM UI optional peer·Theme 연결. strict Typecheck 및 Production Build PASS. 기본 Entry와 HM Entry 모두 명시적 HM 선택 이전에는 Core를 유지한다. 기존 HM Dialog의 직원 정보·Enter·Escape·닫기·focus 복귀, HM→Core 전환 시 동일 Core 인스턴스 유지 PASS.
외부 브라우저 검사: 17개 그룹 PASS, 브라우저 Chromium 155.0.8059.39, 콘솔 오류·브라우저 예외·HTTP 실패 0. StrictMode의 최종 host 1개와 입력 데이터 byte 보존도 검사했다. 이것은 전체 회귀 테스트 건수가 아니다.
기본 Entry 전이 그래프: index.js, 공유 Wrapper JS, index.d.ts, OrgChart.d.ts, types.d.ts에 HM UI 참조가 없음 PASS. B의 skipLibCheck: false 타입 검사가 HM UI 없이 통과했다.
실제 로그: A 빌드, B 빌드, C 빌드, 최종 외부 실행.
첫 offline 설치 시도는 샌드박스 npm 캐시에 TypeScript가 없어 ENOTCACHED로 중단됐다. 네트워크 설치로 해결했고 패키지 FAIL로 계산하지 않았다. 반복 검증은 실패한 환경·미완료 검사만 보완했다.
5. 기존 Storybook·최소 통합 검증
npm pack: Core/UI/Wrapper의 prepack Build와 선언 생성 PASS. 공개 Entry가 실제 tarball에 포함됨 PASS.tsc -p tsconfig.app.json --noEmit: 기존 앱·Storybook TypeScript graph PASS.- Storybook 10.6.1 Production Build: PASS. 기존 전체 회귀 suite는 실행하지 않았다.
- Storybook 브라우저: Expanded의 기본 HM 팝업, Escape/focus 복귀, 기존 Select를 통한 Core 팝업 전환 및 Core 모달 focus PASS. Full Composition Fixed의 렌더링·Core 팝업·Escape PASS. 콘솔 오류·브라우저 예외 0.
- 외부 HM Dialog 캡처와 Storybook Expanded 캡처를 직접 확인했다. 레이아웃·직원 정보·닫기 버튼이 정상 표시됐다. 디자인 최종 승인을 의미하지 않는다.
- Git/산출물 보존: Core/UI/Center Graphic/Theme/기존 데이터/정책/P10 보호 파일의 tracked 수정 0. Expanded Story는 Import 한 줄만 변경했다. 최종 Wrapper tarball은 README의 잔여 lazy 설명만 보완하여
--ignore-scripts로 다시 pack했고, 모든 JS·.d.ts가 실제 설치·검증된 B/C와 byte 동일함을 확인했다. 정상 Build를 반복하지 않았다.
빌드 경고는 기존 :host-context CSS minify 경고, vendor use client bundling 경고 및 큰 chunk 경고다. 빌드 실패는 없다. 이 작업에서는 관련 디자인·엔진 최적화 범위를 확대하지 않았다.
6. Guard와 NOT VERIFIED
기존 P10.1 Guard의 FAIL 10건은 Core Token 참조에 대한 기존 기록이며 해당 파일을 수정하지 않았다. 원본 보고서를 보존했다. 전체 Guard를 반복하거나 전체 판정을 PASS로 바꾸지 않았다.
이번 변경만 한 번 검사한 PARTIAL Guard는 FAIL 0 / NOT VERIFIED 5다. 원본 status와 staticStatus는 NOT VERIFIED, runtimeStatus도 NOT VERIFIED로 그대로 둔다.
- SCOPE-001 3건: 패키지 구현이 Guard의 증명된 Storybook graph 범위 밖임. 별도 npm pack·외부 build·브라우저 증거를 연결하며 원본 상태를 덮어쓰지 않는다.
- TOKEN-001: 기존 Expanded CSS의 Radix runtime 제공 변수.
- TOKEN-002: 기존 StoryPage의 동적 className.
- CSS styleEvidence: STATIC PASS / RUNTIME NOT VERIFIED / DESIGN_INTENT NOT VERIFIED / FINAL NOT VERIFIED. 기존 CSS를 수정하지 않았으며 기술적 팝업 성공을 CSS 디자인 승인으로 사용하지 않았다.
SSR/hydration, 다른 React major·bundler·OS, 전체 스크린리더, 실제 touch, 장기 메모리/성능, 390/768/1280px의 재검증, 전체 회귀 및 디자인·배포 승인은 NOT VERIFIED / 이번 범위에서 미실행이다. 이번 브라우저 검증은 1440px 핵심 팝업 동작에 한정했다. 기존 유효한 검사 결과는 과거 증거로 보존한다.
7. 변경 파일과 사용 가이드 반영
기존 수정 파일:
packages/org-chart-react/package.json: 선택 HM Entry Export 추가. dependency 선언 유지.packages/org-chart-react/build.mjs: UI-independent/HM Entry를 함께 빌드.packages/org-chart-react/src/OrgChart.tsx: UI Import 제거, 명시 Adapter 주입·Core fallback.packages/org-chart-react/src/types.ts: UI-independent popup Adapter 계약 및 추가 Props.packages/org-chart-react/src/index.ts: 공용 Adapter 타입 Export.packages/org-chart-react/src/HMEmployeeDialog.tsx: 팝업 타입을 공용 계약으로 변경.src/org-chart/org-chart-expanded.stories.tsx: HM 선택 Entry로 Import 한 줄 변경.packages/org-chart-react/README.md: 최소 설치·HM Import 전환·커스텀 Adapter·빌드 경계 안내.docs/org-chart/expanded-usage.md: HM 선택 Entry·Adapter 사용법 보완.
신규 파일:
packages/org-chart-react/src/hm-dialog.tsx: 선택 HM Adapter Entry.scripts/verify-orgchart-minimal-install.mjs: 외부 실제 설치·타입·빌드·팝업 검증.scripts/verify-orgchart-hm-story.mjs: 기존 변경 Story/Fixed 핵심 팝업 검증.- 이 보고서.
병렬 사용 가이드 담당자가 반영할 내용: 최소 설치에서 UI/Theme 제외, 기존 HM 소비자의 /hm-dialog Import 전환, employeePopupAdapter 및 'adapter' 계약, package 설치만으로 전환하지 않는 정책, Fixed의 기존 Core/onEmployeeClick 정책. Chart Only·UsageGuide Worktree 파일은 수정하지 않았다. 같은 파일의 동시 변경을 발견하지 않아 현재 Feature에서 최소 수정했다.
8. Git 및 시간
공식 origin: https://gitea.hmac.kr/b25027/HMDesign.git.
Local/Remote Feature HEAD: 5acaf8a29596317133e54e8ad437ee00beba1cf0.
읽기 전용 확인한 Remote main: c45d63a03b84eaac43f01bd400a16488a80e4229. main을 checkout·수정·Merge하지 않았다.
Stage 0. Commit·Push·main Merge 미진행. 이 작업의 수정은 현재 Feature Working Tree에 남긴다. 기존 P10.1과 병렬 정책·사용 가이드 작업을 보존한다.
- Started At: 2026-10-13 15:17:35 KST
- Completed At: 2026-10-13 15:32:28 KST
- Actual Duration: 14분 53초
- Estimated Duration: 약 35–50분
- Variance: 예상보다 20분 7초–35분 7초 짧음
검증 재현: 저장소의 일반 개발 의존성이 준비된 상태에서 ORGCHART_PLAYWRIGHT_MODULE을 기존 Playwright entry로 설정하고 node scripts/verify-orgchart-minimal-install.mjs를 실행한다. 기존 Chrome의 다른 설치 경로는 ORGCHART_CHROME으로 지정한다. 각 실행은 새 외부 임시 소비자를 만들고 기존 폴더를 삭제하지 않는다. Storybook 빌드 후 node scripts/verify-orgchart-hm-story.mjs로 선택된 기존 Story만 검사한다. 생성물은 test-results/org-chart-minimal-install에 보존하며 Stage하지 않았다.