# 제관웹 오프라인 단일파일 500PRO — 전 기능 전수조사 감사 보고서

- **대상 파일**: `E:\도진팩토리\3D스캔및티칭시스템\제관웹_오프라인_단일파일_500PRO.html` (41.7MB, 14,755줄, 내장파일 533개)
- **검사 방법**: 사본을 `http://127.0.0.1:8899` 로 서빙 후 실제 브라우저에서 클릭 + 코드 전수 분석. **원본 파일은 수정하지 않음.**
- **모델 기준**: 500PRO_R CANADA (캐나다 현장), 부품 159개, 조립순서 12스텝 — 정상 로드 확인
- **작성일**: 2026-09-14
- **표기 규칙**: `[실측]` = 실제로 눌러서 확인함 / `[코드]` = 코드 분석에 의한 추정

---

## 0. 한눈에 보는 통계

| 구분 | 개수 |
|---|---|
| 조사한 기능 총계 | **39개** |
| **정상** — 동작하고 복구 경로가 있음 | **15개** |
| **기본기 미비** — 동작은 하나 취소·되돌리기·개별삭제 중 하나 이상 없음 | **17개** |
| **고장 / 조용히 실패** — 눌러도 되지 않거나 반드시 실패함 | **7개** |

> 분류 기준 — *정상*: 눌러서 되고, 실수했을 때 되돌리거나 빠져나올 길이 있다(전역 undo든 ESC든 슬라이더 0 복귀든). *기본기 미비*: 기능 자체는 되지만 무를 방법이 없다. *고장*: 무반응이거나 오프라인에서 반드시 실패한다.
> 집계 대상은 "사용자가 누르는 기능" 39개다. 비활성 흐림 처리·저장 불가 배너·`__fab_embed` 파싱·세 손가락 스와이프 부재는 기능이 아니라 패턴/부재이므로 집계에서 제외하고 §5·§2에 서술만 했다.
> 39개 중 **실제로 클릭해 확인한 것 13개**, 나머지 26개는 코드 근거다.

> **핵심 한 줄**: 이 앱의 "전역 되돌리기"는 전역이 아니다. **기즈모로 부품을 끌어 옮긴 것 딱 하나만** 되돌려진다. 치수·핀·묶음·사진·복제 등 나머지 15개 이상의 기능은 Ctrl+Z 바깥에 영구히 놓여 있다.

---

## 1. ★ 심각도 "상" 요약 — 먼저 고칠 8가지

| # | 기능 | 무엇이 문제인가 | 근거 |
|---|---|---|---|
| **1** | **📦 제품 (현장 모드)** | **현장 모드에서 제품을 아예 불러올 수 없다.** 버튼을 눌러도 아무 일도 안 일어나고 오류 메시지조차 없다. 원인: 제품 목록 드롭다운이 상단 파일명(`#fab-filename`)에 매달려 뜨는데, 현장 모드 CSS가 그 파일명을 숨겨서(크기 0×0) 목록이 보이지 않는 곳에 열린다. **현장 모드가 태블릿 기본값**이므로 CEO가 아이패드로 열면 첫 화면에서 막힌다. | [실측] 클릭 무반응 → `FAB_LIB.openList()` 는 정상 실행되나 앵커 rect가 0×0. 고급 모드로 전환하자 그제서야 목록이 보임 |
| **2** | **되돌리기(전역 undo)** | **이름만 전역이다.** `pushAction()` 호출처가 파일 전체에서 **딱 1곳**(기즈모 드래그). 치수·핀·묶음·사진·복제·공정·주석 등은 등록조차 안 된다. 게다가 새 제품을 불러오면 스택이 통째로 초기화된다. | [코드] 4431 정의 / 4482 유일한 호출 / 4572 export. 타 모듈에서 `FAB_UNDO` 소비 0건 |
| **3** | **📏 치수 — 개별 삭제 불가** | 잰 치수를 **하나씩 지울 방법이 전혀 없다.** 오직 `🗑 치수 지우기`(전부 삭제)뿐. 치수 라벨 자체가 `pointer-events:none` 이라 **탭조차 되지 않는다.** 실수로 한 번 잘못 재면 전부 지우고 다시 재야 한다. | [실측] 라벨 `pointer-events=none`, `onclick=null`. [코드] `measClear()` 937–948, 전체삭제 버튼 994 |
| **4** | **📏 치수 — 취소(ESC) 없음** | ESC를 눌러도 측정 모드가 취소되지 않는다. 탈출은 `측정 끝` 버튼을 정확히 누르는 것뿐. | [실측] **실제 Escape 키** 입력 후에도 버튼이 `✎ 측정중 (1)` 그대로, 측정 바도 그대로 / [코드] 토글 해제 경로만 존재 1013–1020 |
| **5** | **치수 바 ↔ 조립순서 바 겹침** | 측정 중 뜨는 `🗑 치수 지우기 / 측정 끝` 바(847,829 226×62, z=2147483646)가 **조립순서 재생 컨트롤**(844,861 382×64, z=10)을 덮는다. 바이어 미팅 중 치수를 재다가 조립 애니메이션을 못 누르게 된다. | [실측] 두 요소 rect 실측 겹침 확인 |
| **6** | **🧪 구조해석 — 오프라인에서 비활성이 아님** | 지시서의 기대와 달리 **비활성화되지 않는다.** 패널이 완전히 살아 있는 모습으로 열리고 `해석 실행` 버튼도 파랗게 활성이다. 실제로는 `localhost:8097` 서버가 필요해 반드시 실패하며, 실패 메시지가 *"명령창에서 python fea_server.py 를 먼저 실행하세요"* — **아이패드를 든 CEO에게 PC 명령어를 보여준다.** 유일한 사전 경고는 재질 드롭다운 안 `SS275 (서버 미연결)` 라는 묻힌 글자뿐. | [실측] 패널 정상 오픈 + 해석 실행 클릭 / [코드] 11565 API 주소, 12522–12530 무조건 생성, 12107–12109 실패문구 |
| **7** | **SHIN 채팅 전송 — 완전 무반응** | 전송 버튼이 정상으로 보이고 눌리지만, **답도 없고 오류도 없다.** 입력창만 비워진다. `127.0.0.1:8093` 지식서버가 필요한데 오프라인 shim이 모든 절대 `http://` 주소를 차단한다. 파일 내 최악의 조용한 실패. | [코드] 13677 전송버튼, 13895 → 12856 빈 stub / [실측] 콘솔 `[SHIN] 지식서버(8093) 미가동` 경고 확인 |
| **8** | **🎤 음성 입력(STT) — 완전 무반응** | 마이크 권한 실패 시 `if(!ok) return;` 로 조용히 끝난다. **아무 메시지도 없다.** 눌러도 영원히 아무 일이 없다. | [코드] 13316 `ensureMic()`, 13350 무성 return |

