ERP-node/popdocs/decisions/005-breakpoint-redesign.md

182 lines
5.2 KiB
Markdown
Raw Permalink Normal View History

# ADR 005: 브레이크포인트 재설계 (기기 기반)
**날짜**: 2026-02-06
**상태**: 채택
**의사결정자**: 시스템 아키텍트
---
## 상황 (Context)
### 문제 1: 뷰어에서 모드 전환 불일치
```
브라우저 수동 리사이즈 시:
- useResponsiveMode 훅: 768px 이상 → "tablet" 판정
- GRID_BREAKPOINTS: 768~839px → "mobile_landscape" (6칸)
결과: 768~839px 구간에서 모드 불일치 발생
```
### 문제 2: 기존 브레이크포인트 근거 부족
```
기존 설정:
- mobile_portrait: ~599px
- mobile_landscape: 600~839px
- tablet_portrait: 840~1023px
문제: 실제 기기 뷰포트와 맞지 않음
- iPad Mini 세로: 768px (mobile_landscape로 분류됨)
```
### 사용자 요구사항
> "현장 모바일 기기가 최소 8인치 ~ 최대 14인치,
> 핸드폰은 아이폰 미니 ~ 갤럭시 울트라 사이즈"
---
## 연구 (Research)
### 실제 기기 CSS 뷰포트 조사 (2026년 기준)
| 기기 | 화면 크기 | CSS 뷰포트 너비 |
|------|----------|----------------|
| iPhone SE | 4.7" | 375px |
| iPhone 16 Pro | 6.3" | 402px |
| Galaxy S25 Ultra | 6.9" | 440px |
| iPad Mini 7 | 8.3" | 768px |
| iPad Pro 11 | 11" | 834px (세로), 1194px (가로) |
| iPad Pro 13 | 13" | 1024px (세로), 1366px (가로) |
### 업계 표준 브레이크포인트
| 프레임워크 | 모바일/태블릿 경계 | 태블릿/데스크톱 경계 |
|-----------|------------------|-------------------|
| Tailwind CSS | 768px | 1024px |
| Bootstrap 5 | 768px | 992px |
| Material Design 3 | 600px | 840px |
**공통점**: 768px, 1024px가 거의 표준
---
## 결정 (Decision)
### 채택: 기기 기반 브레이크포인트
| 모드 | 너비 범위 | 변경 전 | 근거 |
|------|----------|--------|------|
| mobile_portrait | 0~479px | 0~599px | 스마트폰 세로 최대 440px |
| mobile_landscape | 480~767px | 600~839px | 스마트폰 가로, 767px까지 |
| tablet_portrait | 768~1023px | 840~1023px | iPad Mini 768px 포함 |
| tablet_landscape | 1024px+ | 동일 | 대형 태블릿 가로 |
### 핵심 변경
```typescript
// pop-layout.ts - GRID_BREAKPOINTS
mobile_portrait: { maxWidth: 479 } // was 599
mobile_landscape: { minWidth: 480, maxWidth: 767 } // was 600, 839
tablet_portrait: { minWidth: 768, maxWidth: 1023 } // was 840, 1023
tablet_landscape: { minWidth: 1024 } // 동일
// pop-layout.ts - detectGridMode()
if (viewportWidth < 480) return "mobile_portrait"; // was 600
if (viewportWidth < 768) return "mobile_landscape"; // was 840
if (viewportWidth < 1024) return "tablet_portrait";
// useDeviceOrientation.ts - BREAKPOINTS
TABLET_MIN: 768 // was 840
```
---
## 구현 (Implementation)
### 수정 파일
| 파일 | 변경 내용 |
|------|----------|
| `pop-layout.ts` | GRID_BREAKPOINTS 값 수정, detectGridMode() 조건 수정 |
| `useDeviceOrientation.ts` | BREAKPOINTS.TABLET_MIN = 768 |
| `PopCanvas.tsx` | VIEWPORT_PRESETS width 값 조정 |
| `page.tsx (뷰어)` | detectGridMode() 사용으로 일관성 확보 |
### 뷰어 모드 감지 방식 변경
```typescript
// 변경 전: useResponsiveModeWithOverride만 사용
const currentModeKey = getModeKey(deviceType, isLandscape);
// 변경 후: 프리뷰 모드와 일반 모드 분리
const currentModeKey = isPreviewMode
? getModeKey(deviceType, isLandscape) // 프리뷰: 수동 선택
: detectGridMode(viewportWidth); // 일반: 너비 기반
```
---
## 결과 (Consequences)
### 긍정적 효과
| 효과 | 설명 |
|------|------|
| **기기 커버리지** | 아이폰 SE ~ 갤럭시 울트라, 8~14인치 태블릿 모두 포함 |
| **업계 표준 호환** | 768px, 1024px는 거의 모든 프레임워크 기준점 |
| **일관성 확보** | GRID_BREAKPOINTS와 detectGridMode() 완전 일치 |
| **직관적 매핑** | 스마트폰 세로/가로, 태블릿 세로/가로 자연스럽게 분류 |
### 트레이드오프
| 항목 | 설명 |
|------|------|
| **기존 데이터 영향** | 600~767px 구간이 6칸→6칸 (영향 없음) |
| **768~839px 변경** | 기존 6칸→8칸 (태블릿으로 재분류) |
---
## 세로 자동 확장 (추가 결정)
### 배경
> "세로는 신경쓸 필요가 없는 것 맞지?
> 그렇다면 캔버스도 세로 무한 스크롤이 가능해야겠네?"
### 결정
1. **뷰포트 프리셋에서 height 제거** (width만 유지)
2. **캔버스 높이 동적 계산** (컴포넌트 배치 기준)
3. **항상 여유 행 3개 유지** (추가 배치 공간)
4. **뷰어에서 터치 스크롤** 지원
### 구현
```typescript
// PopCanvas.tsx
const MIN_CANVAS_HEIGHT = 600;
const CANVAS_EXTRA_ROWS = 3;
const dynamicCanvasHeight = useMemo(() => {
const maxRowEnd = visibleComps.reduce((max, comp) => {
return Math.max(max, comp.row + comp.rowSpan);
}, 1);
const totalRows = maxRowEnd + CANVAS_EXTRA_ROWS;
return Math.max(MIN_CANVAS_HEIGHT, totalRows * rowHeight);
}, [layout.components, ...]);
```
---
## 관련 문서
- [003-v5-grid-system.md](./003-v5-grid-system.md) - v5 그리드 시스템 채택
- [006-auto-wrap-review-system.md](./006-auto-wrap-review-system.md) - 자동 줄바꿈
---
**결론**: 실제 기기 뷰포트 기반 브레이크포인트로 일관성 확보 + 세로 무한 스크롤로 UX 개선