# 모바일 반응형 패턴 가이드 > 작성일: 2026-01-10 > 적용 범위: SAM 프로젝트 전체 > 주요 대상 기기: Galaxy Z Fold 5 (접힌 상태 344px) --- ## 1. 브레이크포인트 정의 ### 1.1 Tailwind 기본 브레이크포인트 | 접두사 | 최소 너비 | 대상 기기 | |--------|----------|----------| | (기본) | 0px | Galaxy Fold 접힌 (344px) | | `xs` | 375px | iPhone SE, 소형 모바일 | | `sm` | 640px | 대형 모바일, 소형 태블릿 | | `md` | 768px | 태블릿 | | `lg` | 1024px | 소형 데스크탑 | | `xl` | 1280px | 데스크탑 | | `2xl` | 1536px | 대형 데스크탑 | ### 1.2 커스텀 브레이크포인트 (tailwind.config.js) ```javascript // tailwind.config.js module.exports = { theme: { screens: { 'xs': '375px', // iPhone SE 'sm': '640px', 'md': '768px', 'lg': '1024px', 'xl': '1280px', '2xl': '1536px', // Galaxy Fold 전용 (선택적) 'fold': '344px', }, }, } ``` ### 1.3 주요 테스트 뷰포트 | 기기 | 너비 | 높이 | 우선순위 | |------|------|------|----------| | Galaxy Z Fold 5 (접힌) | **344px** | 882px | 🔴 필수 | | iPhone SE | 375px | 667px | 🔴 필수 | | iPhone 14 Pro | 393px | 852px | 🟡 권장 | | iPad Mini | 768px | 1024px | 🟡 권장 | | Desktop | 1280px+ | - | 🟢 기본 | --- ## 2. 공통 패턴별 해결책 ### 2.1 그리드 레이아웃 #### 문제 344px에서 `grid-cols-2`는 각 항목이 ~160px로 좁아져 텍스트 오버플로우 발생 #### 해결 패턴 **패턴 A: 1열 → 2열 → 4열 (권장)** ```tsx // Before
// After - 344px에서 1열
``` **패턴 B: 최소 너비 보장** ```tsx // 카드 최소 너비 보장 + 자동 열 조정
``` **패턴 C: Flex Wrap (항목 수 가변적일 때)** ```tsx
{/* 카드 내용 */}
``` #### 적용 기준 | 카드 개수 | 권장 패턴 | |-----------|----------| | 1-2개 | `grid-cols-1 xs:grid-cols-2` | | 3-4개 | `grid-cols-1 xs:grid-cols-2 md:grid-cols-4` | | 5개+ | `grid-cols-1 xs:grid-cols-2 md:grid-cols-3 lg:grid-cols-4` | --- ### 2.2 테이블 반응형 #### 문제 테이블이 344px 화면에서 가로 스크롤 없이 표시 불가 #### 해결 패턴 **패턴 A: 가로 스크롤 (기본)** ```tsx
{/* 테이블 내용 */}
``` **패턴 B: 카드형 변환 (복잡한 데이터)** ```tsx {/* 데스크탑: 테이블 */} {/* 테이블 내용 */}
{/* 모바일: 카드 리스트 */}
{data.map((item) => (
거래처 {item.vendor}
{/* 추가 필드 */}
))}
``` **패턴 C: 컬럼 숨김 (우선순위 기반)** ```tsx 등록일 수정일 필수 컬럼 {item.createdAt} {item.updatedAt} {item.essential} ``` --- ### 2.3 카드 컴포넌트 #### 문제 카드 내 금액, 라벨이 좁은 화면에서 잘림 #### 해결 패턴 **패턴 A: 텍스트 크기 반응형** ```tsx // Before

30,500,000,000원

// After

30.5억원