> **⚠️ #1과 #6은 서로 맞물려 악화된다.** #1 때문에 현장 모드에서는 제품을 못 불러오므로 CEO는 **반드시 고급 모드로 넘어가야 한다.** 그런데 고급 모드가 바로 #6의 "살아있는 척하는 구조해석 버튼"이 있는 곳이다(현장 모드에서는 `#fab-actionbar` 가 숨겨져 이 버튼이 안 보인다). 즉 첫 번째 결함이 사용자를 두 번째 결함 앞으로 떠민다. 두 건은 상쇄되지 않고 겹친다.

### 심각도 "상" 이지만 성격이 다른 구조적 문제 2건

| # | 항목 | 내용 |
|---|---|---|
| **9** | **버튼 공장이 4개** | `recBtn` / `mk2` / `fieldBtn` / `makeBtn` — 버튼 만드는 함수가 4종류라 크기·색·간격 규칙이 **애초에 존재하지 않는다.** CEO가 말한 "버튼 위치 임의"의 진짜 원인은 취향이 아니라 이것이다. 이걸 하나로 합치지 않으면 배치를 고쳐도 다시 무너진다. |
| **10** | **로봇 팬던트가 최고 명당을 점거** | 왼쪽 세로 레일 전체(21개 버튼: 제어·티칭, JOG, 포인트 추가/수정/삭제, 홈 설정, ARC ON/OFF, TCP, I/O, 로그, 콘솔)가 **로봇 티칭 전용 기능**이다. 제관 뷰어 용도(바이어 미팅·현장 부품식별)와 무관한데 가장 좋은 자리를 전부 차지하고 있다. 전부 아이콘만 있고 글자가 없어 초보자는 무엇인지 알 수 없다. |

---

## 2. 기능별 전수 감사표

범례 — 동작: ✅정상 / ⚠️부분 / ❌고장·무반응
기본기: **취소**=작업 중 ESC 등으로 무를 수 있나 / **되돌리기**=전역 Ctrl+Z 대상인가 / **개별삭제**=만든 것을 하나씩 지울 수 있나

### 2-1. 치수·측정

| 기능 | 동작 | 취소 | 되돌리기 | 개별삭제 | 피드백 | 터치 | 심각도 | 권고 |
|---|---|---|---|---|---|---|---|---|
| 📏 치수 재기 | ✅ [실측] 1.772m 정상 표시 | ❌ ESC 무효 [실측] | ❌ [코드] | ❌ 라벨 pointer-events:none [실측] | ✅ 토스트+콘솔 | ⚠️ 66×30 (44 미만) | **상** | 라벨 탭 → `✕ 이 치수 삭제`. ESC=진행 중 점 취소. undo 등록 |
| 🗑 치수 지우기 | ✅ [코드 994] | — | ❌ | — | ✅ 토스트 | ⚠️ | **상** | 확인창 필수 + 되돌리기 토스트 |
| 측정 끝 | ✅ [실측] | — | — | — | ✅ | ⚠️ | 중 | 조립순서 바와 겹침 해소 |

### 2-2. 핀·사진·주석

