156 lines
5.8 KiB
Markdown
156 lines
5.8 KiB
Markdown
# WACE 반응형 컴포넌트 전략
|
|
|
|
## 개요
|
|
|
|
WACE 프로젝트의 모든 반응형 UI는 **3개의 레이아웃 프리미티브 + 1개의 훅**으로 통일한다.
|
|
컴포넌트마다 새로 타입을 정의하거나 리사이저를 구현하지 않는다.
|
|
|
|
## 아키텍처
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────┐
|
|
│ useResponsive() 훅 │
|
|
│ isMobile | isTablet | isDesktop | width │
|
|
└──────────┬──────────┬──────────┬────────────────┘
|
|
│ │ │
|
|
┌───────▼──┐ ┌────▼─────┐ ┌─▼──────────────┐
|
|
│ 데이터 │ │ 좌우분할 │ │ 캔버스(디자이너)│
|
|
│ 목록 │ │ 패널 │ │ 화면 │
|
|
└──────────┘ └──────────┘ └────────────────┘
|
|
ResponsiveDataView ResponsiveSplitPanel ResponsiveGridRenderer
|
|
```
|
|
|
|
## 1. useResponsive (훅)
|
|
|
|
**위치**: `frontend/lib/hooks/useResponsive.ts`
|
|
|
|
모든 반응형 판단의 기반. 직접 breakpoint 분기가 필요할 때만 사용.
|
|
가능하면 아래 레이아웃 컴포넌트를 쓰고, 훅 직접 사용은 최소화.
|
|
|
|
| 반환값 | 브레이크포인트 | 해상도 |
|
|
|--------|---------------|--------|
|
|
| isMobile | xs, sm | < 768px |
|
|
| isTablet | md | 768 ~ 1023px |
|
|
| isDesktop | lg, xl, 2xl | >= 1024px |
|
|
|
|
## 2. ResponsiveDataView (데이터 목록)
|
|
|
|
**위치**: `frontend/components/common/ResponsiveDataView.tsx`
|
|
**패턴**: 데스크톱 = 테이블, 모바일 = 카드 리스트
|
|
**적용 대상**: 모든 목록/리스트 화면
|
|
|
|
```tsx
|
|
<ResponsiveDataView<User>
|
|
data={users}
|
|
columns={columns}
|
|
keyExtractor={(u) => u.id}
|
|
cardTitle={(u) => u.name}
|
|
cardFields={[
|
|
{ label: "이메일", render: (u) => u.email },
|
|
{ label: "부서", render: (u) => u.dept },
|
|
]}
|
|
renderActions={(u) => <Button>편집</Button>}
|
|
/>
|
|
```
|
|
|
|
**적용 완료 (12개 화면)**:
|
|
- UserTable, CompanyTable, UserAuthTable
|
|
- DataFlowList, ScreenList
|
|
- system-notices, approvalTemplate, standards
|
|
- batch-management, mail/receive, flowMgmtList
|
|
- exconList, exCallConfList
|
|
|
|
## 3. ResponsiveSplitPanel (좌우 분할)
|
|
|
|
**위치**: `frontend/components/common/ResponsiveSplitPanel.tsx`
|
|
**패턴**: 데스크톱 = 좌우 분할(리사이저 포함), 모바일 = 세로 스택(접기/펼치기)
|
|
**적용 대상**: 카테고리관리, 메뉴관리, 부서관리, BOM 등 좌우 분할 레이아웃
|
|
|
|
```tsx
|
|
<ResponsiveSplitPanel
|
|
left={<TreeView />}
|
|
right={<DetailPanel />}
|
|
leftTitle="카테고리"
|
|
leftWidth={25}
|
|
minLeftWidth={10}
|
|
maxLeftWidth={40}
|
|
height="calc(100vh - 120px)"
|
|
/>
|
|
```
|
|
|
|
**Props**:
|
|
| Prop | 타입 | 기본값 | 설명 |
|
|
|------|------|--------|------|
|
|
| left | ReactNode | 필수 | 좌측 패널 콘텐츠 |
|
|
| right | ReactNode | 필수 | 우측 패널 콘텐츠 |
|
|
| leftTitle | string | "목록" | 모바일 접기 헤더 |
|
|
| leftWidth | number | 25 | 초기 좌측 너비(%) |
|
|
| minLeftWidth | number | 10 | 최소 좌측 너비(%) |
|
|
| maxLeftWidth | number | 50 | 최대 좌측 너비(%) |
|
|
| showResizer | boolean | true | 리사이저 표시 |
|
|
| collapsedOnMobile | boolean | true | 모바일 기본 접힘 |
|
|
| height | string | "100%" | 컨테이너 높이 |
|
|
|
|
**동작**:
|
|
- 데스크톱(>= 1024px): 좌우 분할 + 드래그 리사이저 + 좌측 접기 버튼
|
|
- 모바일(< 1024px): 세로 스택, 좌측 패널 40vh 제한, 접기/펼치기
|
|
|
|
**마이그레이션 후보**:
|
|
- `V2CategoryManagerComponent` (완료)
|
|
- `SplitPanelLayoutComponent` (v1, v2)
|
|
- `BomTreeComponent`
|
|
- `ScreenSplitPanel`
|
|
- menu/page.tsx (메뉴 관리)
|
|
- departments/page.tsx (부서 관리)
|
|
|
|
## 4. ResponsiveGridRenderer (디자이너 캔버스)
|
|
|
|
**위치**: `frontend/components/screen/ResponsiveGridRenderer.tsx`
|
|
**패턴**: 데스크톱(비전폭 컴포넌트) = 캔버스 스케일링, 그 외 = Flex 그리드
|
|
**적용 대상**: 화면 디자이너로 만든 동적 화면
|
|
|
|
이 컴포넌트는 화면 디자이너 시스템 전용. 일반 개발에서 직접 사용하지 않음.
|
|
|
|
## 사용 가이드
|
|
|
|
### 새 화면 만들 때
|
|
|
|
| 화면 유형 | 사용 컴포넌트 |
|
|
|-----------|--------------|
|
|
| 데이터 목록 (테이블) | `ResponsiveDataView` |
|
|
| 좌우 분할 (트리+상세) | `ResponsiveSplitPanel` |
|
|
| 디자이너 화면 | `ResponsiveGridRenderer` (자동) |
|
|
| 단순 레이아웃 | Tailwind 반응형 (`flex-col lg:flex-row`) |
|
|
|
|
### 금지 사항
|
|
|
|
1. 컴포넌트 내부에 `isDraggingRef`, `handleMouseDown/Move/Up` 직접 구현 금지
|
|
-> `ResponsiveSplitPanel` 사용
|
|
2. `hidden lg:block` / `lg:hidden` 패턴으로 테이블/카드 이중 렌더링 금지
|
|
-> `ResponsiveDataView` 사용
|
|
3. `window.innerWidth` 직접 체크 금지
|
|
-> `useResponsive()` 훅 사용
|
|
4. 반응형 분기를 위한 새로운 타입/인터페이스 정의 금지
|
|
-> 기존 프리미티브의 Props 사용
|
|
|
|
### 폐기 예정 컴포넌트
|
|
|
|
| 컴포넌트 | 대체 | 상태 |
|
|
|----------|------|------|
|
|
| `ResponsiveContainer` | Tailwind 또는 `useResponsive` | 미사용, 삭제 예정 |
|
|
| `ResponsiveGrid` | Tailwind `grid-cols-*` | 미사용, 삭제 예정 |
|
|
| `ResponsiveText` | Tailwind `text-sm lg:text-lg` | 미사용, 삭제 예정 |
|
|
|
|
## 파일 구조
|
|
|
|
```
|
|
frontend/
|
|
├── lib/hooks/
|
|
│ └── useResponsive.ts # 브레이크포인트 훅 (기반)
|
|
├── components/common/
|
|
│ ├── ResponsiveDataView.tsx # 테이블/카드 전환
|
|
│ └── ResponsiveSplitPanel.tsx # 좌우 분할 반응형
|
|
└── components/screen/
|
|
└── ResponsiveGridRenderer.tsx # 디자이너 캔버스 렌더러
|
|
```
|