``` **패턴 B: 금액 포맷 함수 개선** ```typescript // utils/format.ts export const formatAmountResponsive = (amount: number, compact = false): string => { if (compact || amount >= 100000000) { // 억 단위 const billion = amount / 100000000; return billion >= 1 ? `${billion.toFixed(1)}억원` : formatAmount(amount); } if (amount >= 10000) { // 만 단위 const man = amount / 10000; return `${man.toFixed(0)}만원`; } return new Intl.NumberFormat('ko-KR').format(amount) + '원'; }; ``` **패턴 C: 라벨 줄바꿈 허용** ```tsx // Before

현금성 자산 합계

// After

현금성 자산 합계

``` **패턴 D: Truncate + Tooltip** ```tsx

{longLabel}

``` --- ### 2.4 모달/다이얼로그 #### 문제 모달이 344px 화면에서 좌우 여백 없이 꽉 차거나 넘침 #### 해결 패턴 **패턴 A: 최대 너비 반응형** ```tsx // Before // After ``` **패턴 B: 전체 화면 모달 (복잡한 내용)** ```tsx ``` **패턴 C: 모달 내부 스크롤** ```tsx {/* 헤더 */}
{/* 스크롤 가능한 내용 */}
{/* 푸터 */}
``` --- ### 2.5 버튼 그룹 #### 문제 여러 버튼이 가로로 나열될 때 344px에서 넘침 #### 해결 패턴 **패턴 A: Flex Wrap** ```tsx // Before
// After
``` **패턴 B: 세로 배치 (모바일)** ```tsx
``` **패턴 C: 아이콘 전용 (극소 화면)** ```tsx ``` --- ### 2.6 긴 텍스트 처리 #### 문제 긴 제목, 설명, 메시지가 좁은 화면에서 레이아웃 깨짐 #### 해결 패턴 **패턴 A: Truncate (한 줄)** ```tsx

{title}

``` **패턴 B: Line Clamp (여러 줄)** ```tsx

{description}

``` **패턴 C: Break Keep (한글 단어 단위)** ```tsx

가지급금 인정이자 4.6%, 법인세 및 연말정산 시 대표자 종합세 가중 주의

``` **패턴 D: 반응형 텍스트 크기** ```tsx

{title}

``` --- ### 2.7 헤더/네비게이션 #### 문제 페이지 헤더의 타이틀과 액션 버튼이 충돌 #### 해결 패턴 **패턴 A: 세로 배치 (모바일)** ```tsx

{title}

{description}

