# 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 개선