Merge remote-tracking branch 'origin/master'
This commit is contained in:
386
claudedocs/[PLAN] mobile-overflow-testing.md
Normal file
386
claudedocs/[PLAN] mobile-overflow-testing.md
Normal file
@@ -0,0 +1,386 @@
|
||||
# 모바일 화면 오버플로우 테스트 계획서
|
||||
|
||||
> 작성일: 2026-01-09
|
||||
> 대상 기기: Galaxy Z Fold (접힌 상태)
|
||||
> 목표: 모든 페이지에서 텍스트/요소 오버플로우 검출 및 수정
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 목적
|
||||
Galaxy Fold 접힌 상태(344px)에서 UI 요소가 컨테이너를 벗어나거나 텍스트가 잘리는 문제를 사전에 발견하고 수정
|
||||
|
||||
### 1.2 대상 뷰포트
|
||||
|
||||
| 기기 | 너비 | 높이 | 비고 |
|
||||
|------|------|------|------|
|
||||
| Galaxy Z Fold 5 (접힌) | **344px** | 882px | 주요 테스트 대상 |
|
||||
| Galaxy Z Fold 5 (펼친) | 1812px | 882px | 참고용 |
|
||||
| iPhone SE | 375px | 667px | 비교 테스트 |
|
||||
|
||||
### 1.3 테스트 범위
|
||||
|
||||
**총 페이지 수: 185개**
|
||||
|
||||
| 카테고리 | 페이지 수 | 우선순위 |
|
||||
|----------|----------|----------|
|
||||
| construction (시공) | 40 | 🔴 높음 |
|
||||
| accounting (회계) | 26 | 🔴 높음 |
|
||||
| sales (영업) | 18 | 🔴 높음 |
|
||||
| settings (설정) | 17 | 🟡 중간 |
|
||||
| hr (인사) | 14 | 🟡 중간 |
|
||||
| production (생산) | 10 | 🟡 중간 |
|
||||
| quality (품질) | 4 | 🟢 낮음 |
|
||||
| reports (리포트) | 2 | 🟢 낮음 |
|
||||
| dashboard | 1 | 🔴 높음 |
|
||||
| 기타 | ~50 | 🟡 중간 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 테스트 방법
|
||||
|
||||
### 2.1 방법 A: Playwright 자동화 (권장)
|
||||
|
||||
**장점**
|
||||
- 전체 페이지 일괄 스크린샷
|
||||
- 반복 테스트 용이
|
||||
- 수정 후 비교 테스트 가능
|
||||
|
||||
**단점**
|
||||
- 초기 세팅 필요
|
||||
- 로그인/인증 처리 필요
|
||||
|
||||
**구현 방식**
|
||||
```typescript
|
||||
// playwright-mobile-test.ts
|
||||
import { chromium } from 'playwright';
|
||||
|
||||
const VIEWPORT = { width: 344, height: 882 };
|
||||
const BASE_URL = 'http://localhost:3000/ko';
|
||||
|
||||
const pages = [
|
||||
'/dashboard',
|
||||
'/sales/client-management-sales-admin',
|
||||
'/accounting/sales',
|
||||
// ... 전체 페이지 목록
|
||||
];
|
||||
|
||||
async function captureScreenshots() {
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext({
|
||||
viewport: VIEWPORT,
|
||||
// 로그인 쿠키 설정
|
||||
});
|
||||
|
||||
for (const page of pages) {
|
||||
const p = await context.newPage();
|
||||
await p.goto(`${BASE_URL}${page}`);
|
||||
await p.screenshot({
|
||||
path: `screenshots/fold/${page.replace(/\//g, '-')}.png`,
|
||||
fullPage: true
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**결과물**
|
||||
```
|
||||
screenshots/fold/
|
||||
├── dashboard.png
|
||||
├── sales-client-management-sales-admin.png
|
||||
├── accounting-sales.png
|
||||
└── ... (185개)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.2 방법 B: Chrome DevTools 수동 검수
|
||||
|
||||
**장점**
|
||||
- 즉시 시작 가능
|
||||
- 실시간 CSS 수정 테스트 가능
|
||||
- 인터랙션 확인 가능
|
||||
|
||||
**단점**
|
||||
- 시간 소요 (페이지당 1-2분)
|
||||
- 반복 테스트 불편
|
||||
|
||||
**설정 방법**
|
||||
1. Chrome DevTools (F12) 열기
|
||||
2. Device Toolbar (Ctrl+Shift+M) 활성화
|
||||
3. 기기 목록 → Edit → Add custom device
|
||||
4. 이름: `Galaxy Z Fold 5 (Folded)`
|
||||
5. 너비: `344`, 높이: `882`
|
||||
6. Device pixel ratio: `3`
|
||||
7. User agent: Mobile
|
||||
|
||||
**체크리스트**
|
||||
```markdown
|
||||
## 페이지: [페이지명]
|
||||
|
||||
### 레이아웃
|
||||
- [ ] 헤더 정상 표시
|
||||
- [ ] 사이드바 접힘/메뉴 버튼 표시
|
||||
- [ ] 메인 컨텐츠 영역 정상
|
||||
|
||||
### 텍스트
|
||||
- [ ] 제목 텍스트 오버플로우 없음
|
||||
- [ ] 버튼 텍스트 잘림 없음
|
||||
- [ ] 테이블 헤더 가독성 확인
|
||||
|
||||
### 테이블/리스트
|
||||
- [ ] 가로 스크롤 정상 동작
|
||||
- [ ] 컬럼 최소 너비 확보
|
||||
- [ ] 체크박스/액션 버튼 접근 가능
|
||||
|
||||
### 폼
|
||||
- [ ] 입력 필드 너비 적절
|
||||
- [ ] 라벨 텍스트 가독성
|
||||
- [ ] 버튼 터치 영역 충분 (최소 44px)
|
||||
|
||||
### 모달/팝업
|
||||
- [ ] 화면 내 표시
|
||||
- [ ] 닫기 버튼 접근 가능
|
||||
- [ ] 스크롤 정상 동작
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 방법 C: 혼합 방식 (권장)
|
||||
|
||||
1. **1단계**: Playwright로 전체 페이지 스크린샷 캡처
|
||||
2. **2단계**: 스크린샷에서 문제 있어 보이는 페이지 목록 작성
|
||||
3. **3단계**: 문제 페이지만 DevTools로 상세 검수
|
||||
4. **4단계**: 수정 후 Playwright로 재검증
|
||||
|
||||
---
|
||||
|
||||
## 3. 예상 문제 패턴
|
||||
|
||||
### 3.1 높은 위험도 🔴
|
||||
|
||||
| 패턴 | 예시 | 해결 방법 |
|
||||
|------|------|----------|
|
||||
| 고정 너비 테이블 | `min-w-[800px]` | 가로 스크롤 또는 반응형 |
|
||||
| 긴 텍스트 nowrap | `whitespace-nowrap` | `truncate` 또는 줄바꿈 |
|
||||
| 고정 px 버튼 그룹 | `w-[400px]` | `w-full` 또는 flex-wrap |
|
||||
| 큰 모달 | `max-w-4xl` | `max-w-[calc(100vw-2rem)]` |
|
||||
|
||||
### 3.2 중간 위험도 🟡
|
||||
|
||||
| 패턴 | 예시 | 해결 방법 |
|
||||
|------|------|----------|
|
||||
| Flex 오버플로우 | `flex gap-4` 자식 | `min-w-0` 추가 |
|
||||
| Grid 고정 컬럼 | `grid-cols-4` | `grid-cols-1 md:grid-cols-4` |
|
||||
| 이미지 고정 크기 | `w-[200px]` | `max-w-full` |
|
||||
|
||||
### 3.3 낮은 위험도 🟢
|
||||
|
||||
| 패턴 | 예시 | 해결 방법 |
|
||||
|------|------|----------|
|
||||
| 패딩 과다 | `p-8` | `p-4 md:p-8` |
|
||||
| 폰트 크기 | `text-xl` | `text-lg md:text-xl` |
|
||||
|
||||
---
|
||||
|
||||
## 4. 수정 가이드라인
|
||||
|
||||
### 4.1 테이블 반응형 처리
|
||||
|
||||
```tsx
|
||||
// Before
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-[800px]">
|
||||
|
||||
// After
|
||||
<div className="overflow-x-auto -mx-4 md:mx-0">
|
||||
<table className="min-w-[600px] md:min-w-[800px]">
|
||||
```
|
||||
|
||||
### 4.2 텍스트 오버플로우 처리
|
||||
|
||||
```tsx
|
||||
// Before
|
||||
<span className="whitespace-nowrap">{longText}</span>
|
||||
|
||||
// After
|
||||
<span className="truncate max-w-[200px]" title={longText}>{longText}</span>
|
||||
```
|
||||
|
||||
### 4.3 버튼 그룹 반응형
|
||||
|
||||
```tsx
|
||||
// Before
|
||||
<div className="flex gap-2">
|
||||
<Button>저장</Button>
|
||||
<Button>취소</Button>
|
||||
<Button>삭제</Button>
|
||||
</div>
|
||||
|
||||
// After
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button className="flex-1 min-w-[80px]">저장</Button>
|
||||
<Button className="flex-1 min-w-[80px]">취소</Button>
|
||||
<Button className="flex-1 min-w-[80px]">삭제</Button>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 4.4 모달 반응형
|
||||
|
||||
```tsx
|
||||
// Before
|
||||
<DialogContent className="max-w-2xl">
|
||||
|
||||
// After
|
||||
<DialogContent className="max-w-2xl w-[calc(100vw-2rem)]">
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 실행 계획
|
||||
|
||||
### 5.1 Phase 1: 환경 준비 (30분)
|
||||
|
||||
- [ ] Playwright 스크립트 작성
|
||||
- [ ] 로그인 토큰/쿠키 설정
|
||||
- [ ] 테스트 페이지 URL 목록 정리
|
||||
- [ ] 스크린샷 저장 폴더 생성
|
||||
|
||||
### 5.2 Phase 2: 스크린샷 캡처 (1-2시간)
|
||||
|
||||
- [ ] Playwright 스크립트 실행
|
||||
- [ ] 185개 페이지 스크린샷 캡처
|
||||
- [ ] 캡처 실패 페이지 확인 및 재시도
|
||||
|
||||
### 5.3 Phase 3: 문제 페이지 분류 (1시간)
|
||||
|
||||
스크린샷 검토 후 분류:
|
||||
|
||||
| 상태 | 설명 | 액션 |
|
||||
|------|------|------|
|
||||
| ✅ OK | 문제 없음 | 스킵 |
|
||||
| ⚠️ Minor | 경미한 문제 | 백로그 |
|
||||
| 🔴 Critical | 사용 불가 수준 | 즉시 수정 |
|
||||
|
||||
### 5.4 Phase 4: 수정 작업 (문제 수에 따라)
|
||||
|
||||
- [ ] Critical 문제 우선 수정
|
||||
- [ ] 수정 후 해당 페이지 재캡처
|
||||
- [ ] Before/After 비교 확인
|
||||
|
||||
### 5.5 Phase 5: 검증 (30분)
|
||||
|
||||
- [ ] 전체 재캡처
|
||||
- [ ] 수정 결과 확인
|
||||
- [ ] 결과 보고서 작성
|
||||
|
||||
---
|
||||
|
||||
## 6. 결과물
|
||||
|
||||
### 6.1 스크린샷 폴더 구조
|
||||
|
||||
```
|
||||
screenshots/
|
||||
├── fold-344px/
|
||||
│ ├── dashboard.png
|
||||
│ ├── sales/
|
||||
│ │ ├── client-management.png
|
||||
│ │ └── quote-management.png
|
||||
│ └── accounting/
|
||||
│ └── ...
|
||||
├── issues/
|
||||
│ ├── critical/
|
||||
│ └── minor/
|
||||
└── fixed/
|
||||
└── before-after/
|
||||
```
|
||||
|
||||
### 6.2 이슈 리포트
|
||||
|
||||
```markdown
|
||||
## 오버플로우 이슈 리포트
|
||||
|
||||
### Critical Issues (즉시 수정 필요)
|
||||
|
||||
| # | 페이지 | 문제 | 스크린샷 |
|
||||
|---|--------|------|----------|
|
||||
| 1 | /sales/quote | 테이블 헤더 잘림 | [링크] |
|
||||
| 2 | /accounting/daily-report | 차트 오버플로우 | [링크] |
|
||||
|
||||
### Minor Issues (백로그)
|
||||
|
||||
| # | 페이지 | 문제 | 스크린샷 |
|
||||
|---|--------|------|----------|
|
||||
| 1 | /settings/accounts | 버튼 그룹 좁음 | [링크] |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 예상 소요 시간
|
||||
|
||||
| 단계 | 예상 시간 | 비고 |
|
||||
|------|----------|------|
|
||||
| 환경 준비 | 30분 | Playwright 세팅 |
|
||||
| 스크린샷 캡처 | 1-2시간 | 185페이지, 자동화 |
|
||||
| 문제 분류 | 1시간 | 수동 검토 |
|
||||
| 수정 작업 | 2-8시간 | 문제 수에 따라 |
|
||||
| 검증 | 30분 | 재캡처 |
|
||||
| **총합** | **5-12시간** | |
|
||||
|
||||
---
|
||||
|
||||
## 8. 의사결정 포인트
|
||||
|
||||
### Q1: 자동화 vs 수동?
|
||||
- **권장**: 혼합 방식 (자동 캡처 → 수동 분류 → 수정)
|
||||
|
||||
### Q2: 전체 vs 우선순위별?
|
||||
- **권장**: 전체 캡처 후, Critical만 우선 수정
|
||||
|
||||
### Q3: 지금 vs 나중에?
|
||||
- 현재 수정 비용 < 나중 수정 비용
|
||||
- 가능하면 빠른 시일 내 진행 권장
|
||||
|
||||
---
|
||||
|
||||
## 9. 시작 전 필요한 것
|
||||
|
||||
1. **로컬 개발 서버** 실행 상태
|
||||
2. **테스트 계정** 로그인 정보
|
||||
3. **Node.js + Playwright** 설치
|
||||
4. **약 2-3시간** 집중 시간
|
||||
|
||||
---
|
||||
|
||||
## 부록: 페이지 URL 목록
|
||||
|
||||
<details>
|
||||
<summary>전체 페이지 목록 (185개) - 클릭하여 펼치기</summary>
|
||||
|
||||
### Dashboard
|
||||
- `/dashboard`
|
||||
|
||||
### Sales (18개)
|
||||
- `/sales/client-management-sales-admin`
|
||||
- `/sales/quote-management`
|
||||
- `/sales/order-management`
|
||||
- ... (상세 목록 필요시 추가)
|
||||
|
||||
### Accounting (26개)
|
||||
- `/accounting/sales`
|
||||
- `/accounting/vendors`
|
||||
- `/accounting/bills`
|
||||
- ... (상세 목록 필요시 추가)
|
||||
|
||||
### Construction (40개)
|
||||
- `/construction/sites`
|
||||
- `/construction/work-logs`
|
||||
- ... (상세 목록 필요시 추가)
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
> **다음 단계**: 이 계획서 검토 후, 진행 방식 결정하면 Playwright 스크립트 작성 시작
|
||||
@@ -0,0 +1,146 @@
|
||||
# Server Component → Client Component 마이그레이션 계획서
|
||||
|
||||
## 배경
|
||||
- **문제**: Server Component에서 API 호출 시 토큰 갱신(쿠키 수정)이 불가능
|
||||
- **원인**: Next.js 15에서 Server Component 렌더링 중 쿠키 수정 금지
|
||||
- **영향**: 토큰 만료 시 기본값 표시 → 데이터 덮어쓰기 위험
|
||||
- **결정**: 폐쇄형 사이트로 SEO 불필요, Client Component로 전환
|
||||
|
||||
## 변경 대상 (53개 페이지)
|
||||
|
||||
### Settings (4개)
|
||||
- [ ] settings/notification-settings/page.tsx
|
||||
- [ ] settings/popup-management/page.tsx
|
||||
- [ ] settings/permissions/[id]/page.tsx
|
||||
- [ ] settings/account-info/page.tsx
|
||||
|
||||
### Accounting (9개)
|
||||
- [ ] accounting/vendors/page.tsx
|
||||
- [ ] accounting/sales/page.tsx
|
||||
- [ ] accounting/deposits/page.tsx
|
||||
- [ ] accounting/bills/page.tsx
|
||||
- [ ] accounting/withdrawals/page.tsx
|
||||
- [ ] accounting/expected-expenses/page.tsx
|
||||
- [ ] accounting/bad-debt-collection/page.tsx
|
||||
- [ ] accounting/bad-debt-collection/[id]/page.tsx
|
||||
- [ ] accounting/bad-debt-collection/[id]/edit/page.tsx
|
||||
|
||||
### Sales (4개)
|
||||
- [ ] sales/quote-management/page.tsx
|
||||
- [ ] sales/pricing-management/page.tsx
|
||||
- [ ] sales/pricing-management/[id]/edit/page.tsx
|
||||
- [ ] sales/pricing-management/create/page.tsx
|
||||
|
||||
### Production (3개)
|
||||
- [ ] production/work-orders/[id]/page.tsx
|
||||
- [ ] production/screen-production/page.tsx
|
||||
- [ ] production/screen-production/[id]/page.tsx
|
||||
|
||||
### Quality (1개)
|
||||
- [ ] quality/inspections/[id]/page.tsx
|
||||
|
||||
### Master Data (2개)
|
||||
- [ ] master-data/process-management/[id]/page.tsx
|
||||
- [ ] master-data/process-management/[id]/edit/page.tsx
|
||||
|
||||
### Material (2개)
|
||||
- [ ] material/stock-status/[id]/page.tsx
|
||||
- [ ] material/receiving-management/[id]/page.tsx
|
||||
|
||||
### Outbound (2개)
|
||||
- [ ] outbound/shipments/[id]/page.tsx
|
||||
- [ ] outbound/shipments/[id]/edit/page.tsx
|
||||
|
||||
### Construction - Order (8개)
|
||||
- [ ] construction/order/order-management/[id]/page.tsx
|
||||
- [ ] construction/order/order-management/[id]/edit/page.tsx
|
||||
- [ ] construction/order/site-management/[id]/page.tsx
|
||||
- [ ] construction/order/site-management/[id]/edit/page.tsx
|
||||
- [ ] construction/order/structure-review/[id]/page.tsx
|
||||
- [ ] construction/order/structure-review/[id]/edit/page.tsx
|
||||
- [ ] construction/order/base-info/items/[id]/page.tsx
|
||||
- [ ] construction/order/base-info/pricing/[id]/page.tsx
|
||||
- [ ] construction/order/base-info/pricing/[id]/edit/page.tsx
|
||||
- [ ] construction/order/base-info/labor/[id]/page.tsx
|
||||
|
||||
### Construction - Project/Bidding (8개)
|
||||
- [ ] construction/project/bidding/[id]/page.tsx
|
||||
- [ ] construction/project/bidding/[id]/edit/page.tsx
|
||||
- [ ] construction/project/bidding/site-briefings/[id]/page.tsx
|
||||
- [ ] construction/project/bidding/site-briefings/[id]/edit/page.tsx
|
||||
- [ ] construction/project/bidding/estimates/[id]/page.tsx
|
||||
- [ ] construction/project/bidding/estimates/[id]/edit/page.tsx
|
||||
- [ ] construction/project/bidding/partners/[id]/page.tsx
|
||||
- [ ] construction/project/bidding/partners/[id]/edit/page.tsx
|
||||
|
||||
### Construction - Project/Contract (4개)
|
||||
- [ ] construction/project/contract/[id]/page.tsx
|
||||
- [ ] construction/project/contract/[id]/edit/page.tsx
|
||||
- [ ] construction/project/contract/handover-report/[id]/page.tsx
|
||||
- [ ] construction/project/contract/handover-report/[id]/edit/page.tsx
|
||||
|
||||
### Others (4개)
|
||||
- [ ] payment-history/page.tsx
|
||||
- [ ] subscription/page.tsx
|
||||
- [ ] dev/test-urls/page.tsx
|
||||
- [ ] dev/construction-test-urls/page.tsx
|
||||
|
||||
## 변환 패턴
|
||||
|
||||
### Before (Server Component)
|
||||
```typescript
|
||||
import { Component } from '@/components/...';
|
||||
import { getData } from '@/components/.../actions';
|
||||
|
||||
export default async function Page() {
|
||||
const result = await getData();
|
||||
return <Component initialData={result.data} />;
|
||||
}
|
||||
```
|
||||
|
||||
### After (Client Component)
|
||||
```typescript
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Component } from '@/components/...';
|
||||
import { getData } from '@/components/.../actions';
|
||||
import { DEFAULT_DATA } from '@/components/.../types';
|
||||
|
||||
export default function Page() {
|
||||
const [data, setData] = useState(DEFAULT_DATA);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
getData()
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
setData(result.data);
|
||||
}
|
||||
})
|
||||
.finally(() => setIsLoading(false));
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return <div>로딩 중...</div>;
|
||||
}
|
||||
|
||||
return <Component initialData={data} />;
|
||||
}
|
||||
```
|
||||
|
||||
## 추가 작업
|
||||
|
||||
### 1. RULES.md 업데이트
|
||||
- Client Component 사용 원칙 추가
|
||||
- SEO 불필요 폐쇄형 사이트 명시
|
||||
|
||||
### 2. fetch-wrapper.ts 정리
|
||||
- skipTokenRefresh 옵션 제거 (불필요해짐)
|
||||
|
||||
### 3. actions.ts 정리
|
||||
- skipTokenRefresh 관련 코드 제거
|
||||
|
||||
## 진행 상태
|
||||
- 시작일: 2026-01-09
|
||||
- 현재 상태: 진행 중
|
||||
Reference in New Issue
Block a user