ERP-node/docs/ycshin-node/PGN[맥락]-페이징-단락이동.md

129 lines
6.6 KiB
Markdown

# [맥락노트] 페이징 단락(그룹) 번호 네비게이션 - PageGroupNav 공통 컴포넌트
> 관련 문서: [계획서](./PGN[계획]-페이징-단락이동.md) | [체크리스트](./PGN[체크]-페이징-단락이동.md)
---
## 왜 이 작업을 하는가
- 현재 페이지네이션은 `1 / 38` 텍스트만 표시하고 `< >`로 한 페이지씩 이동
- 수십 페이지가 있을 때 원하는 페이지로 빠르게 이동할 수 없음
- 페이지 번호를 직접 클릭할 수 있어야 UX가 개선됨
---
## 핵심 결정 사항과 근거
### 1. 공통 컴포넌트로 분리 (C안)
- **결정**: `PageGroupNav.tsx`라는 순수 컨트롤 컴포넌트를 별도 파일로 생성
- **근거**: 프로젝트에 페이징이 15곳 이상 존재. 인라인 수정하면 같은 로직을 복사해야 함
- **대안 검토 A**: v2-table-list 인라인만 수정 → 기각 (미래 확장 시 복사-붙여넣기 기술 부채)
- **대안 검토 B**: 기존 `Pagination.tsx` 업그레이드 → 기각 (전체 행 레이아웃이 포함되어 v2-table-list와 레이아웃 충돌)
- **대안 검토 D**: 전체 한번에 적용 → 기각 (12파일 동시 수정은 블래스트 반경이 큼)
### 2. 레이아웃 무관 설계
- **결정**: PageGroupNav는 `<< < [번호들] > >>`만 렌더링. 외부 레이아웃(페이지크기, 내보내기 등)을 포함하지 않음
- **근거**: 사용처마다 레이아웃이 다름. v2-table-list는 좌측(페이지크기)+중앙(컨트롤)+우측(내보내기), Pagination.tsx는 좌측(페이지정보)+우측(크기선택+컨트롤). 레이아웃을 강제하면 props 분기가 증가하여 복잡해짐
### 3. 10개 단위 단락(그룹)
- **결정**: 페이지를 10개씩 묶어 하나의 단락으로 취급
- **근거**: 사용자에게 익숙한 패턴 (네이버, 구글 등). 5개는 너무 적고, 20개는 너무 많음
- **확장성**: `groupSize` props로 기본값 10을 변경 가능하게 설계
### 4. `< >` = 단락 이동, `<< >>` = 첫/끝 단락
- **결정**: `<`는 이전 단락 첫 페이지, `>`는 다음 단락 첫 페이지. `<<`는 1페이지, `>>`는 마지막 단락 첫 페이지
- **근거**: 사용자 요청. 기존의 "한 페이지씩 이동"은 번호 클릭으로 대체됨
- **주의**: `>>`는 마지막 **페이지**가 아닌 마지막 **단락의 첫 페이지**로 이동. 예: 총 38페이지일 때 `>>` 클릭 → 31페이지 선택 (38이 아님)
### 5. 고정 슬롯 + 고정 너비
- **결정**: 항상 10개 슬롯을 렌더링하고, 모든 버튼은 동일한 고정 너비(`w-8 sm:w-9`)
- **근거**: `< >` 버튼을 연속 클릭할 때 번호 자릿수(1자리→2자리)나 페이지 수(10개→8개) 변화로 버튼 위치가 흔들리면 안 됨
- **구현**: 마지막 단락에서 페이지가 10개 미만이면 남은 슬롯은 동일 크기의 빈 `<div>`로 채움
### 6. 단계적 적용 (1단계: v2-table-list만)
- **결정**: 이번 작업은 v2-table-list에만 적용. 나머지는 별도 작업으로 점진 적용
- **근거**: 15곳 동시 수정은 리스크가 높음. v2-table-list가 가장 많이 사용되므로 여기서 검증 후 확산
### 7. 비활성화 기준은 단락 기준
- **결정**: `<< <`는 첫 번째 단락일 때 비활성화 (currentPage === 1이 아님). `> >>`는 마지막 단락일 때 비활성화
- **근거**: 기존은 currentPage 기준이었지만, 단락 이동이므로 단락 기준으로 변경이 자연스러움. 첫 단락 안에서 5페이지에 있어도 `<`는 비활성화
---
## 관련 파일 위치
| 구분 | 파일 경로 | 설명 |
|------|----------|------|
| 생성 | `frontend/components/common/PageGroupNav.tsx` | 페이지 그룹 네비게이션 공통 컴포넌트 |
| 수정 | `frontend/lib/registry/components/v2-table-list/TableListComponent.tsx` | paginationJSX 중앙 영역 교체 (5139~5182행) |
| 참고 | `frontend/components/common/Pagination.tsx` | 기존 공통 페이지네이션 (이번에 수정 안 함) |
---
## 기술 참고
### 단락 계산 공식
```
groupSize = 10 (기본값)
currentGroupIndex = Math.floor((currentPage - 1) / groupSize)
groupStartPage = currentGroupIndex * groupSize + 1
groupEndPage = Math.min(groupStartPage + groupSize - 1, totalPages)
lastGroupIndex = Math.floor((totalPages - 1) / groupSize)
lastGroupStartPage = lastGroupIndex * groupSize + 1
isFirstGroup = currentGroupIndex === 0
isLastGroup = currentGroupIndex === lastGroupIndex
```
### 고정 슬롯 배열 생성
```
slots = [groupStart, groupStart+1, ..., groupEnd, null, null, ...] (총 groupSize개)
예: 단락 31~38 → [31, 32, 33, 34, 35, 36, 37, 38, null, null]
```
### handlePageChange 호출 흐름
```
PageGroupNav onPageChange(page)
→ TableListComponent handlePageChange(newPage)
→ setCurrentPage(newPage)
→ useEffect 트리거 → 백엔드 API 재호출 (page 파라미터 변경)
```
- handlePageChange는 `setCurrentPage`만 호출. `onConfigChange` 전파는 제거됨 (pageSize/currentPage는 세션 전용)
- handlePageChange는 기존 함수 그대로 사용. PageGroupNav가 올바른 page 값을 전달하기만 하면 됨
---
## 추가 결정: 표시갯수(pageSize) 캐시 정책
### 8. pageSize는 세션 전용, DB에 저장 안 함
- **결정**: pageSize를 `onConfigChange`로 부모/DB에 전파하지 않음. sessionStorage에만 탭별로 저장
- **근거**: pageSize는 일시적 탐색 설정이지 영구 화면 설정이 아님. DB에 저장하면 다른 사용자에게도 영향이 가고, 새로고침 시 의도치 않은 값이 남음
- **F5 정책**: 활성 탭은 캐시 삭제 → 기본값 20으로 fresh start. 비활성 탭은 캐시 유지
### 9. 테이블 캐시는 탭별 격리 (탭 ID 스코프)
- **결정**: `tableState_*`, `pageSize_*`, `filterSettings_*`, `groupSettings_*` 키를 `{prefix}_{tabId}_{tableName}` 구조로 변경
- **근거**: 같은 테이블이 여러 탭에서 열릴 수 있음. 탭 구분 없으면 "활성 탭 캐시만 삭제" 불가능
- **구현**: `useTabId()` 훅으로 현재 탭 ID 접근. `clearTabCache(tabId)`에서 해당 탭의 모든 관련 키 일괄 삭제
### 10. localStorage vs sessionStorage 분류
- **결정**: 탭별 캐시는 sessionStorage, 사용자 설정은 localStorage
- **근거**: 탭별 캐시(컬럼 너비 캐시, 필터, 그룹, pageSize)는 탭 닫으면 무의미. 사용자 설정(컬럼 가시성, 순서, 정렬)은 사용자가 의도적으로 변경한 환경설정이므로 세션 간 보존
- **분류**:
- sessionStorage: `tableState_*`, `pageSize_*`, `filterSettings_*`, `groupSettings_*`
- localStorage: `table_column_visibility_*`, `table_sort_state_*`, `table_column_order_*`