``` **패턴 B: 아이콘 버튼 (극소 화면)** ```tsx ``` --- ### 2.8 패딩/마진 반응형 #### 문제 데스크탑용 패딩이 모바일에서 공간 낭비 #### 해결 패턴 ```tsx // Before
// After
// 카드 내부 ``` --- ## 3. Tailwind 유틸리티 클래스 모음 ### 3.1 자주 사용하는 반응형 패턴 ```css /* 그리드 */ .grid-responsive-1-2-4: grid-cols-1 xs:grid-cols-2 md:grid-cols-4 .grid-responsive-1-2-3: grid-cols-1 xs:grid-cols-2 md:grid-cols-3 .grid-responsive-1-3: grid-cols-1 md:grid-cols-3 /* 텍스트 */ .text-responsive-sm: text-xs xs:text-sm .text-responsive-base: text-sm xs:text-base .text-responsive-lg: text-base xs:text-lg md:text-xl .text-responsive-xl: text-lg xs:text-xl md:text-2xl .text-responsive-2xl: text-xl xs:text-2xl md:text-3xl /* 패딩 */ .p-responsive: p-3 xs:p-4 md:p-6 .px-responsive: px-3 xs:px-4 md:px-6 .py-responsive: py-3 xs:py-4 md:py-6 /* 갭 */ .gap-responsive: gap-2 xs:gap-3 md:gap-4 /* Flex 방향 */ .flex-col-to-row: flex-col xs:flex-row ``` ### 3.2 커스텀 유틸리티 (globals.css) ```css /* globals.css */ @layer utilities { .grid-responsive-cards { @apply grid grid-cols-1 xs:grid-cols-2 md:grid-cols-4 gap-3 xs:gap-4; } .text-amount { @apply text-xl xs:text-2xl md:text-3xl font-bold; } .card-padding { @apply p-3 xs:p-4 md:p-6; } .section-padding { @apply p-4 xs:p-5 md:p-6; } } ``` --- ## 4. 적용 체크리스트 ### 4.1 페이지 단위 체크리스트 ```markdown ## 페이지: [페이지명] 테스트 뷰포트: 344px (Galaxy Fold) ### 레이아웃 - [ ] 헤더 타이틀/액션 버튼 충돌 없음 - [ ] 그리드 카드 오버플로우 없음 - [ ] 사이드바 접힘 상태 정상 ### 텍스트 - [ ] 제목 텍스트 잘림/줄바꿈 정상 - [ ] 금액 표시 가독성 확보 - [ ] 라벨 텍스트 truncate 또는 줄바꿈 ### 테이블 - [ ] 가로 스크롤 정상 동작 - [ ] 필수 컬럼 표시 확인 - [ ] 체크박스/액션 버튼 접근 가능 ### 카드 - [ ] 카드 내용 오버플로우 없음 - [ ] 터치 영역 충분 (최소 44px) - [ ] 카드 간 간격 적절 ### 모달 - [ ] 화면 내 완전히 표시 - [ ] 닫기 버튼 접근 가능 - [ ] 내부 스크롤 정상 ### 버튼 - [ ] 버튼 그룹 wrap 정상 - [ ] 터치 영역 충분 - [ ] 아이콘/텍스트 가독성 ``` ### 4.2 컴포넌트 단위 체크리스트 ```markdown ## 컴포넌트: [컴포넌트명] ### 필수 확인 - [ ] min-width 고정값 없음 또는 반응형 처리 - [ ] whitespace-nowrap 사용 시 truncate 동반 - [ ] grid-cols-N 사용 시 모바일 breakpoint 추가 - [ ] 패딩/마진 반응형 적용 ### 권장 확인 - [ ] 텍스트 크기 반응형 - [ ] 버튼 크기 반응형 - [ ] 아이콘 크기 반응형 ``` --- ## 5. 적용 사례 ### 5.1 CEO 대시보드 적용 예정 **현재 문제점**: - `grid-cols-2 md:grid-cols-4` → 344px에서 카드당 ~160px - 금액 "3,050,000,000원" 표시 → 잘림 - "현금성 자산 합계" 라벨 → 잘림 **적용 계획**: 1. 그리드: `grid-cols-1 xs:grid-cols-2 md:grid-cols-4` 2. 금액: `formatAmountResponsive()` 함수 사용 (억 단위) 3. 라벨: `break-keep` 또는 `truncate` 4. 카드 패딩: `p-3 xs:p-4 md:p-6` 5. 헤더 버튼: 아이콘 전용 옵션 **상세 계획**: `[PLAN] ceo-dashboard-refactoring.md` 참조 --- ## 6. 테스트 방법 ### 6.1 Chrome DevTools 설정 1. DevTools 열기 (F12) 2. Device Toolbar (Ctrl+Shift+M) 3. Edit → Add custom device: - Name: `Galaxy Z Fold 5 (Folded)` - Width: `344` - Height: `882` - Device pixel ratio: `3` - User agent: Mobile ### 6.2 권장 테스트 순서 1. **344px**: 최소 지원 너비 (Galaxy Fold) 2. **375px**: iPhone SE 3. **768px**: 태블릿 4. **1280px**: 데스크탑 ### 6.3 자동화 테스트 (Playwright) ```typescript // playwright.config.ts const devices = [ { name: 'Galaxy Fold', viewport: { width: 344, height: 882 } }, { name: 'iPhone SE', viewport: { width: 375, height: 667 } }, { name: 'iPad', viewport: { width: 768, height: 1024 } }, { name: 'Desktop', viewport: { width: 1280, height: 800 } }, ]; ``` --- ## 변경 이력 | 날짜 | 버전 | 변경 내용 | |------|------|----------| | 2026-01-10 | 1.0 | 초기 작성 |