Files
web-page-backend/docs/superpowers/specs/2026-04-23-responsive-web-design.md
gahusb bd7875b36a docs: 반응형 설계 리뷰 피드백 반영
- 라우트 경로 수정 (/lab/music→/music, /blog-marketing→/blog-lab 등)
- /realestate/property 미등록 라우트 제외, 실제 14개 뷰로 정정
- breakpoint 예외 목록 명시 (420/520/700px)
- 사이드바→바텀네비 마이그레이션 상세 계획 추가
- react-swipeable 경량 라이브러리 활용 명시
- 미니플레이어+바텀네비 스태킹 사양 추가
- viewport-fit=cover, prefers-reduced-motion, 테스트 뷰포트 명시
- Phase 1을 1a(breakpoint 정리) + 1b(컴포넌트)로 세분화

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 14:17:07 +09:00

361 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 반응형 웹 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` 추가 필요: `<meta name="viewport" content="width=device-width, initial-scale=1.0, 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 최소)