Files
shkim4 dc9258599c feat(chart): add @hm-design/chart package with Bar, Line, Donut, Pie, Radar, Area and Radial charts
- new workspace package packages/chart (shadcn/ui Chart + Recharts, HM Theme tokens), examples entry with sample data
- Storybook Chart group (src/chart), consumer example (examples/chart), build:chart / build:chart-example scripts
- README rewritten as the AI usage guide (install, CSS wiring, chart selection, data rules, verification)
- docs: package count/list, Submodule guide (chart workspace, React dedupe), shared AI_GUIDE row, MAINTAINING, story inventory
2026-11-06 15:52:47 +09:00

317 lines
39 KiB
Markdown

# HMDesign AI 작업 가이드 — 공통 진입점
> 이 파일은 HMDesign 패키지(`@hm-design/ui`, `@hm-design/sw`, `@hm-design/org-chart`, `@hm-design/org-chart-react`)의 `ai/AI_GUIDE.md`에 **같은 내용으로** 들어 있습니다. 원본은 HMDesign 저장소 `docs/ai/AI_GUIDE.md`이며 패키지 사본은 `npm run sync:ai-docs`로 갱신합니다. 사본을 직접 고치지 않습니다.
사용자가 "HMDesign 패키지를 기준으로 화면을 구현해 주세요", "HMDesign SW로 화면을 만들어 주세요"처럼 요청하면 AI 코딩 도구는 이 파일의 1~7단계를 순서대로 따릅니다. 이 문서와 각 패키지의 `ai/` 문서는 실제 공개 API·CSS에서 확인한 내용만 적습니다. 여기에 없는 컴포넌트·Props·토큰은 없는 것으로 취급합니다.
## 0. 읽는 순서
1. **이 파일**(어느 패키지의 사본이든 같음)
2. 선택한 패키지의 `ai/AI_USAGE.md` → `ai/COMPONENT_CATALOG.md` → `ai/DESIGN_RULES.md` → `ai/COMPOSITION_PATTERNS.md` (SW 뷰어 모드는 `AI_USAGE.md` §0 다음에 `ai/VIEWER.md`를 먼저 읽고 카탈로그의 뷰어 절을 봅니다)
3. API가 의심스러우면 그 패키지의 `dist/*.d.ts`(공개 진입점에서 export되는 것만)
| 유형 | 패키지 | 지침 위치(설치 후) | JS 진입점 | CSS |
|---|---|---|---|---|
| ① Web UI | `@hm-design/ui` | `node_modules/@hm-design/ui/ai/` | `@hm-design/ui`, `@hm-design/ui/theme` | `@hm-design/ui/tailwind.css` + `@hm-design/ui/theme.css`(Tailwind CSS 4 필요), 선택 `@hm-design/ui/dashboard-status.css` |
| ② SW UI — 일반 모드 | `@hm-design/sw` | `node_modules/@hm-design/sw/ai/` (`AI_USAGE.md` §0 모드 선택 → 일반 모드 문서) | `@hm-design/sw` | `@hm-design/sw/styles.css` |
| ② SW UI — 뷰어 모드 | `@hm-design/sw`(같은 패키지) | `node_modules/@hm-design/sw/ai/` (`AI_USAGE.md` §0 → `VIEWER.md`) | `@hm-design/sw` | `@hm-design/sw/styles.css`(같은 파일) |
| ③ OrgChart | `@hm-design/org-chart`(Core) + React면 `@hm-design/org-chart-react` | `node_modules/@hm-design/org-chart/ai/` (React 어댑터 안내는 `node_modules/@hm-design/org-chart-react/ai/AI_USAGE.md`) | `@hm-design/org-chart`, `@hm-design/org-chart-react`, 선택 `@hm-design/org-chart-react/hm-dialog` | `@hm-design/org-chart/engine.css`, `@hm-design/org-chart/style.css`(URL로 전달 — Shadow DOM 안에 로드) |
| 기타 | `@hm-design/center-graphic` | AI 지침 없음. 패키지 `README.md`만 | `@hm-design/center-graphic`, 선택 `@hm-design/center-graphic/reference`(Storybook 검토용 참고 데모, 컴포넌트 API 아님) | JS 진입점이 자동 import. 명시가 필요하면 `@hm-design/center-graphic/style.css` |
| 기타 — 차트 | `@hm-design/chart`(+ Theme 토큰용 `@hm-design/ui` peer) | AI 지침 폴더 없음. 패키지 `README.md`(`node_modules/@hm-design/chart/README.md`)가 설치·차트 선택·Props·검증 지침 | `@hm-design/chart`, 예시 데이터 `@hm-design/chart/examples`(운영 데이터 아님) | Tailwind 앱에서 `@hm-design/chart/tailwind.css` + `@hm-design/ui/tailwind.css` + `@hm-design/ui/theme.css`(순서는 README). 차트 스타일은 JS 진입점이 자동 import |
모든 패키지는 서로 독립입니다(`@hm-design/org-chart-react`만 Core에 의존, `@hm-design/ui`는 `/hm-dialog`를 쓸 때만 선택 peer, `@hm-design/chart`는 `@hm-design/ui`의 Theme CSS 토큰만 peer로 사용). React·React DOM `^19`는 peer입니다.
## 1단계. 사용 목적 확인
화면 구현 요청을 받으면 코드 작성 전에 **사용 유형**을 정합니다. 유형은 다음 넷이고, SW는 다시 두 모드로 나뉩니다.
1. Web
2. SW — **SW 일반 모드**(편집용: `SWHeader`, `SWPopup` …) / **SW 뷰어 모드**(보기 전용: `SWViewerHeader`, `SWViewerMenu`, `SWViewerPanel` …)
3. OrgChart
4. 혼합 사용(영역마다 위 유형 하나)
다음 순서로 판단하고, **판단되면 다시 묻지 않습니다.**
1. 소비 프로젝트의 `AGENTS.md`·`CLAUDE.md` 등에 `HMDesign 사용 유형:` 설정이 있으면 그대로 따릅니다(§9). 값은 `Web` / `SW 일반` / `SW 뷰어` / `OrgChart` / `혼합(영역별: …)`입니다. 값이 `SW`뿐이면 유형은 정해진 것이고 모드만 아래 4번으로 정합니다.
2. 사용자 요청이 유형을 분명히 말하면 그대로 따릅니다.
- Web: 웹 화면, 관리자·업무 화면, 목록·검색·Form, 대시보드, GNB/LNB, Dialog, Table …
- SW: 데스크톱 SW, 도면·CAD, SW Header, 툴바, 레이어/색상/선스타일, 속성창·SW Popup, 뷰어 …
- OrgChart: 조직도, 조직 계층·직원 카드, 조직 JSON/CSV/Excel 시각화 …
- 둘 이상이 함께 나오면 ④ 혼합(예: "업무 화면 안에 조직도" = Web + OrgChart).
3. 위로 정할 수 없으면 코드 작성 전에 **그대로** 묻습니다.
> 어떤 HMDesign 디자인 시스템을 사용하시겠습니까?
>
> 1. Web
> 2. SW (일반 모드 / 뷰어 모드)
> 3. OrgChart
> 4. 혼합 사용
4. **SW가 정해졌거나 포함됐는데 모드가 불명확하면** 코드 작성 전에 묻습니다. 설정 값(`SW 일반`/`SW 뷰어`)이나 요청이 모드를 분명히 말하면 묻지 않습니다. 판단 근거와 질문 문구는 `@hm-design/sw/ai/AI_USAGE.md` §0을 따릅니다. 유형 질문이 필요한 경우에는 같은 메시지에서 2번 선택 시의 모드도 함께 묻습니다(한 번에 끝냄).
> SW 화면을 어떤 모드로 만들까요?
>
> 1. SW 일반 모드 — 편집용 Header(`SWHeader`)·속성창·SW Popup
> 2. SW 뷰어 모드 — 보기 전용 Header(`SWViewerHeader`)·뷰어 메뉴·뷰어 패널
- "HMDesign SW로 화면을 만들어 주세요"처럼 SW만 말하고 모드 근거가 없으면 유형은 SW로 확정하고 4번의 모드 질문만 합니다.
- `package.json`에 설치된 패키지가 하나뿐이어도 그것만으로 유형을 확정하지 않습니다(설치가 덜 된 상태일 수 있음). 요청 내용과 맞을 때만 근거로 씁니다. SW 모드도 같은 패키지이므로 설치 상태로는 판단하지 않습니다.
- 정해진 유형·모드는 결과 보고(7단계)에 적고, 작업 중에 다른 유형·모드의 컴포넌트·스타일을 임의로 섞지 않습니다(5단계).
- 혼합을 고르면 영역별 패키지(예: "페이지 = Web, 가운데 영역 = OrgChart")를 확인합니다. SW 영역이 있으면 그 영역의 모드(일반/뷰어)까지 정합니다.
- **OrgChart가 포함되고 생성 방식이 없으면** 같은 메시지에서 다음도 묻습니다(이미 말했으면 묻지 않음): "조직도만 기존 페이지에 삽입할까요(Chart Only), 아니면 레이아웃까지 구성한 새 페이지 전체를 생성할까요(Full Page)?" 상세는 `@hm-design/org-chart/ai/AI_USAGE.md` §1.
- 선택한 패키지가 설치되어 있지 않으면 설치가 필요하다고 보고합니다. 다른 HMDesign 패키지나 임의 라이브러리로 대신하지 않습니다.
## 2단계. 패키지 분석
1. `node_modules/@hm-design/<패키지>/package.json`의 `version`·`exports`·`peerDependencies`를 확인합니다. `exports`에 없는 경로(`src/...`, `dist/components/...`)는 import하지 않습니다.
2. 그 패키지의 `ai/` 문서를 §0 순서로 읽습니다. 필요한 절만 읽고 전체 `dist`를 훑지 않습니다.
3. 카탈로그와 실제 `dist/index.d.ts`가 다르면 **`.d.ts`가 기준**입니다. 차이를 결과 보고에 적습니다.
4. 소비 프로젝트의 기존 CSS 진입점·폰트·빌드 도구(Vite 등)·이미 쓰는 디자인 시스템을 확인합니다. 기존 프로젝트의 디자인 시스템을 바꾸지 않습니다.
## 3단계. 화면 분석
요청 화면을 항목으로 나누고 항목마다 판단을 기록합니다.
| 요청 항목 | 판단 | 근거(카탈로그의 실제 이름) |
|---|---|---|
| 예: 상단 메뉴 | 재사용 | Web `GNB` + `GNBMobileMenu` |
| 예: 레이어 선택(SW 일반) | 재사용 | SW `SWHeaderLayerMenu` |
| 예: 상단 메뉴(SW 뷰어) | Props 설정 | SW `SWViewerHeader`의 `groups` |
| 예: 검색 상자(SW 일반) | 신규 | SW 카탈로그에 없음 → `SWHeaderInput` 재사용 + 일반 모드 토큰 |
판단 값은 **재사용**(그대로) / **Props 설정**(기존 Variant·Props) / **조합**(기존 컴포넌트 배치) / **신규**(소비 프로젝트에 최소 구현) 중 하나입니다.
## 4단계. UI 구현
우선순위(위가 먼저):
1. 선택 패키지의 기존 컴포넌트·Pattern을 그대로 사용
2. 기존 Variant / Props / Callback으로 해결
3. 기존 컴포넌트 조합(배치용 CSS만 소비 프로젝트에 작성)
4. 조합으로 안 되는 부분만 **소비 프로젝트에** 새로 구현 — 아래 "없는 컴포넌트 처리 3단계"
모든 단계는 **1단계에서 정한 유형·모드 안에서만** 찾습니다. SW 뷰어 모드는 뷰어 컴포넌트(`SWViewer*`)를, SW 일반 모드는 일반 컴포넌트(`SWHeader`·`SWPopup` …)를 먼저 씁니다. 다른 모드에 같은 역할의 컴포넌트가 있어도 가져오지 않습니다.
### 없는 컴포넌트 처리 3단계
| 단계 | 조건 | 할 일 | 결과 보고 |
|---|---|---|---|
| ① 재사용 | 선택 유형·모드에 컴포넌트·Variant·Props·조합이 있음 | 그대로 사용(위 1~3) | 재사용 / Props 설정 / 조합 |
| ② 같은 모드 스타일로 신규 | 컴포넌트는 없지만 그 모드의 토큰·확인값·상태 표현이 있음 | 소비 프로젝트에 최소 구현. 그 유형·모드의 토큰과 `DESIGN_RULES.md`(SW 뷰어는 `VIEWER.md`도)의 크기·색·상태 표현만 읽고, 안쪽에는 그 모드의 공개 컴포넌트를 재사용 | 신규 · 읽은 토큰 목록 |
| ③ HMDesign과 조화되는 새 스타일 | ②로 참고할 토큰·확인값이 없음 | HMDesign 공통 규칙(아래)과 선택 유형·모드의 가장 가까운 토큰을 기준으로 새 스타일을 구성 | 신규 · **"AI 구성 값 — 디자인 확인 필요"** 목록(속성·값·이유) |
- 토큰·확인값이 있으면 ②에서 반드시 그것을 씁니다. ③은 참고할 값이 정말 없을 때만이며, ③에서 만든 값은 확정 디자인이 아니라 확인 대상입니다. 화면 인상을 크게 바꾸는 값(주요 색·Header 높이 등)이 필요하면 구현 전에 사용자에게 먼저 확인합니다.
- 유형·모드별 구체 토큰과 예는 각 패키지 `ai/AI_USAGE.md`에 있습니다.
규칙:
- `node_modules` 안 패키지 파일을 수정하지 않습니다. 패키지 `dist` 구현이나 내부 CSS 블록을 복사해 같은 컴포넌트를 다시 만들지 않습니다.
- 이미 있는 컴포넌트와 같은 역할의 컴포넌트를 새로 만들지 않습니다(예: Web에 `Dialog`가 있는데 자체 Modal 작성 금지).
- 토큰·확인값이 있는 속성에 새 값을 만들지 않습니다. 색·크기·간격·radius·그림자는 각 패키지 `DESIGN_RULES.md`(SW 뷰어는 `VIEWER.md`도)의 토큰·확인값을 씁니다. 값이 없을 때만 위 ③으로 구성하고 "AI 구성 값"으로 보고합니다(추측한 값을 확정값처럼 쓰지 않음).
- 공통: Font Weight는 400 / 500 / 700만 씁니다(600 없음). Light/Dark 분기를 만들지 않습니다. 새 컴포넌트 CSS에 `html`·`body`·`*` 전역 규칙을 넣지 않습니다. 새 class는 소비 프로젝트 접두사(예: `app-`)를 씁니다.
- 요청에 없는 메뉴·통계·설명·다운로드·외부 API·AI 입력 UI를 추가하지 않습니다. 필요해 보이면 제안으로만 보고합니다.
- **디자인 적용 시 변경 범위 제한(2026-10-23, 모든 컴포넌트 — Header 포함).** Figma·디자인 시안 적용은 디자인 변경만 합니다. 일반 SW Header, SW Viewer Header, Popup·Panel, 그 밖의 HMDesign 컴포넌트와 HMDesign을 Git Submodule로 쓰는 소비 프로젝트에 모두 적용합니다.
- 바꾸지 않는 것: 실제 상태값(`selected`·`active`·`disabled`·`checked`·`expanded`·`hidden` 등), 메뉴의 기본 선택 상태(예: Model / Layout), Popup 열림·닫힘 상태, 스위치·체크박스 기본값, 입력값·숫자·개수 등 표시 데이터, Props와 그 기본값, 이벤트·클릭 동작, 조건부 렌더링, 기존 반응형 기능, 사용자 설정·상태 관리 로직, 요청받지 않은 다른 화면·컴포넌트.
- 바꿀 수 있는 것: 배경색·글자색·Border·Gradient·Shadow·Radius·Padding·Gap, 너비·높이·정렬·레이아웃, 기존 상태에 대응하는 시각 스타일. 선택 상태의 모양을 바꿔도 어떤 항목이 선택되어 있는지는 바꾸지 않습니다.
- Figma에 특정 상태가 그려져 있어도 컴포넌트의 기본 상태를 바꾸지 않습니다. 디자인 비교는 검증용 Story나 테스트 데이터에서 하고, Storybook 예시값을 소비 프로젝트의 기본값으로 복사하지 않습니다. 상태·기능 변경이 꼭 필요해 보이면 적용하지 말고 별도로 보고합니다.
- 작업 후 Git Diff로 요청 범위 밖 변경이 없는지 확인합니다.
- **Git Submodule 소비 프로젝트의 콘텐츠 생성 제한(2026-10-23, Header 제외).** HMDesign을 Git Submodule로 사용하는 소비 프로젝트의 UI 컴포넌트·화면에 적용합니다. **제외:** 일반 SW Header(`SWHeader`), SW Viewer Header(`SWViewerHeader`)와 그 밖의 모든 Header 관련 컴포넌트·영역 — 텍스트는 기존 Header 전용 AI 지침을 따르되, 위 "디자인 적용 시 변경 범위 제한"(상태·기능 변경 금지)은 Header에도 그대로 적용합니다.
1. 사용자가 요청하지 않은 설명·안내 문구·제목·라벨·툴팁을 임의로 추가하지 않습니다.
2. Storybook의 샘플 텍스트나 데이터를 실제 소비 프로젝트에 임의로 복사하지 않습니다.
3. Figma 또는 기존 컴포넌트에 없는 텍스트를 추측해서 생성하지 않습니다.
4. 기존 텍스트와 데이터를 임의로 변경하지 않습니다.
5. 필요한 콘텐츠가 불명확하면 임의로 확정하지 않고 결과 보고에 확인 대상으로 적습니다.
- **Git Submodule 사용 규칙(2026-10-23).** 소비 프로젝트에서 HMDesign을 사용할 때 요청 범위 밖은 바꾸지 않습니다. Submodule Commit 포인터는 사용자 승인 없이 바꾸지 않습니다. 소비 프로젝트의 기존 데이터와 기능을 우선 유지합니다. 연결 방식은 9절을 따릅니다.
1. **확인 순서.** 컴포넌트를 적용하기 전에 (가) 연결된 Submodule의 실제 경로와 고정 Commit(`git submodule status`), (나) 그 Commit의 공통 `AI_GUIDE.md`(이 파일), (다) 사용할 패키지의 `ai/` 지침과 컴포넌트별 디자인 규칙(`DESIGN_RULES.md`, SW 뷰어는 `VIEWER.md`), (라) 실제 공개 Export·Props·사용법(카탈로그, 의심되면 `dist/*.d.ts`), (마) 소비 프로젝트의 기존 화면과 동작 순서로 확인한 뒤 적용합니다. 다른 Commit·원격 저장소·Storybook 배포본의 지침으로 대신하지 않습니다.
2. **Storybook은 사용 예시로만.** Storybook은 조합·외형 참고용이며 실제 데이터·상태값·기본값의 기준이 아닙니다. 소비 프로젝트의 기존 상태값과 사용자 동작을 Storybook 예시로 교체하지 않습니다. 아이콘·문구·데이터·상태·기능 유지와 "원본 대비 변경" 보고는 아래 "기존 화면 전환 시 원본 보존"을 따릅니다.
3. **Submodule 수정 금지.** 컴포넌트를 사용하는 작업은 소비 프로젝트의 코드만 변경합니다. HMDesign Submodule 내부의 소스·지침·설정·빌드 산출 설정을 고치지 않습니다(9절의 `npm ci`·`npm run build:packages`로 `dist/`를 만드는 것은 수정이 아님).
4. **기능이 부족할 때.** HMDesign 컴포넌트가 필요한 기능을 지원하지 않으면 먼저 기존 Props·Slot·`children`·컴포넌트 조합(위 "없는 컴포넌트 처리 3단계")으로 대안을 검토해 적용 가능 여부를 보고합니다. HMDesign 패키지 자체 수정이나 Submodule Commit 변경이 필요하면 적용하지 말고 필요 사유와 범위를 적어 별도 승인을 요청합니다.
- **기존 화면 전환 시 원본 보존(2026-10-23, 모든 화면·컴포넌트 — Header 포함).** 기존 화면을 HMDesign 컴포넌트로 전환·마이그레이션할 때 적용합니다. 위 "디자인 적용 시 변경 범위 제한"·"콘텐츠 생성 제한"·"Git Submodule 사용 규칙"과 함께 적용하며, 콘텐츠 생성 제한의 Header 예외는 기존 Header의 아이콘·문구·상태·기능을 바꾸거나 제거해도 된다는 뜻이 아닙니다.
1. 원본과 같게 유지: 아이콘과 그 의미, 표시 문구·라벨·툴팁, 버튼·메뉴·입력 요소와 그 구성, 클릭·선택·입력 동작, 활성·비활성·선택·체크 등 상태 표시, 실제 데이터·기본값·표시 조건, 기존 기능과 사용자 작업 흐름. HMDesign 디자인 적용만을 이유로 제거·변경하지 않습니다.
2. 제거·대체·변경은 다음 중 하나일 때만 허용합니다: (가) HMDesign 지침이 명시적으로 요구함, (나) HMDesign 컴포넌트가 그 요소·동작을 지원하지 않아 기존 형태 유지가 불가능함, (다) 사용자가 명시적으로 승인함. (나)는 먼저 기존 Props·Slot·`children`·조합(위 "없는 컴포넌트 처리 3단계")으로 유지할 수 있는지 확인한 뒤에만 인정하며, 지원하지 않는 그 요소 외의 다른 요소·기능은 바꾸지 않습니다.
3. 다음 이유만으로는 바꾸지 않습니다: 더 깔끔해 보임, HMDesign 예시 화면에 없음, 중요도·사용 빈도가 낮아 보임, 구현 단순화, AI가 불필요하다고 판단함. 근거가 명시적 지침이나 확인된 컴포넌트 미지원이 아니라 AI의 판단이면 적용하지 않고 사용자에게 먼저 확인하며, 승인받지 못한 변경은 적용하지 않습니다.
4. 결과 보고(7단계)에 **"원본 대비 변경"** 항목을 반드시 넣습니다. 제거·대체·변경한 UI 요소는 누락 없이 `원본 요소 | 변경 내용 | 변경 근거` 표로 적고(그대로 유지한 항목은 나열하지 않아도 됨), 근거는 **지침 조항**(파일·조항·규칙) / **컴포넌트 미지원**(확인한 미지원 항목과 대안 검토 결과) / **판단**(적용하지 않고 승인 요청) 중 하나로 구분합니다. 변경이 없으면 "원본 대비 변경 없음"이라고 적습니다.
### 없는 UI를 같은 스타일로 만들 때 확인할 항목
신규 항목마다 아래를 선택 유형·모드의 문서에서 찾아 그대로 적용합니다(②). 찾을 수 없는 항목은 ③으로 구성하고 "AI 구성 값 — 디자인 확인 필요"로 보고합니다.
| 항목 | Web(`@hm-design/ui`) | SW 일반 모드(`@hm-design/sw`) | SW 뷰어 모드(`@hm-design/sw`) | OrgChart |
|---|---|---|---|---|
| 토큰·CSS 변수 | `--hm-sem-*`, `--hm-color-*`, `--hm-radius-*`(`:root`) | `--hm-sw-header-*`, `--hm-sw-property-*`(`SWTheme` 범위) | `--hm-sw-viewer-*` + 두 Header가 공유하는 `--hm-sw-header-document-*`·`object-*`·`property-*`(SW 범위) | `--hm-orgchart-*` 공개 입력(Shadow DOM 상속) |
| 색·Typography | DESIGN_RULES §2·§3 | DESIGN_RULES §2·§3 | VIEWER.md `SWViewerHeader`·디자인 변경 절 | DESIGN_RULES §2·§3 |
| 크기·여백 | DESIGN_RULES §4 | DESIGN_RULES §1 | VIEWER.md 디자인 변경 절(52px Header 등 실측값) | 카드·간격 변경 금지(승인 디자인) |
| Border·Radius·배경·그림자 | DESIGN_RULES §2·§4 | DESIGN_RULES §2·§8 | VIEWER.md `SWViewerPanel` 절(프레임은 SWPopup과 같음) | 공개 입력만 |
| 아이콘 | `lucide-react`(패키지 의존성) | 사용자·프로젝트 제공 에셋 → 패키지 공개 Export 중 같은 기능 → 없으면 코드 작성 전에 사용자에게 먼저 확인(Storybook에만 있으면 소비 프로젝트 사용 승인 또는 SVG 제공, HMDesign에도 없으면 에셋 제공 또는 대체 여부. 답변 전에는 외부 라이브러리·AI 생성 SVG·Storybook 파일로 대체하거나 생략 확정 금지. 사용 승인은 공식 패키지 등록 권한이 아님). 시안 기반 Header 도구 아이콘·창 제어 버튼은 `@hm-design/sw` `ai/AI_USAGE.md` §5 | 프로그램 제공 16px `currentColor` 아이콘, 외곽선은 `SWViewerIcon`. 선택 순서는 SW 일반 모드와 같음(`AI_USAGE.md` §5) | Core 내장 |
| 스크롤바 | `ScrollArea`(Radix), DESIGN_RULES §6 | 전용 디자인 없음 — 브라우저 기본(AI_USAGE §2) | 전용 디자인 없음 — 패널 본문 스크롤은 `SWViewerPanel` | Core 내부 Zoom/Pan |
| Hover / Active / Focus / Disabled | DESIGN_RULES §5 | DESIGN_RULES §4 | VIEWER.md `SWViewerHeader` 절 상태 표현 | Core 내장 |
| Popup·Panel | `Dialog`·`AlertDialog`·`Sheet`·`Drawer`·`Popover` | `SWPopup` + `SWPopupSection`/`SWPopupRow` | `SWViewerPanel`(+ `modal`) + `SWViewerSection`/`SWViewerField` | Core 팝업 / HM Dialog / 어댑터 |
| 동작·키보드 | Radix 동작 유지 | 카탈로그 "공통 키보드" | VIEWER.md `SWViewerMenu`·`SWViewerPanel` 키보드 | Core 키보드(Pan, Alt+M 이동 등) |
## 5단계. 패키지별 디자인 분리 (혼합 사용 포함)
각 패키지의 스타일 범위는 다음과 같습니다(실제 CSS 기준).
| 패키지 | 스타일이 적용되는 범위 | 주의 |
|---|---|---|
| Web | `theme.css`의 토큰은 `:root, [data-hm-theme]`. `tailwind.css`는 Tailwind base에서 `*`(border·outline), `body`(배경·글자), `html`(글꼴)을 **문서 전체에** 적용. 앱이 import하는 `tailwindcss`의 Preflight도 전역 | Web CSS를 넣은 문서에서는 다른 영역에도 전역 초기화가 적용됨 |
| SW(일반·뷰어 공통) | 토큰은 `.hm-sw-header`와 `.hm-sw-theme`에만 정의(뷰어 토큰 `--hm-sw-viewer-*`도 같은 범위). 전역 선택자 없음. `SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`은 자기 root에 `hm-sw-theme`를 가짐. 토큰 기본값은 가장 바깥 SW 범위에서만 선언되고 안쪽 SW 범위는 상속(변경은 가장 바깥 범위의 `style`, SW `AI_USAGE.md` §3.1) | 일반 모드의 Header 밖 SW 부품은 반드시 `<SWTheme>` 안 |
| OrgChart | Core가 자기 open Shadow DOM에만 CSS 로드. 호스트 CSS selector는 안쪽에 닿지 않고 **Custom Property 상속만** 통과 | 호스트 class로 카드 모양을 바꾸려 하지 않음 |
혼합 규칙:
1. 영역마다 하나의 패키지를 정하고 그 영역의 신규 UI는 그 패키지의 토큰만 읽습니다. Web 토큰(`--hm-sem-*`)을 SW 영역에, SW 토큰(`--hm-sw-*`)을 Web 영역에 쓰지 않습니다. OrgChart 내부는 `--hm-orgchart-*`만 씁니다. 글꼴도 같습니다: SW 기본 글꼴은 Noto Sans KR(`--hm-sw-header-font-family`, 2026-10-20 확정, Dotum 기본값 철회), Web 기본 글꼴도 Noto Sans KR(`--hm-font-family-base`)이지만 토큰은 각자 쓰고, OrgChart는 자기 설정을 유지합니다. 한 패키지의 글꼴 토큰·값을 다른 영역에 복사하지 않습니다.
2. 다른 패키지 컴포넌트는 **문서에 허용된 지점에서만** 씁니다.
- SW 일반 모드 `SWPopup`의 `children` 안 Web 컨트롤(SW 카탈로그가 허용, 예: Popup 하단 `Button`)
- SW 뷰어 모드 `SWViewerPanel`의 `children` 안 Web 컨트롤 — `SWViewer*` 컨트롤로 안 될 때만(SW `AI_USAGE.md` §0.4)
- OrgChart Full Page의 바깥 레이아웃 = Web(또는 요청된 패키지)
- OrgChart React의 직원 팝업 = 선택 `@hm-design/org-chart-react/hm-dialog`(Web `Dialog`, Web Theme CSS 필요)
3. 패키지 class(`hm-sw-*`, `hm-orgchart-*`, Web `data-slot`)를 소비 코드에서 덮어쓰지 않습니다. 배치는 `className`·`style`과 소비 프로젝트 class로 합니다.
4. **Web + SW를 한 문서에 함께 쓰면** Web의 전역 base(위 표)가 SW 화면에도 적용됩니다. SW는 자기 범위에서 버튼 등을 초기화하지만 이 조합의 시각 결과는 패키지에서 검증된 적이 없습니다(NOT VERIFIED). 이 조합이면 브라우저에서 SW 부품의 글꼴·테두리·배경을 직접 확인하고 차이를 보고합니다. 가능하면 Web CSS가 없는 SW 전용 화면(별도 entry)으로 분리합니다.
5. Web Scoped Theme(`[data-hm-theme]`)는 body Portal(Select·Popover·DatePicker 팝업)에 전달되지 않습니다. Web 영역만 다른 테마로 바꾸려면 Global Theme를 쓰거나 차이를 보고합니다.
### SW 일반 모드 ↔ 뷰어 모드 분리
SW 일반 모드와 뷰어 모드는 같은 패키지·같은 CSS 파일이지만 **서로 다른 디자인**입니다. 한 화면(한 Header 영역)에는 한 모드만 씁니다.
1. 일반 모드 화면: `SWHeader`·개별 컨트롤·`SWPopup`·`SWHeaderPropertyPanel`·`SWToolButton`/`SWToolGroup`. `SWViewer*` 컴포넌트와 `--hm-sw-viewer-*` 토큰을 쓰지 않습니다.
2. 뷰어 모드 화면: `SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`과 뷰어 패널 컨트롤(`SWViewerSection`·`SWViewerField` …). `SWHeader`에 뷰어 메뉴를 억지로 넣거나 `SWPopup`을 뷰어처럼 재스타일하지 않습니다.
3. 패키지가 실제로 공유하는 부분은 혼합이 아닙니다: `SWViewerPanel`은 `SWPopup` 프레임을 그대로 렌더링하고, 두 Header는 파일명·객체 수정·속성 면 토큰(`--hm-sw-header-document-*`·`object-*`·`property-*`)을 공유합니다. 소비 코드가 이 공유를 흉내 내 다른 모드 부품을 섞어도 된다는 뜻은 아닙니다.
4. 프로그램이 두 모드를 모두 가지면 모드 전환 시 Header 컴포넌트를 바꿔 끼웁니다(파일·패널 상태는 프로그램 상태로 유지). 세부는 `@hm-design/sw/ai/AI_USAGE.md` §0과 `VIEWER.md`.
### Header 전용 스타일의 적용 범위 (2026-11-05)
화면 상단 Header 컴포넌트 — SW `SWHeader`·`SWProcessHeader`·`SWViewerHeader`, Web `GNB`·`LNBMobileHeader`·`DashboardHeader` — 의 전용 스타일은 **그 Header 영역 안에서만** 씁니다. 전용 스타일은 Header의 class(`hm-sw-header__*`·`hm-sw-process-*`·`hm-sw-viewer-header__*`, Web Header의 `data-slot`)와 Header 모양을 정하는 값(배경·gradient·테두리·글자 외곽선·높이·간격)입니다. `DialogHeader`·`CardHeader`처럼 다른 컴포넌트 안의 머리 부품은 여기서 말하는 Header가 아닙니다. 이 규칙은 아래를 정할 뿐 기존 Header의 레이아웃·스타일·공개 API를 바꾸지 않습니다.
1. Header 밖의 본문·패널·카드·버튼·입력 필드와 다른 컴포넌트에 Header 전용 class·CSS·값을 붙이거나 복사하지 않습니다. "Header 스타일로" 같은 요청도 Header 영역에만 적용하고, 별도 요청이 없으면 Header 밖 기존 UI의 디자인과 동작은 그대로 둡니다.
2. 화면 전체 토큰·테마(Web Runtime Theme `--hm-sem-*`, SW 가장 바깥 범위의 `style` 토큰, 위 표의 범위)와 Header 전용 스타일을 구분합니다. Header를 맞추려고 화면 전체 테마 값을 바꾸지 않습니다.
3. Header를 구현하려고 전역 CSS(`html`·`body`·`*`, 공통 reset)를 바꾸거나 기존 본문 스타일을 덮어쓰지 않습니다.
4. Header와 본문의 경계에서는 배치에 필요한 연결만 소비 프로젝트 class로 처리합니다(Header 높이만큼 본문 시작 위치, sticky·z-index, 남는 높이를 본문에 주는 flex 등).
5. 공식 컴포넌트 내부 스타일을 소비 프로젝트에서 Override하지 않습니다(위 혼합 규칙 3). 바꿀 수 있는 것은 각 패키지가 공개한 Props·토큰뿐입니다.
6. 시안에 본문 디자인이 따로 있으면 그 영역의 패키지(위 혼합 규칙 1)의 공식 컴포넌트로 구현합니다. Header와 같은 패키지의 부품을 Header 밖에 둘 때도 그 부품의 공식 사용법(SW는 `<SWTheme>` 안)을 따르고 Header 모양을 덧입히지 않습니다.
7. 패키지가 공식으로 공유하는 부분은 위반이 아닙니다(예: `SWPopup`·`<SWTheme>` 부품이 `--hm-sw-header-*` 토큰을 읽음, 위 SW 분리 3). 소비 코드가 이를 흉내 내 Header 스타일을 다른 곳에 쓰면 안 됩니다.
8. 사용자가 화면 전체에 Header 디자인을 적용하라고 **명시한 경우에만** 범위를 넓힙니다. 이때도 공식 컴포넌트·공개 토큰으로만 맞추고 Header class를 복사하지 않으며, 결과 보고에 넓힌 범위를 적습니다.
## 6단계. 디자인 검증
소비 프로젝트에서 실제로 실행한 것만 PASS로 적습니다.
1. Typecheck(`tsc --noEmit` 등)와 Production Build
2. 브라우저 렌더링: 재사용한 컴포넌트가 HM 외형으로 보이는지(CSS 진입점 누락 확인), 신규 UI가 같은 토큰을 쓰는지
3. 상태·동작: Hover / Focus(키보드) / Disabled, Popup 열기·닫기·Escape·Focus 복귀, 선택 패키지의 핵심 동작
4. 폭: Web 390 / 768 / 1280 / 1440px, SW 일반 모드는 대상 창 폭(Header는 반응형 More 포함), SW 뷰어 모드는 대상 창 폭을 줄였다 늘리며 실제 공간 부족에 따른 단계(`iconOnlyBelow` 항목 아이콘만 → `collapseBelow` 항목 More 이동, 숫자는 px 경계가 아니라 순서) 전후, OrgChart는 캔버스 크기·초기 Fit
5. 혼합이면 영역 경계에서 스타일 침범이 없는지, SW면 선택하지 않은 모드의 컴포넌트·토큰이 섞이지 않았는지, Header 전용 스타일이 Header 밖에 쓰이지 않았는지(§5, "Header 전용 스타일의 적용 범위")
6. 실행하지 못한 항목은 `NOT VERIFIED`로 남깁니다.
## 7단계. 결과 보고 형식
```md
## HMDesign 적용 결과
- 사용 유형: Web | SW 일반 | SW 뷰어 | OrgChart(Chart Only|Full Page) | 혼합(영역별: …)
- 유형·모드 판단 근거: 프로젝트 설정 | 요청 문구 "…" | 사용자 답변
- 패키지·버전: @hm-design/ui 0.1.0, …
- 재사용한 컴포넌트: …(Props 설정 포함)
- 조합한 부분: …
- AI가 새로 구현한 부분: 파일 경로 · 이유(카탈로그에 없음) · 안쪽에서 재사용한 컴포넌트
- 적용한 디자인 토큰: --hm-… (신규 UI가 읽은 것)
- AI 구성 값 — 디자인 확인 필요: 없음 | 속성 · 값 · 이유(4단계 ③)
- 원본 대비 변경(기존 화면 전환 시 필수, 4단계 "원본 보존"): 원본 대비 변경 없음 | 아래 표
| 원본 요소 | 변경 내용 | 변경 근거 |
|---|---|---|
| 예: 기존 아이콘 | HMDesign 아이콘으로 대체 | 지침 조항(파일·조항) 또는 컴포넌트 미지원(미지원 항목·대안 검토) |
| 예: 기존 상태 표시 | 적용하지 않음 — 변경 필요 여부 확인 | 판단 — 사용자 승인 필요 |
- 카탈로그와 .d.ts 차이: 없음 | …
- 검증: Typecheck PASS · Build PASS · 브라우저(폭/상태) … · NOT VERIFIED: …
- 제안(구현하지 않음): …
```
## 8. 상황별 예시
### 예시 A — Web 화면 (목록 + 검색)
- 읽기: `node_modules/@hm-design/ui/ai/` → COMPOSITION_PATTERNS "목록 화면"
- 재사용: `LNB`(또는 `GNB`) 중 **하나**, `PageHeader`, `Card`, `FilterBar` + `FilterBarSearch` + `FilterBarActions`, `DataTable` + `useDataTable`, `Button`
- 신규(필요 시만): 카탈로그에 없는 콘텐츠 블록 → 소비 프로젝트 컴포넌트, `--hm-sem-*` 토큰과 `Card` 재사용
```css
/* src/index.css */
@import "tailwindcss";
@import "@hm-design/ui/tailwind.css";
@import "@hm-design/ui/theme.css";
```
```tsx
import { Button, Card, CardContent, FilterBar, FilterBarActions, FilterBarSearch, PageHeader, PageHeaderContent, PageHeaderTitle } from "@hm-design/ui"
```
### 예시 B0 — "HMDesign SW로 화면을 만들어 주세요" (모드 미지정)
- 유형은 SW로 확정, 모드 근거가 없으므로 코드 작성 전에 1단계 4번의 모드 질문만 합니다. 답에 따라 B1 또는 B2로 진행합니다.
- 소비 프로젝트 설정이 `HMDesign 사용 유형: SW 일반` 또는 `SW 뷰어`이면 묻지 않고 바로 B1/B2입니다.
### 예시 B1 — SW 일반 모드 (편집 Header + 도구 막대 + 설정 Popup)
- 읽기: `node_modules/@hm-design/sw/ai/` → AI_USAGE §0(일반 모드) → COMPOSITION_PATTERNS "6. 파일 열기 + 도구 막대", 예제 `ai/examples/ExampleF-ViewerToolbar.tsx`(파일 이름의 Viewer는 과거 명칭이며 일반 모드 `SWHeader` 예제)
- 재사용: `SWHeader`(`documentOpenPlacement="header"`, `controls`, `tools`), `SWToolGroup` + `SWToolButton`(Model/Layout 탭, Fit 등), `SWPopup` + `SWPopupSection` + `SWPopupRow` + `SWHeaderInput`(설정 Popup), 로고(홈) 버튼 메뉴는 `SWHeader`의 `homeMenu` + `SWRecentFiles`(**일반 모드 전용**, 예제 `ExampleG-HomeMenu.tsx`)
- 신규: SW에 없는 기능(예: 검색) → 소비 프로젝트 컴포넌트, `<SWTheme>` 안, `--hm-sw-header-*` 토큰, 안쪽 입력은 `SWHeaderInput`(예제 `ExampleD-SearchExtension.tsx`)
```tsx
import { SWHeader, SWPopup, SWTheme, SWToolButton, SWToolGroup } from "@hm-design/sw"
import "@hm-design/sw/styles.css"
```
### 예시 B2 — SW 뷰어 모드 (뷰어 Header + 메뉴 + 패널)
- 읽기: `node_modules/@hm-design/sw/ai/` → AI_USAGE §0(뷰어 모드) → `VIEWER.md`, 예제 `ai/examples/ExampleH-ViewerMode.tsx`
- 재사용: `SWViewerHeader`(`groups` 데이터: `button`·`toggle`·`menu`·`tabs`·`switch`·`custom` 항목, `onCommand`, `trailing`에 `SWViewerStatus`·`SWViewerHeaderButton`. 창 최소화·닫기가 필요한 버전은 `trailing` 맨 끝에 `SWHeaderWindowControls showWindowMove={false}` — VIEWER.md §2.1), Dropdown은 `type: "menu"` 항목의 `entries`(단독·우클릭은 `SWViewerMenu`), 팝업은 `SWViewerPanel` + `SWViewerSection`·`SWViewerField`·`SWViewerSwitch`·`SWViewerInput`·`SWViewerButton`, 옵션 패널 게이지는 `SWSlider appearance="property"`(스타일 B, VIEWER.md §4)
- 신규: 뷰어에 없는 패널 콘텐츠 → 소비 프로젝트 컴포넌트를 `SWViewerPanel`의 `children`에, 안쪽은 `SWViewerField` + `SWViewerInput` 등, 외형은 `--hm-sw-viewer-*` 토큰
- 하지 않음: `SWHeader`·`SWPopup`을 뷰어 화면에 섞기(예외: 위 `trailing` 끝의 `SWHeaderWindowControls` 최소화·닫기), 로고(홈) 메뉴(`SWHomeMenu`·`SWRecentFiles`·`homeMenu`)를 뷰어 화면에 넣거나 비슷하게 만들기(홈 메뉴는 일반 모드 전용), 레이어 Popup의 레이어별 표시·숨김을 `SWViewerSwitch`·Checkbox·눈 아이콘으로 만들기(전구 `SWLayerVisibilityIcon` 아이콘 버튼 필수, 전체 레이어도 상단의 같은 전구 버튼 하나, VIEWER.md §4.1), 로고가 없다고 임의 문자·아이콘 넣기, 연결할 명령이 없는 메뉴를 가짜 동작으로 만들기(제외 또는 `disabled` + 미연결 보고)
```tsx
import { SWViewerHeader, SWViewerPanel, SWViewerSection, SWViewerField, SWViewerSwitch, type SWViewerHeaderGroup } from "@hm-design/sw"
import "@hm-design/sw/styles.css"
```
### 예시 C — 조직도만 (Chart Only)
- 읽기: `node_modules/@hm-design/org-chart/ai/` → COMPOSITION_PATTERNS "1. Chart Only"
- 재사용: React `OrgChart`(`@hm-design/org-chart-react`) 또는 Vanilla `createOrgChart`, 데이터 `JsonOrgChartDataSource` + `validateOrgChartDataset`
- 필수 옵션: `layoutMode="auto"` + `presentationMode="chart-only"`(초기 Fit·직접 휠 Zoom이 기본)
- **추가하지 않음:** 페이지 제목·통계·설명·Zoom 버튼 바·외부 회색 배경·Navigation. Fixed Chart Only는 미지원(`TypeError`)
```tsx
import { OrgChart } from "@hm-design/org-chart-react"
import { JsonOrgChartDataSource } from "@hm-design/org-chart"
import engineUrl from "@hm-design/org-chart/engine.css?url" // Vite. 다른 도구는 실제 배포 URL
import coreUrl from "@hm-design/org-chart/style.css?url"
```
### 예시 D — Web + OrgChart (Full Page)
- 영역: 페이지 레이아웃·제목·필터 = Web, 조직도 영역 = OrgChart
- 읽기: Web `ai/` + OrgChart `ai/COMPOSITION_PATTERNS.md` "2. Full Page"
- 재사용: Web `LNB`/`GNB` 중 하나, `PageHeader`, `Card`, `Select`·`Label`(회사 선택 등 요청된 컨트롤만) + OrgChart `OrgChart`(`selectedCompanyIds` 등 Props로 연결)
- 직원 팝업을 Web Dialog로: `import { OrgChart } from "@hm-design/org-chart-react/hm-dialog"` + `employeePopup="hm-dialog"`(Web CSS 진입점 필요)
- 분리: 조직도 카드·색은 OrgChart 기본 유지. Web 토큰을 조직도에 넣지 않음(바꿔야 하면 `--hm-orgchart-*` 공개 입력만)
## 9. 소비 프로젝트 설정 — AI가 이 지침을 찾게 하기
AI 코딩 도구는 보통 **프로젝트 루트의** `AGENTS.md`(Codex 등)·`CLAUDE.md`(Claude Code)·도구별 규칙 파일만 자동으로 읽고 `node_modules`는 읽지 않습니다. 패키지 설치만으로 지침이 자동 적용되지는 않으므로 소비 프로젝트에서 한 번 연결합니다.
1. 패키지에 들어 있는 `ai/AGENTS_SNIPPET.md`를 루트 `AGENTS.md`(없으면 새로 만듦)에 붙여 넣고 `HMDesign 사용 유형:` 줄을 프로젝트에 맞게 고칩니다. 값은 `Web` / `SW 일반` / `SW 뷰어` / `OrgChart` / `혼합(영역별: 예 "페이지 = Web, 중앙 = OrgChart")` 중 하나입니다. SW 프로젝트면 모드까지 적어야 AI가 모드를 다시 묻지 않습니다(`SW`만 적으면 모드를 묻습니다). 정하지 않았으면 그 줄을 지워 AI가 1단계에서 묻게 합니다.
```bash
cat node_modules/@hm-design/ui/ai/AGENTS_SNIPPET.md >> AGENTS.md
```
(PowerShell: `Get-Content node_modules/@hm-design/ui/ai/AGENTS_SNIPPET.md | Add-Content AGENTS.md`. 설치한 아무 HMDesign 패키지의 사본이나 같습니다.)
2. Claude Code는 `CLAUDE.md`에 `@AGENTS.md` 한 줄을 두면 같은 내용을 읽습니다. 다른 도구(Cursor 규칙 등)는 그 도구의 규칙 파일에 같은 내용을 넣습니다.
3. 패키지를 업데이트한 뒤 스니펫이 바뀌었는지 확인합니다(스니펫은 경로 안내만 하므로 보통 그대로 둡니다).
자동으로 되지 않는 것: 패키지 설치 시 루트 파일 생성(`postinstall` 없음), 도구가 `node_modules`를 스스로 탐색하는 것. 위 연결이 없으면 사용자가 "node_modules/@hm-design/…/ai/AI_GUIDE.md를 먼저 읽어"라고 요청해야 합니다.
**Git Submodule + npm Workspace로 연결한 경우**(현재 공식 연결 방식. HM 패키지는 npm Registry로 배포하지 않으므로 HMDesign 저장소를 예: `HMDesign/` 폴더에 Submodule로 고정하고 `workspaces`에 `HMDesign/packages/<패키지>`를 등록한 구성): `node_modules/@hm-design/<패키지>`는 `HMDesign/packages/<패키지>`로 연결되므로 지침 위치는 위 표와 같습니다(`HMDesign/packages/<패키지>/ai/`와 같은 파일). 공개 진입점은 `dist/`를 가리키므로 HMDesign 폴더 안에서 `npm ci`와 `npm run build:packages`를 먼저 실행해야 하며, `dist/`가 없으면 Import 오류를 컴포넌트 결함으로 보고하지 말고 빌드 필요로 보고합니다. HMDesign 저장소 루트의 `AGENTS.md`·`CLAUDE.md`는 HMDesign 개발용이므로 소비 프로젝트 지침으로 쓰지 않습니다. `npm install @hm-design/<패키지>@<버전>`처럼 Registry에서 설치하거나 `.npmrc`에 `@hm-design:registry`를 추가하지 않습니다.
## 10. 문서 갱신 (HMDesign 저장소 유지보수자)
컴포넌트를 추가·수정하면 같은 변경에서 해당 패키지 `ai/COMPONENT_CATALOG.md`와 필요한 `DESIGN_RULES.md`·`COMPOSITION_PATTERNS.md`를 갱신하고 `npm run check:ai-docs`를 통과시킵니다. 절차는 저장소 `docs/ai/MAINTAINING.md`(패키지 미포함)에 있습니다.