5.2 KiB
5.2 KiB
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+ | 동일 | 대형 태블릿 가로 |
핵심 변경
// 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() 사용으로 일관성 확보 |
뷰어 모드 감지 방식 변경
// 변경 전: 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칸 (태블릿으로 재분류) |
세로 자동 확장 (추가 결정)
배경
"세로는 신경쓸 필요가 없는 것 맞지? 그렇다면 캔버스도 세로 무한 스크롤이 가능해야겠네?"
결정
- 뷰포트 프리셋에서 height 제거 (width만 유지)
- 캔버스 높이 동적 계산 (컴포넌트 배치 기준)
- 항상 여유 행 3개 유지 (추가 배치 공간)
- 뷰어에서 터치 스크롤 지원
구현
// 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 - v5 그리드 시스템 채택
- 006-auto-wrap-review-system.md - 자동 줄바꿈
결론: 실제 기기 뷰포트 기반 브레이크포인트로 일관성 확보 + 세로 무한 스크롤로 UX 개선