# 반응형 웹 UI/UX 전면 개선 설계 > 모바일에서 UI 짤림 현상 해결 + 풀 모바일 경험 적용 > 작성일: 2026-04-23 > 리뷰 반영: 2026-04-23 (라우트 경로 수정, breakpoint 예외 명시, 구현 복잡도 보완) --- ## 1. 목표 - 전체 15개 뷰(12개 라우트 + 3개 서브라우트)에서 모바일 UI 짤림 현상 해결 - 현재 다크 네온 사이버펑크 디자인 톤 유지 - 모바일 전용 UX 패턴 추가 (바텀 네비게이션, 스와이프, 풀다운 리프레시, FAB, 바텀시트) - 기능적 손실 없이 반응형 적용 **대상 뷰 목록 (routes.jsx 기준):** | # | 라우트 | 컴포넌트 | 비고 | |---|--------|---------|------| | 1 | `/` | Home | | | 2 | `/lotto` | Lotto | 3탭 (Briefing/Analysis/Purchase) | | 3 | `/stock` | Stock | | | 4 | `/stock/trade` | StockTrade | 서브라우트 | | 5 | `/travel` | Travel | | | 6 | `/blog` | Blog | | | 7 | `/blog-lab` | BlogMarketing | | | 8 | `/realestate` | Subscription | | | 9 | `/music` | MusicStudio | | | 10 | `/todo` | Todo | | | 11 | `/agent-office` | AgentOffice | | | 12 | `/lab` | EffectLab | | | 13 | `/lab/sword-stream` | SwordStream | 서브라우트 | | 14 | `/lab/day-calc` | DayCalc | 서브라우트 | > Note: `RealEstate.jsx` (`/realestate/property`)는 routes.jsx에 미등록 상태. 반응형 스코프에서 제외. --- ## 2. 접근 방식 **글로벌 모바일 시스템 구축 → 주요 페이지 적용 → 전체 페이지 확장** 1. 공통 모바일 인프라(컴포넌트, breakpoint, 앱 셸) 구축 2. 주요 4개 페이지 (홈, 로또, 주식, 여행) 우선 적용 3. 나머지 페이지 확장 적용 --- ## 3. 글로벌 모바일 인프라 ### 3-1. Breakpoint 시스템 통일 현재 53개 미디어 쿼리에서 다양한 값이 혼재. 4단계로 통일: | 이름 | 값 | 용도 | |------|-----|------| | sm | 480px | 소형 폰 | | md | 768px | 태블릿/대형 폰 (주요 분기점) | | lg | 1024px | 소형 데스크톱 | | xl | 1280px | 대형 데스크톱 | 기존 미디어 쿼리의 비표준 값(640px, 900px, 960px, 1100px 등)은 기능 손실 없이 가장 가까운 표준 breakpoint로 정리한다. **허용 예외 (이동 시 시각적 회귀 발생):** | 기존 값 | 파일 | 사유 | |---------|------|------| | 420px | Stock.css (4곳) | 소형 폰 전용 패딩/라벨 축소, 480px로 이동 시 중간 기기에서 불필요한 축소 | | 520px | Stock.css (1곳) | 지표 카드 특수 레이아웃 | | 700px | Stock.css (1곳) | AI 코치 설정 그리드, 768px로 이동 시 태블릿에서 조기 축소 | 위 값들은 해당 페이지 CSS에서 기존 값을 유지한다. ### 3-2. 바텀 네비게이션 바 (`BottomNav`) - 768px 이하에서 사이드바 대신 표시 - 주요 5개 메뉴 아이콘 + "더보기" 메뉴 (나머지 페이지) - 현재 페이지 활성 표시 — 네온 시안 글로우 유지 - 사이드바는 모바일에서 완전히 숨김 (기존 햄버거→슬라이드 방식 제거) - 높이: 56~64px - `env(safe-area-inset-bottom)` 대응 (노치/홈 인디케이터 기기) - `index.html`에 `viewport-fit=cover` 추가 필요: `` - 더보기 메뉴: 탭 시 위로 펼쳐지는 오버레이 패널 **사이드바→바텀네비 마이그레이션 상세:** - `Navbar.jsx`: 768px 이하에서 사이드바 렌더링 제거, `sidebar-toggle` 버튼 제거 - `Navbar.css`: `.sidebar` transform/transition 미디어 쿼리 제거, `.sidebar__overlay` 제거 - `Navbar.jsx` useEffect: `body.overflow = 'hidden'` 토글 로직 정리 - `App.jsx`에서 `BottomNav` 컴포넌트 조건부 렌더링 (`useIsMobile()` 기반) **더보기 메뉴 내용 (나머지 네비게이션 항목):** | 순서 | 아이콘 | 라벨 | 경로 | |------|--------|------|------| | 1 | 음악 | 뮤직 | `/music` | | 2 | 로봇 | 에이전트 | `/agent-office` | | 3 | 블로그 | 블로그 | `/blog` | | 4 | 마케팅 | 블로그랩 | `/blog-lab` | | 5 | 건물 | 청약 | `/realestate` | | 6 | 체크 | TODO | `/todo` | | 7 | 실험 | 이펙트랩 | `/lab` | **기본 5개 메뉴 구성:** | 순서 | 아이콘 | 라벨 | 경로 | |------|--------|------|------| | 1 | 홈 | 홈 | `/` | | 2 | 클로버 | 로또 | `/lotto` | | 3 | 차트 | 주식 | `/stock` | | 4 | 카메라 | 여행 | `/travel` | | 5 | 더보기 | 메뉴 | 오버레이 | ### 3-3. 공통 모바일 컴포넌트 | 컴포넌트 | 파일 | 역할 | |---------|------|------| | `BottomNav` | `src/components/BottomNav.jsx` | 하단 고정 네비게이션 | | `PullToRefresh` | `src/components/PullToRefresh.jsx` | 터치 풀다운 새로고침 래퍼 | | `SwipeableView` | `src/components/SwipeableView.jsx` | 좌우 스와이프 탭/뷰 전환 | | `FAB` | `src/components/FAB.jsx` | 플로팅 액션 버튼 (바텀 네비 위 배치) | | `MobileSheet` | `src/components/MobileSheet.jsx` | 바텀시트 모달 (드래그 핸들, 스냅 포인트) | **공통 훅 (신규 `src/hooks/` 디렉토리 생성):** > 기존 훅은 페이지별 디렉토리에 colocate (`src/pages/lotto/hooks/` 등). > 모바일 인프라 훅은 여러 페이지에서 공유하므로 `src/hooks/`에 배치한다. | 훅 | 파일 | 역할 | |----|------|------| | `useIsMobile` | `src/hooks/useIsMobile.js` | 768px 이하 감지 (matchMedia) | | `useSwipe` | `src/hooks/useSwipe.js` | 터치 스와이프 방향·거리 감지 | **경량 라이브러리 활용:** - `react-swipeable` (~3KB gzipped): SwipeableView/useSwipe 기반으로 활용 — 터치 velocity, threshold snap, 방향 판별을 직접 구현하지 않음 - PullToRefresh: 터치 이벤트 직접 구현하되, iOS Safari rubber-banding 및 `overscroll-behavior: contain` 대응 필수 - MobileSheet: CSS `transform` + `touch-action: none`으로 구현, 스냅 포인트 2단계 (50%, 90%) ### 3-4. 앱 셸 레이아웃 변경 ``` 데스크톱: [사이드바 240px] [콘텐츠] 모바일: [탑바 56px] [콘텐츠 (padding-bottom: 바텀네비 높이)] [바텀 네비 56-64px] ``` - 콘텐츠 영역에 `padding-bottom` 추가 (바텀 네비 겹침 방지) - 탑바: 현재 구조 유지, 페이지 타이틀 + 액션 버튼 영역 - `body` overflow: 모바일에서 auto (현재와 동일) --- ## 4. 주요 페이지별 모바일 설계 ### 4-1. 홈 (Home) — `/` | 영역 | 데스크톱 | 모바일 (≤768px) | |------|---------|-----------------| | 히어로 | 2컬럼 그리드 | 1컬럼 스택, 타이틀 축소 | | 네비 카드 그리드 | auto-fill minmax(180px) | 2컬럼 고정, 카드 높이 축소 | | TODO 보드 | 3컬럼 칸반 | 스와이프 탭 (Todo/진행중/완료) | | 블로그 포스트 | 카드 그리드 | 1컬럼 리스트 | | 프로필 섹션 | 사이드 카드 | 하단 접이식 패널 | - 풀다운 리프레시: 블로그 포스트 갱신 - FAB: 없음 (네비게이션 허브) ### 4-2. 로또 (Lotto) — `/lotto` | 영역 | 데스크톱 | 모바일 | |------|---------|--------| | 3탭 구조 | 상단 탭바 | 스와이프 탭 전환 | | 브리핑 탭 | 카드 레이아웃 | 1컬럼, 볼 크기 36→32px | | 분석 탭 | 그리드 카드 | 1컬럼 스택 | | 구매 이력 테이블 | 6컬럼 그리드 | 가로 스크롤 테이블 + 행 터치 바텀시트 | | 번호 추천 카드 | 다중 그리드 | 1컬럼, 볼 간격 조정 | | 전략 차트 | 넓은 차트 | 가로스크롤 또는 축소 | - FAB: "추천받기" (빠른 번호 추천) - 풀다운 리프레시: 브리핑/분석 데이터 갱신 ### 4-3. 주식 (Stock / StockTrade) — `/stock`, `/stock/trade` **Stock (뉴스/지표)** | 영역 | 데스크톱 | 모바일 | |------|---------|--------| | 헤더 | 2컬럼 | 1컬럼 스택 | | 뉴스 그리드 | auto-fit minmax(260px) | 1컬럼 카드 리스트 | | 필터 | 가로 나열 | 가로 스크롤 칩 바 | | 지표 카드 | 그리드 | 가로 스크롤 카드 캐러셀 | **StockTrade (매매)** | 영역 | 데스크톱 | 모바일 | |------|---------|--------| | 포트폴리오 테이블 | 넓은 테이블 | 카드형 리스트 (종목별 카드) | | 매도 이력 | 테이블 | 가로 스크롤 + 행 터치 바텀시트 | | 자산 차트 | 넓은 recharts | 풀 너비, 축 라벨 축소 | | 예수금 섹션 | 인라인 | 접이식 카드 | - FAB: "종목 추가" (Stock), "매도 기록" (StockTrade) - 풀다운 리프레시: 뉴스/포트폴리오 갱신 ### 4-4. 여행 (Travel) — `/travel` | 영역 | 데스크톱 | 모바일 | |------|---------|--------| | 지역 선택 | Leaflet 지도 | 높이 50vh→35vh, 핀치 줌 | | 사진 그리드 | 다중 컬럼 | 2컬럼 → 1컬럼 (≤480px) | | 사진 상세 | 모달 | 풀스크린 뷰어 + 스와이프 넘기기 | | 지역 필터 | 드롭다운 | 바텀시트 지역 선택 | - 풀다운 리프레시: 사진 목록 갱신 - FAB: 없음 --- ## 5. 나머지 페이지 모바일 설계 ### 5-1. 블로그 (Blog) — `/blog` | 영역 | 모바일 변경 | |------|------------| | 글 목록 | 1컬럼 리스트형 | | 글 상세 | 풀 너비, 폰트 크기 조정 | | 태그 필터 | 가로 스크롤 칩 바 | | 작성/수정 폼 | 풀 너비, 툴바 축소 | - FAB: "글 쓰기" - 풀다운 리프레시: 글 목록 갱신 ### 5-2. 블로그 마케팅 (BlogMarketing) — `/blog-lab` | 영역 | 모바일 변경 | |------|------------| | 대시보드 지표 | 2컬럼 → 1컬럼 (≤480px) | | 파이프라인 테이블 | 카드형 리스트 (상태 배지) | | 키워드 분석 | 접이식 아코디언 | | 수익 내역 | 가로 스크롤 테이블 | - FAB: "키워드 분석" - 풀다운 리프레시: 대시보드 갱신 ### 5-3. 부동산 청약 (Subscription) — `/realestate` | 영역 | 모바일 변경 | |------|------------| | 공고 목록 | 1컬럼 카드 리스트 | | 필터 | 바텀시트 필터 패널 | | 공고 상세 | 바텀시트 상세보기 | | 매칭 결과 | 1컬럼, 점수 강조 | | 대시보드 | 2컬럼 그리드 | - FAB: "공고 등록" - 풀다운 리프레시: 공고/매칭 갱신 ### 5-4. 뮤직 스튜디오 (MusicStudio) — `/music` | 영역 | 모바일 변경 | |------|------------| | 헤더 | 1컬럼, 타이틀 클램프 축소 | | 생성 폼 | 풀 너비 스택 | | 라이브러리 | 1컬럼 리스트 (앨범아트 + 제목) | | 플레이어 | 미니 플레이어 바텀 고정 (높이 56px, 바텀 네비 위 = bottom: 64px) | | 가사 에디터 | 풀 너비 | | 레이더 위젯 | 중앙 정렬 | - FAB: "음악 생성" - 풀다운 리프레시: 라이브러리 갱신 - 미니 플레이어 표시 시 콘텐츠 padding-bottom: 바텀네비(64px) + 미니플레이어(56px) = 120px ### 5-5. TODO — `/todo` | 영역 | 모바일 변경 | |------|------------| | 칸반 보드 | 스와이프 탭 (Todo/진행중/완료) | | 할일 카드 | 스와이프로 상태 변경 | | 입력 폼 | FAB → 바텀시트 입력 폼 | - FAB: "할일 추가" ### 5-6. 에이전트 오피스 (AgentOffice) — `/agent-office` | 영역 | 모바일 변경 | |------|------------| | 캔버스 오피스 | 풀스크린 캔버스, 핀치 줌/패닝 | | 에이전트 패널 | 바텀시트 에이전트 상세 | | 작업 로그 | 바텀시트 로그 뷰 | | 명령 입력 | 하단 입력 바 (채팅 UX) | | WebSocket 상태 | 탑바에 연결 상태 아이콘 | ### 5-7. 이펙트 랩 — `/lab`, `/lab/day-calc`, `/lab/sword-stream` | 페이지 | 모바일 변경 | |--------|------------| | EffectLab 허브 | 카드 그리드 → 1컬럼 리스트 | | DayCalc | 풀 너비 스택, 네이티브 날짜 피커 | | SwordStream | 풀스크린 캔버스, 터치 인터랙션 유지, 오버레이 축소 | --- ## 6. 터치 타겟 가이드라인 - 모든 터치 타겟: 최소 44×44px (Apple HIG 기준) - 버튼 간 간격: 최소 8px - FAB 크기: 56×56px - 바텀 네비 아이템: 최소 48×48px 터치 영역 --- ## 7. 성능 고려사항 - 모바일에서 글로우/그라디언트 효과: box-shadow 개수 줄이기 (3중→1중) - `background-attachment: fixed` → 모바일에서 `scroll` (현재 적용됨, 유지) - 이미지: `loading="lazy"` 속성 확인 - 스와이프/터치 이벤트: passive listener 사용 - 바텀시트 애니메이션: `transform` + `will-change` 사용 (layout thrashing 방지) - 신규 애니메이션(스와이프, 바텀시트, 풀다운)은 `prefers-reduced-motion: reduce` 쿼리 존중 — Travel.css, MusicStudio.css 기존 패턴과 통일 ### 주의: Stock.css / StockTrade.jsx 커플링 `StockTrade.jsx`는 `Stock.css`의 스타일을 공유한다. Stock.css의 반응형 수정은 StockTrade에도 영향을 미치므로, 반드시 두 페이지를 함께 검증해야 한다. --- ## 8. 구현 순서 ### Phase 1: 글로벌 인프라 **Phase 1a: Breakpoint 정리 (기존 CSS만 수정, 신규 코드 없음)** 1. Breakpoint 시스템 통일 — 각 CSS 파일의 비표준 미디어 쿼리를 표준 값으로 정리 2. `index.html`에 `viewport-fit=cover` 추가 3. 회귀 테스트: 정리 후 각 페이지 데스크톱/모바일 확인 **Phase 1b: 공통 컴포넌트 & 앱 셸** 4. `react-swipeable` 패키지 설치 5. `src/hooks/` 디렉토리 생성 + `useIsMobile`, `useSwipe` 훅 구현 6. `BottomNav` 컴포넌트 구현 + 사이드바 모바일 제거 마이그레이션 (Navbar.jsx/css 수정) 7. `PullToRefresh`, `SwipeableView`, `FAB`, `MobileSheet` 컴포넌트 구현 8. 앱 셸 레이아웃 수정 (App.jsx, App.css) ### Phase 2: 주요 페이지 적용 9. 홈 페이지 반응형 개선 10. 로또 페이지 반응형 개선 11. 주식 페이지 (Stock + StockTrade 함께 검증) 반응형 개선 12. 여행 페이지 반응형 개선 ### Phase 3: 나머지 페이지 확장 13. 블로그 (`/blog`) + 블로그 마케팅 (`/blog-lab`) 14. 부동산 청약 (`/realestate`) 15. 뮤직 스튜디오 (`/music`) 16. TODO (`/todo`) 17. 에이전트 오피스 (`/agent-office`) 18. 이펙트 랩 (`/lab` + `/lab/day-calc` + `/lab/sword-stream`) ### Phase 4: 검증 19. 전체 뷰 모바일 UI 검증 — 대상 뷰포트: 360px (Galaxy S), 390px (iPhone 14), 768px (iPad), 1024px (데스크톱) 20. `prefers-reduced-motion` 동작 확인 21. 터치 타겟 크기 검증 (44×44px 최소)