| 기능 | 동작 | 취소 | 되돌리기 | 개별삭제 | 피드백 | 심각도 | 권고 |
|---|---|---|---|---|---|---|---|
| 📍 핀 찍기 | ✅ [코드 8489+] | ❌ | ❌ | ✅ 핀 삭제 9247 | ⚠️ 삭제 실패가 `console.warn` 만 [코드 9378] | 중 | 삭제 실패를 화면에 표시. undo 등록 |
| 핀사진 | ✅ [코드] | ❌ | ❌ | ✅ | ⚠️ 팝업 텍스트만 9371 | 중 | 동일 |
| 🕸 사진가지 | ✅ [코드 7640+] | ❌ | ❌ | ✅ 목록 제거 7857 (파일은 남음) | ⚠️ | 중 | 실제 삭제 여부 명시 |
| 사진 촬영 | ✅ 오프라인 정상 [코드 376–398 IndexedDB 에뮬] | — | ❌ | ✅ | ✅ | 하 | — |
| 부품별 주석 | ✅ [코드 5891–5895] | ❌ | ❌ | ✅ | ⚠️ | 중 | undo 등록 |

### 2-3. 형상 조작

| 기능 | 동작 | 취소 | 되돌리기 | 개별삭제 | 피드백 | 심각도 | 권고 |
|---|---|---|---|---|---|---|---|
| 기즈모 이동/회전 | ✅ [코드] | — | ✅ **유일** [코드 4482] | — | ⚠️ setStatus만, 토스트 없음 | 하 | 태블릿에선 상태줄이 안 보임 → 토스트 병행 |
| 💥 분해 슬라이더 | ✅ [코드 6564–6824] | ✅ 0으로 복귀 | ❌ | — | ✅ 토스트 (단위수 표시) | 하 | 설계상 가역이라 양호 |
| 격리(더블클릭) | ✅ | ✅ **ESC 지원** [코드 7168] | ❌ | — | ✅ | 하 | **모범 사례** — 다른 기능이 본받을 것 |
| 계층 진입/탈출 | ✅ | ✅ ESC | ❌ | — | ✅ | 하 | 양호 |
| 🖐 손조작 | ❌ 오프라인 사망 [코드 11408 동적 import CORS 차단] | — | — | — | ⚠️ 패널 먼저 열리고 글자만 빨개짐 | **상** | 지원 불가 시 버튼을 아예 만들지 말 것 |
| ⧉ 복사 / ⧉ 전체 복제 | ✅ [코드 4662/4685] | ❌ | ❌ | ✅ Delete키·🗑 4783 | ✅ setStatus | 중 | 복제/삭제 모두 undo 등록 |
| 🗑 (복제 삭제) | ✅ 원본은 보호됨 4710 | ❌ | ❌ | — | ✅ | 중 | 되돌리기 토스트 |
| 📦 묶음 만들기 | ✅ [코드 7545–7568] | ⚠️ 덮어쓰기 confirm만 | ❌ | ✅ 묶음 해제 7570 | ✅ setStatus | 중 | undo 등록 |
| ⟲ 전체 원위치 | ✅ [실측 활성화됨] | — | ❌ 이 동작 자체는 못 무름 | — | ⚠️ setStatus만 | 중 | 확인창 + 되돌리기 |
| ↩ 자세 초기화 | ✅ | ❌ | ❌ (자체 되돌리기 10217 별도) | ✅ 10217 | ⚠️ | 중 | 전역 undo로 통합 |

### 2-4. 되돌리기·복구

| 기능 | 동작 | 비고 | 심각도 |
|---|---|---|---|
| ↩ 되돌리기 / ↪ 다시하기 | ⚠️ **기즈모 전용** [실측: 치수 잰 뒤에도 여전히 흐림·`pointer-events:none`] | 스택 50개, 위치·회전·크기만 복원. 표시·부모·데이터 상태는 복원 안 됨. **새 제품 로드 시 초기화** | **상** |
| 비활성 시 흐림 처리 | ✅ [실측 opacity 0.32 + pointer-events none] | **모범 사례** — 잘 되어 있음 | — |
| 세 손가락 스와이프 실행취소 | ❌ 없음 | 아이패드 전 앱 공통 문법인데 미구현 | 중 |

### 2-5. 재생·타임라인

