1
0
Fork 0
Everything2Everything/docs/tdd/03_DESIGN_AUDIT_TDD.md
Yun Chan 4cd9c678c0
Some checks are pending
Forgejo Release / build-and-release (push) Waiting to run
feat(tdd): implement SSOT canon, AGENTS.md, ultra-strict design audit, E2E scenarios, and Forgejo release pipeline
2026-09-03 12:21:40 +09:00

68 lines
6.8 KiB
Markdown

# 03. 초엄격 데스크톱 UI & 디자인 감사 TDD (Design Audit TDD)
> "A great desktop user experience is not accidental; it is mathematically verifiable through deterministic layout assertions and design token constraints."
이 문서는 데스크톱 WPF 애플리케이션에서 **시각적 치우침, 폰트 미가독, 컨테이너 오버플로, 인풋창 패딩 오류, 아이콘-텍스트 기준선 불일치, 끔찍한 UX 결함**을 단위 테스트 수준에서 철저하게 잡아내기 위한 **디자인 감사 TDD 규약**을 정의한다.
---
## 1. UI 테스트의 역사적 난제와 결정론적 해결책
### 1.1 깨지기 쉬운(Fragile) 픽셀 매칭의 한계
* 전체 화면 캡처 후 픽셀 단위로 비교하는 방식은 Windows OS 버전, ClearType 폰트 렌더링 서브픽셀 차이, 그래픽 드라이버 안티앨리어싱 때문에 1픽셀만 달라져도 테스트가 깨지는 치명적인 플레이키(Flaky) 문제를 낳는다.
* 이는 개발자로 하여금 UI 테스트를 무시하거나 비활성화하게 만드는 주범이다.
### 1.2 Everything2Everything의 3계층 디자인 감사 솔루션
1. **계층 1: XAML 정적 AST(구문 트리) 토큰 감사**
- 빌드된 XAML 파일을 XML DOM/AST로 파싱하여 모든 레이아웃 컨테이너, 버튼, 인풋, 텍스트블록의 속성을 검사.
- 0.1초 만에 실행되며, 어떤 파일 몇 번째 줄에서 디자인 규약이 위반되었는지 정확히 집어냄.
2. **계층 2: In-Memory STA Visual Tree 배치 및 경계(Bounds) 감사**
- 백그라운드 STA 스레드에서 창과 컨트롤을 메모리상에 생성하고 `Measure()``Arrange()`를 호출.
- 자식 요소가 부모 컨테이너의 영역을 벗어나 잘려나가는지(Clipping/Overflow), 최소 클릭 타깃 높이(32px)를 만족하는지 검증.
3. **계층 3: 복합 사용자 유즈케이스 E2E 시나리오 감사**
- 커맨드 바인딩, 큐 상태 전이, 텍스트 입력, 빈 상태(Empty State) 전환을 실제 데이터 흐름으로 검증.
---
## 2. 초엄격 디자인 감사 7대 원약 (Strict Design Rules)
### 규칙 1: 아이콘-텍스트 수직 기준선 중앙 정렬 (Vertical Alignment)
* **결함 현상**: `StackPanel Orientation="Horizontal"` 안에 아이콘(16px~24px)과 텍스트(12px~14px)가 들어갈 때, `VerticalAlignment="Center"`를 명시하지 않으면 WPF 기본값인 `Top` 또는 `Stretch`로 인해 아이콘과 텍스트가 위아래로 어긋나 끔찍한 시각적 불균형을 초래함.
* **감사 규칙**:
- 가로 방향 `StackPanel` 내부에 `Image`, `Path`, `ui:SymbolIcon`, `Ellipse`(상태 점)와 `TextBlock`이 공존하는 경우, 부모 `StackPanel``VerticalAlignment="Center"`가 지정되어 있거나, 내부의 모든 자식 요소에 `VerticalAlignment="Center"`가 선언되어 있어야 한다.
### 규칙 2: 인풋창 내부 요소 패딩 (Input Field Padding)
* **결함 현상**: `TextBox`, `PasswordBox`, `ComboBox`의 내부 패딩이 0이거나 너무 좁으면 입력 텍스트의 글리프(g, y, p, j의 디센더 또는 대문자)가 테두리에 닿거나 왼쪽 벽에 달라붙어 극도로 답답한 인상을 줌.
* **감사 규칙**:
- 모든 `TextBox``PasswordBox` 스타일의 `Padding`은 **수평 최소 8px 이상, 수직 최소 4px 이상**이어야 한다. (권장: `10,8` 또는 `12,8`).
- 좌우/상하 패딩이 기형적으로 비대칭인 값(예: `0,6` 또는 `20,1`)은 금지한다.
### 규칙 3: 유니코드 이모지 혼용 및 다국어 통일 (No Raw Emojis in Text)
* **결함 현상**: `Content="⚙ 설정"`처럼 텍스트 문자열 안에 유니코드 특수문자나 이모지를 날것으로 섞으면, OS 폰트 렌더링에 따라 이모지가 흑백 글리프로 왜곡되거나 텍스트 베이스라인이 위아래로 심하게 요동침. 또한 어떤 버튼은 영문("Diagnose", "Export Log"), 어떤 버튼은 한글("설정")로 혼용되는 조악한 UX 발생.
* **감사 규칙**:
- 버튼이나 메뉴 항목에 유니코드 이모지(`⚙`, `📁`, `🗑`, `✖` 등)를 텍스트 문자열에 인라인으로 포함하는 것을 엄격히 금지한다.
- 아이콘이 필요한 경우 Fluent UI의 표준 벡터 심볼(`ui:SymbolIcon`) 또는 일관된 `Path`를 분리된 엘리먼트로 배치한다.
- 상단 네비게이션 및 액션 버튼은 한국어로 완전 통일(`설정`, `컨텍스트 메뉴 등록`, `진단`, `로그 내보내기`, `목록 비우기`)한다.
### 규칙 4: 컨테이너 오버플로 및 텍스트 트림 (Overflow & Clipping Safety)
* **결함 현상**: 파일 경로, 파일명, 상태 메시지가 긴 경우 상위 컨테이너 너비를 뚫고 나가 다른 열의 버튼을 가리거나 화면 밖으로 잘려나감.
* **감사 규칙**:
- 동적 데이터(바인딩)를 표시하는 모든 `TextBlock`은 반드시 `TextTrimming="CharacterEllipsis"` 또는 `TextWrapping="Wrap"`을 지정해야 한다.
- 고정 너비가 아닌 가변 너비 컬럼(`*` 컬럼) 내에서 생략 부호(`...`)가 자연스럽게 동작하도록 컨테이너 제약을 설정해야 한다.
### 규칙 5: 폰트 명도 대비 및 테마 가독성 (WCAG 2.2 AA Contrast)
* **결함 현상**: 다크 모드 배경(`#090A0C`, `#131417`) 위에서 텍스트 색상이 너무 어두운 회색(`#3A3D45` 이하)이어서 글자가 전혀 보이지 않거나 가독성이 현저히 떨어짐.
* **감사 규칙**:
- 본문 텍스트(`FsTextPrimary`: `#ECEEFA`, 대비율 > 14:1)와 부가 텍스트(`FsTextSecondary`: `#8B909A`, 대비율 > 4.8:1)는 WCAG AA 표준(4.5:1)을 무조건 충족해야 한다.
- 극소형 캡션(10~11px)이라도 대비율 3.0:1 미만의 브러시 사용을 금지한다.
### 규칙 6: 제로-보이드 빈 상태 원칙 (Zero-Void Empty State)
* **결함 현상**: 큐나 결과 목록에 아이템이 없을 때 아무런 안내도 없이 시커먼 빈 공간만 덩그러니 노출되면, 사용자는 프로그램이 멈추었거나 고장 난 것으로 오인함.
* **감사 규칙**:
- `ActiveQueue`뿐만 아니라 `PastResults`(변환 이력) 화면 역시 데이터가 없을 때 표시되는 **전용 빈 상태(Empty State) 안내(일러스트 또는 아이콘 + 명확한 설명 문구)**가 반드시 존재해야 한다.
### 규칙 7: 8px 그리드 시스템 및 일관된 패딩 (Spacing System)
* **결함 현상**: 마진과 패딩에 3, 7, 11, 13, 23px 등 무작위 숫자가 혼재하여 전체 인터페이스의 시각적 리듬감이 깨짐.
* **감사 규칙**:
- 모든 `Margin``Padding`은 원칙적으로 **4px, 8px, 12px, 16px, 20px, 24px, 32px**의 4/8 배수 단위를 준수한다.
- 형제(Sibling) 버튼 간의 크기나 패딩은 동일한 위계(Hierarchy)에서 반드시 일치해야 한다 (예: 확인/취소 버튼의 패딩 통일).