| 기능 | 동작 | 기본기 | 피드백 | 심각도 | 권고 |
|---|---|---|---|---|---|
| ▶ 조립순서 재생 | ✅ [실측] **실제 재생 확인** — 1/12 진행, 부품 분해 애니메이션 + 스텝 설명 자막 `2. 2110DN-0058-0013 — 취부` 표시 | 재생 중 분해 차단됨(양호) | ✅ 토스트 + 자막 | 하 | 속도조절·단계점프 없음(§3 참조) |
| ⏮ ◀스텝 ▶ 스텝▶ | ✅ [실측] ▶ 눌러 재생·⏸ 전환 확인 | ❌ 되돌리기 없음 | ✅ | **상** | 측정 중에는 치수 바에 가려져 누를 수 없음(#5) |
| 📅 타임라인 | ✅ [코드 749–765] | ❌ 취소·undo 없음 | ⚠️ | 중 | — |

### 2-6. 저장·백업

| 기능 | 동작 | 오프라인 | 기본기 | 심각도 |
|---|---|---|---|---|
| 💾 저장 | ✅ [코드 362–449 localStorage 오버레이] | ✅ 정상 | ❌ undo 없음 | 하 |
| ⬇ 작업백업 | ✅ Blob 다운로드 [코드 1121–1180] | ✅ 정상 | — | 하 |
| ⬆ 작업복원 | ✅ | ✅ 정상 | ✅ confirm 있음 1149 / ❌ 복원 후 되돌리기 불가 | 중 |
| 저장 불가 경고 배너 | ✅ [코드 1184–1196] | ✅ | **모범 사례** — `⚠ 저장 불가 모드` 상시 배너 | — |
| 📋 공정서 불러오기 / 📦 실행기록 저장 | ✅ [코드 12967–13016] | ✅ 정상 | ❌ | 하 |

### 2-7. 서버 의존 기능 (오프라인 판정)

> ⚠️ **중요**: 오프라인 shim이 **절대 `http://` 주소를 프로토콜과 무관하게 전부 차단**한다(코드 1062). 따라서 `localhost` 로 띄워도 이 기능들은 살아나지 않는다. 본 감사의 localhost 실측치 = 아이패드 `file://` 실제 동작과 동일하다.

| 기능 | 오프라인 처리 | 판정 | 심각도 |
|---|---|---|---|
| 🧪 구조해석 | ❌ **비활성 아님.** 살아있는 척하다 클릭 시 파이썬 명령어 안내 | **나쁨** | **상** |
| SHIN 채팅 전송 | ❌ 무반응·무오류 | **최악** | **상** |
| 🎤 음성 입력 | ❌ 완전 무음 실패 | **최악** | **상** |
| 👁 SHIN의 눈 (카메라) | ⚠️ 오류는 뜨나 파이썬 안내 | 나쁨 | 중 |
| 🎙 회의녹음 | ✅ **원인을 먼저 검사하고 사람 말로 안내**: *"오프라인 파일(file://)에서는 사파리 보안정책상 마이크를 쓸 수 없습니다"* [코드 289–299] | **모범 사례 ★** | — |
| AR 추적 | ✅ 지원 없으면 **버튼을 아예 만들지 않음** [코드 14741] | **모범 사례 ★** | — |
| AR (일반) | ❌ `isSecureContext` 로 막으려 했으나 `file://`에선 이 값이 true라 게이트가 안 걸림 → 엉뚱하게 "카메라 권한 확인" 오류 | 나쁨 | 중 |

### 2-8. 기타

| 기능 | 동작 | 심각도 | 비고 |
|---|---|---|---|
| 제품 전환 / 파일 열기(.obj) | ⚠️ 고급 모드에서만 정상 [실측 — CANADA 로드 성공]. **현장 모드에서는 무반응** [실측] | **상**(#1) | 기본 모드에서 못 쓰므로 "고장"으로 집계 |
| 부품 선택·이름 표시 | ✅ [코드 3839] | 하 | — |
| ⬚ 화면 맞춤 | ✅ [코드 4934] | 하 | 위치가 툴바 밖 별도 줄 |
| 공정 선택 | ✅ [코드 5593+] | 중 | undo 없음, 행 삭제만 가능 |
| 평면/정면/측면/등각 | ✅ [코드] | 하 | 50×25 — **터치 최소 44pt 미달** [실측 크기] |
| 현장모드 ↔ 고급모드 | ✅ [실측] 양방향 전환 확인 | 하 | — |
| `__fab_embed` 파싱 | ✅ 533개 로드 [실측] | 중 | try/catch 없음 — 실패 시 **완전 무증상 빈 앱** [코드 6행] |

---

## 3. 고도화 기회 (CEO 지시 추가 조사) — "빨리 먹을 수 있는 것" 순

효용/난이도 모두 상·중·하. 정렬 기준 = 효용 높고 난이도 낮은 순.

### 3-A. 지금 바로 (효용 상 · 난이도 하) — 1군

| # | 항목 | 효용 | 난이도 | 설명 |
|---|---|---|---|---|
| 1 | **되돌리기 토스트** | 상 | 하 | 무언가 만들거나 지울 때마다 하단에 `치수 1개 추가됨 — 되돌리기` 4초 표시. CEO 불만 3개(취소·되돌리기·개별삭제)를 **한 번에** 완화 |
| 2 | **치수 라벨 탭 → 개별 삭제** | 상 | 하 | `pointer-events` 만 켜고 삭제 버튼 붙이면 끝. #3 직접 해결 |
| 3 | **큰 글씨 치수 (발표 모드)** | 상 | 하 | 폰트 크기 배수 토글. 바이어 앞 가독성 |
| 4 | **세 손가락 스와이프 되돌리기** | 상 | 하 | 아이패드 표준 문법. 버튼보다 먼저 |
| 5 | **화면 캡처 → 사진첩 저장** | 상 | 하 | 이미 캡처 기능 있음. 다운로드만 연결 |
| 6 | **ESC = 모든 모드 취소 통일** | 상 | 하 | 격리(7168)에 이미 구현됨 → 나머지로 복사 |
| 7 | **조립 재생 속도 조절** | 중 | 하 | 슬라이더 1개. 미팅에서 "천천히 다시" 요청 대응 |
| 8 | **특정 단계로 점프** | 중 | 하 | 이미 스텝 번호 있음. 번호 탭 → 이동 |

### 3-B. 다음 (효용 상 · 난이도 중) — 2군

| # | 항목 | 효용 | 난이도 | 설명 |
|---|---|---|---|---|
| 9 | **발표 모드(화면 깔끔히)** | 상 | 중 | 버튼 대부분 숨기고 모델만. 바이어 미팅 전용 프리셋 |
| 10 | **부위별 메모를 3D에 꽂기** | 상 | 중 | 핀 기능 확장. 텍스트 말풍선 |
| 11 | **단면 보기(절단면)** | 상 | 중 | Three.js clipping plane. 붐 내부 설명 시 강력 |
| 12 | **치수 목록표 내보내기** | 상 | 중 | 잰 치수 CSV. 이미 배열로 들고 있음 |
| 13 | **수리 전/후 비교 뷰** | 상 | 중 | CANADA vs 수정제안서 obj 나란히/겹쳐. **바이어 설득력 최상** |
| 14 | **진행률 % · 남은 작업** | 중 | 중 | 타임라인 + 공정서 결합 |
| 15 | **백업 파일에 주석 포함** | 중 | 중 | 현재 주석이 백업에 안 들어감 → 협업 차단 요인 |
| 16 | **날짜별 현장 사진 ↔ 타임라인 연동** | 중 | 중 | 사진 기능 이미 있음, 날짜 축만 연결 |
| 17 | **단계별 사진 오버레이** | 중 | 중 | 조립 단계 ↔ 실제 촬영 사진 대조 |

### 3-C. 장기 (난이도 상) — 3군

| # | 항목 | 효용 | 난이도 |
|---|---|---|---|
| 18 | 각도 자동 인식 | 중 | 상 |
| 19 | 구멍 지름 자동 인식 | 상 | 상 |
| 20 | 판 두께 자동 인식 | 상 | 상 |
| 21 | 도면값 대비 오차 표시 | 상 | 상 (도면 수치 입력 경로 필요) |
| 22 | 두 사람 포인터 공유(실시간 협업) | 중 | 상 (서버 필요 — 오프라인 원칙과 충돌) |

### 3-D. 연출·전환 품질 (Astra급 데모 UX 대비 부족분)

| # | 항목 | 효용 | 난이도 | 현재 상태 |
|---|---|---|---|---|
| 23 | 패널 등장/퇴장 애니메이션 (150–200ms) | 중 | 하 | 지금은 **툭 나타났다 툭 사라짐** |
| 24 | 활성 모드 발광(glow) 표시 | 중 | 하 | 없음 |
| 25 | 카메라 이동 보간(easing) | 중 | 하 | 화면 맞춤이 순간이동 |
| 26 | 로딩 진행 표시 | 중 | 하 | 41MB 로딩 중 **아무 표시 없음** |
| 27 | 이모지 라벨 → 단색 선 아이콘 통일 | 중 | 중 | 기기마다 이모지 모양이 달라 "임의" 인상 증폭 |

---

## 4. UI 디자인 벤치마킹 (CEO 지시 추가 조사)

> 용어 — *툴바*: 버튼이 줄지어 있는 막대 / *오버플로*: 덜 쓰는 버튼을 `⋯ 더보기` 뒤에 숨기는 것 / *컨텍스트 액션*: 부품을 누르면 그 옆에 뜨는 작은 메뉴

### 4-1. 툴바 구성 원칙 — 벤치마크 4종

**Shapr3D (아이패드 CAD 표준, 최우선 참고)**
- 메뉴는 **왼쪽 한 줄에만** 반투명으로 얹힌다. 왼손잡이는 설정에서 좌↔우를 통째로 바꾼다.
- 핵심은 **적응형 메뉴**: 무언가를 선택하면 "다음에 쓸 것 같은 도구"를 예측해 메뉴가 바뀐다. **버튼을 찾아다니게 하지 않고, 버튼이 찾아온다.**
- 메뉴 맨 위는 **명령 검색** — 못 찾으면 이름으로 친다.

**SketchUp for iPad**
- **사용자 구성 단축 툴바 2개, 각 8칸 상한.** 회사가 "자주 쓰는 것만 8개"라는 상한을 정해 놓았다.
- **방사형 툴바** (펜슬 더블탭), **컨텍스트 메뉴 툴바** (고른 객체에 가능한 명령만 표시).

**Fusion 360 / Onshape 뷰어**
- 보기 전용 모드에서는 툴바를 거의 다 걷어내고 **화면맞춤 / 뷰큐브 / 부품목록 / 단면**만 남긴다. 편집 도구는 아예 안 보인다.

**Astra급 AI 데모 UX**
- 버튼이 항상 다 떠 있지 않고 필요할 때 부드럽게 나타난다. 상태를 글자가 아니라 **색과 움직임**으로 알린다. 하단 토스트에 **되돌리기 버튼을 같이 넣는다.**

**우리와의 대조**

| 저들 | 우리 |
|---|---|
| 왼쪽 **한 곳**에만 메뉴 | 왼쪽 레일 + 상단 줄 + 우측 부유 버튼 + 하단 바 → **4군데 분산** [실측] |
| 버튼 생성 규칙 1개 | **4종 공장** (recBtn/mk2/fieldBtn/makeBtn) ← "임의 배치"의 진짜 원인 |
| 상시 노출 8개 상한 | **77개 클릭 요소 동시 노출** [실측] |
| 상황별 적응형 | 항상 전부 표시 |

### 4-2. 우리 기능 사용빈도 순위 (바이어 미팅 / 현장 부품식별 / 수리계획 근거)

1. 뷰 회전·이동·확대(제스처) · 2. 부품 선택+이름 · 3. 화면 맞춤 · 4. 격리/숨기기 · 5. 되돌리기/취소 · 6. 치수+개별삭제 · 7. 분해 슬라이더 · 8. 핀+사진 · 9. 계층 트리 · 10. 조립순서 재생 · 11. 제품 전환 · 12. 자세 초기화 · 13. 기즈모·손조작·복사·묶음 · 14. 저장/백업/타임라인/녹음 · 15. 구조해석·공정·로봇 팬던트

### 4-3. 모드 전환 패턴

**문제**: 지금 select/move/rotate/measure 중 무엇이 켜져 있는지 화면만 봐선 모른다 → "아무 데나 눌렀는데 부품이 움직였다" 사고.

- **4-3-1. 상단 중앙 모드 배지 신설(상시).** `📏 측정 — 첫 번째 점을 누르세요   ✕ 취소`
- **4-3-2. 기본은 항상 "보기(선택)"**, 1회 작업 후 자동 복귀 (연속 사용은 길게 눌러 잠금)
- **4-3-3. 편집성 모드일 때 화면 테두리 2px 주황** = "지금 모델이 바뀔 수 있음"
- **4-3-4. `✕ 취소`는 모드 배지 안에만.** ESC 키도 동일 동작

### 4-4. 컨텍스트 액션

- **4-4-1.** 부품 1회 탭 = 선택 + 이름 + **부품 위쪽 가로 알약형 미니바** (원형은 손가락에 가려서 쓰지 않음)
- **4-4-2.** 미니바 고정 5칸: `[🔍 이 부품만] [👁 숨기기] [📏 여기서 측정] [📌 핀+사진] [⋯]`
- **4-4-3.** `⋯` 안: 부품 정보(치수·수량·재질), 색 바꾸기, 이 부품 원위치, 묶음 추가, 트리에서 보기
- **4-4-4.** 빈 공간 탭 = 선택 해제 (예외 없음)
- **4-4-5.** 길게 누르기 0.5초 = 다중 선택 시작 (진동 1회)
- **4-4-6.** 미니바 모든 동작은 되돌리기 토스트 4초

### 4-5. 제스처 관례 (반드시 지킬 것)

| # | 제스처 | 동작 |
|---|---|---|
| 4-5-1 | 한 손가락 드래그 | 회전 |
| 4-5-2 | 두 손가락 드래그 | 화면 이동 |
| 4-5-3 | 핀치 / 두 손가락 비틀기 | 확대·축소 / 롤 |
| **4-5-4** | **세 손가락 좌·우 스와이프** | **실행취소 / 다시실행 — CEO "취소 없음" 불만의 가장 값싼 해결책. 버튼보다 먼저 붙일 것** |
| 4-5-5 | 부품 길게 누르기 | 다중 선택 |
| 4-5-6 | 빈 곳 더블탭 | 화면 맞춤 |
| 4-5-7 | 애플펜슬 호버 | 누르기 전에 부품 이름 미리보기 (미팅 효과 큼) |
| 4-5-8 | **금지** | 한 손가락 스와이프 메뉴, 화면 가장자리 스와이프(iPadOS 충돌), 세 손가락 재정의 |

### 4-6. 시각 위계

- **4-6-1. 터치 타겟 최소 44×44pt** (Apple HIG). 현장 모드는 **64pt**(장갑 기준). → **현재 위반 다수**: 평면/정면/측면/등각 50×25, 치수 66×30, 타임라인 90×30, 파일명 200×17 [전부 실측]
- **4-6-2.** 버튼 간격 최소 8pt
- **4-6-3. 색은 딱 4가지**: 주요(청록 채움) / 보조(투명+회색테두리) / 위험(빨강 글씨) / 비활성(30% 흐림)
- **4-6-4. 빨강 버튼은 툴바에 절대 두지 않는다** → `⋯ 더보기` 안 + 확인창 1회
- **4-6-5. 한 번에 보이는 버튼 최대 9개** (툴바 8 + 더보기 1)
- **4-6-6.** 아이콘+글자 병기 기본. 아이콘 단독은 되돌리기/다시하기 2개만
- **4-6-7.** 이모지 라벨 폐기 → 단색 선 아이콘 통일
- **4-6-8.** 그룹 사이 1px 구분선 + 위아래 12pt 여백, 그룹 안은 4pt. **"가까운 것이 한 묶음"이 위치 규칙의 전부**
- **4-6-9. 버튼 공장을 `makeBtn` 하나로 통일** — 인자 `(아이콘, 라벨, 등급, 그룹)`. **이 항목 없이는 나머지 개편이 다시 무너진다**
- **4-6-10.** 모든 파괴적 동작에 4초 되돌리기 토스트

### 4-7. ★ 우리 툴바 개편 시안 ★

#### 4-7-A. 미팅 모드 (바이어 데모 기본값)

```
┌──────────────────────────────────────────────────────────────┐
│          📏 측정 — 첫 번째 점을 누르세요            ✕ 취소   │ ← 모드 배지(상단 중앙·상시)
└──────────────────────────────────────────────────────────────┘

 ┌────────┐
 │ 👆     │  보기       ← [G1] 기본·항상 켜짐 (앱 시작 상태)
 │ 이름   │
 ├────────┤               ─── 구분선 ───
 │ ⤢      │  화면맞춤    ← [G2] 길잡이
 │ 🔍     │  이 부품만   ←      (격리 / 다시 누르면 전체 복귀)
 ├────────┤               ─── 구분선 ───
 │ 📏     │  측정        ← [G3] 설명 도구
 │ ↔      │  분해        ←      (누르면 슬라이더가 하단에 뜸)
 │ ▶      │  조립순서    ←
 ├────────┤               ─── 구분선 ───
 │ ↩      │              ← [G4] 되돌리기 (아이콘만, 44pt)
 │ ↪      │              ←      다시하기
 ├────────┤               ─── 구분선 ───
 │ ⋯      │  더보기      ← [G5] 오버플로
 └────────┘
        ↑ 왼쪽 세로 1줄. 버튼 8개 + 더보기 1개. 이게 전부.

   [부품 탭 시 그 위에 뜨는 미니바]
   ╭─────────────────────────────────────────────╮
   │ 🔍 이부품만 │ 👁 숨기기 │ 📏 측정 │ 📌 핀 │ ⋯ │
   ╰─────────────────────────────────────────────╯

   [하단 임시 영역 — 필요할 때만]
   분해 ▐━━━━━●━━━━━▌ 40%       또는   ◀◀ ⏸ ▶▶  3/12단계

   [토스트 — 동작 후 4초]      치수 1개 추가됨      되돌리기
```

#### 4-7-B. 현장 모드 (장갑·햇빛·한 손)

```
┌──────────────────────────────────────────────────────────────┐
│  👆 보기 — 부품을 누르면 이름이 나옵니다           ⚙ 모드   │
└──────────────────────────────────────────────────────────────┘

 ┌──────────┐   ← 버튼 64pt, 글자 17pt 굵게, 고대비(검정 배경/흰 글씨)
 │   👆     │
 │ 이름보기 │
 ├──────────┤
 │   ⤢      │
 │ 화면맞춤 │
 ├──────────┤
 │   🔍     │
 │ 이부품만 │
 ├──────────┤
 │   📌     │
 │ 핀+사진  │   ← 현장 1순위. 미팅 모드보다 위로 승격
 ├──────────┤
 │   📏     │
 │   측정   │
 ├──────────┤
 │   ↩      │
 │ 되돌리기 │   ← 현장에선 아이콘만 금지, 글자 필수
 └──────────┘
      6개. 더보기 없음. 편집 기능 **전부 차단**.
      ※ 단, §1-#1(제품 로드 불가)을 먼저 고쳐야 이 모드가 쓸모 있어진다.
```

#### 4-7-C. 승인용 번호 목록 (그대로 구현자에게 전달 가능)

**[왼쪽 툴바에 남는 것 — 8개 + 더보기]**
1. `👆 보기` — 선택·이름표시. 앱 시작 기본값
2. `⤢ 화면맞춤` — 별도 줄에서 툴바 G2로 이동
3. `🔍 이 부품만` — 기존 격리. 토글식
4. `📏 측정` — 1회 측정 후 자동으로 보기 모드 복귀
5. `↔ 분해` — 누르면 하단에 슬라이더만 뜸
6. `▶ 조립순서` — 누르면 하단에 재생 컨트롤
7. `↩ 되돌리기` (아이콘만)
8. `↪ 다시하기` (아이콘만)
9. `⋯ 더보기`

**[`⋯ 더보기`로 강등]**
10. 계층(부품 트리) — 더보기 최상단, 우측 슬라이드 패널
11. 제품 전환 / 파일 열기(.obj)
12. 저장 / 작업 백업 / 작업 복원
13. 타임라인
14. 회의 녹음
15. 사진 촬영 / 핀사진 모아보기 / 사진가지
16. 자세 초기화 · 전체 원위치 (빨강, 확인창 필수)
17. 치수 전체 지우기 (빨강, 확인창 필수)
18. 묶음 만들기 / 복사 / 전체 복제
19. 설정 (왼손잡이 좌↔우, 모드 선택, 글자 크기)

**[컨텍스트 액션으로 전환 — 툴바에서 제거]**
20. 격리 → 미니바 `🔍 이 부품만` (툴바에도 중복 유지, 의도된 중복)
21. 숨기기 → 미니바 `👁 숨기기`
22. **개별 치수 삭제 → 치수 라벨 탭 시 `✕ 이 치수 삭제`** ★CEO "개별 삭제 없음" 직접 해결★
23. 핀 찍기 → 미니바 `📌 핀`
24. 부품 이름·정보 → 미니바 `⋯`
25. 부품 색 변경, 이 부품만 원위치 → 미니바 `⋯`

**[완전 숨김 — "전문가 모드" 스위치에서만 노출]**
26. **로봇 팬던트 툴바 전체** (제어·티칭/JOG/포인트/홈/ARC/TCP/I\O/로그/콘솔 — 21개). 미팅·현장 기본값에서 존재 자체를 감춘다
27. 구조해석(FEA)
28. 공정 선택
29. 손조작 / 기즈모 이동 / 기즈모 회전 (미팅 중 모델이 뜯어지는 사고의 주범)

**[신설]**
30. 상단 중앙 모드 배지 + `✕ 취소`
31. 하단 되돌리기 토스트
32. 세 손가락 스와이프 실행취소/다시실행
33. 애플펜슬 호버 부품 이름 미리보기
34. 명령 검색 (`⋯ 더보기` 최상단) — 기능이 30개 넘으므로 필수
35. **`makeBtn` 단일 공장 통일**, recBtn/mk2/fieldBtn 제거

**[구현 순서 권고]**
`35` → `30·31·32`(CEO 1순위 불만) → `§1-#1 현장모드 제품로드 수정` → `22 개별 치수 삭제` → `4-7-A 툴바 재배치` → `미니바` → `26~29 숨김` → `4-7-B 현장모드` → `33·34`

---

## 5. 잘 되어 있는 것 (유지·확산할 모범 사례)

1. **↩/↪/⟲ 버튼의 비활성 흐림 처리** — 누를 수 없을 때 opacity 0.32 + pointer-events none. 다른 버튼들도 이 패턴을 따를 것
2. **회의녹음의 오프라인 안내** — 원인을 먼저 검사하고 사람 말로 설명. **구조해석·SHIN·STT가 본받아야 할 표준**
3. **AR추적의 버튼 미생성** — 지원 안 되면 버튼을 아예 만들지 않음. 죽은 버튼 0개
4. **격리(isolate)의 ESC 탈출** — 취소 경로가 제대로 있는 유일한 기능
5. **저장 불가 모드 상시 배너** — 데이터 손실을 사전에 경고
6. **오프라인 저장소 shim** — localStorage/IndexedDB를 메모리로 대체, 사진 표시까지 monkey-patch로 해결. 기술적으로 훌륭
7. **분해 슬라이더의 가역성** — 0으로 되돌리면 원상복구. 설계 자체가 안전

---

## 6. 검사 한계 (정직 고지)

**① 네트워크 의존 기능 — localhost 실측 = `file://` 동작 (근거 있음)**
오프라인 shim이 **프로토콜과 무관하게** 절대 `http://` 주소를 전부 차단한다(코드 1062). 따라서 구조해석·SHIN 채팅·SHIN의 눈·음성입력·손조작의 실패는 localhost에서 본 것이 아이패드 `file://` 에서도 그대로 재현된다. 이 부분은 안심하고 §1·§2-7의 판정을 신뢰해도 된다.

**② 저장소 기능 — 미검증 (주의)**
localhost 에서는 `localStorage` 가 정상 동작하므로 shim이 메모리 모드로 떨어지지 않았고, 그래서 `⚠ 저장 불가 모드` 배너가 이번 세션에서 **한 번도 뜨지 않았다.** §2-6의 "저장 ✅ 오프라인 정상"과 §5-5의 배너 모범 사례는 **코드 근거일 뿐 실측이 아니다.** 아이패드 사파리 `file://` 에서 메모리 모드로 떨어지는 경로는 확인하지 못했다. 참고로 크롬에서 `file://` 로 열어도 사파리의 동작은 재현되지 않으므로, 이건 **아이패드 실기로만 확인 가능**하다.

**③ 터치**
실제 손가락 터치(멀티터치·제스처)는 검증하지 못했다. 터치 항목은 **버튼 크기 실측치**에 근거한 판정이다.

**④ 실측 비율**
39개 기능 중 실제 클릭으로 확인한 것은 13개, 나머지 26개는 코드 근거다. 표의 `[실측]`/`[코드]` 표기로 구분했다.
