5.5 KiB
5.5 KiB
[맥락노트] 페이징 - 페이지 번호 직접 입력 네비게이션
왜 이 작업을 하는가
- 현재 페이지네이션은
1 / 38읽기 전용 텍스트만 표시 - 수십 페이지가 있을 때 원하는 페이지로 빠르게 이동할 수 없음 (
>연타 필요) - 페이지 번호를 직접 입력하여 즉시 이동할 수 있어야 UX가 개선됨
핵심 결정 사항과 근거
1. 10개 번호 버튼 그룹 → 입력 필드로 설계 변경
- 결정: 이전 설계(10개 페이지 번호 버튼 나열)를 폐기하고, 기존
현재/총텍스트에서 현재 부분을 입력 필드로 교체 - 근거: 10개 버튼은 공간을 많이 차지하고 고정 슬롯/고정 너비 등 복잡한 레이아웃 제약이 발생. 입력 필드 방식이 더 직관적이고 공간 효율적
- 이전 산출물:
PageGroupNav.tsx→ 삭제 완료
2. << < > >> 버튼 동작 유지
- 결정: 4개 화살표 버튼의 동작은 기존과 완전히 동일하게 유지
- 근거: 입력 필드가 "원하는 페이지로 점프" 역할을 하므로, 버튼은 기존의 순차 이동(+1/-1, 첫/끝) 그대로 유지하는 것이 자연스러움
3. 입력 중에는 페이지 이동 안 함
- 결정: onChange는 입력 필드 표시만 변경. Enter 또는 blur로 실제 페이지 이동
- 근거:
28을 입력하려면2를 먼저 치는데,2에서 바로 이동하면 안 됨
4. 포커스 시 전체 선택 (select all)
- 결정: 입력 필드 클릭 시 기존 숫자를 전체 선택
- 근거: 사용자가 "15페이지로 가고 싶다" → 클릭 → 바로
15타이핑. 기존 값을 지우는 추가 동작 불필요
5. 유효 범위 자동 보정
- 결정: 1 미만 → 1, totalPages 초과 → totalPages, 빈 값/비숫자 → 현재 페이지 유지
- 근거: 에러 메시지보다 자동 보정이 UX에 유리
- 대안 검토: 입력 자체를 숫자만 허용 → 기각 (백스페이스로 비울 때 불편)
6. inputMode="numeric" 사용
- 결정:
type="text"+inputMode="numeric" - 근거:
type="number"는 브라우저별 스피너 UI가 추가되고, 빈 값 처리가 어려움.inputMode="numeric"은 모바일에서 숫자 키보드를 띄우면서 text 입력의 유연성 유지
7. 신규 컴포넌트 분리 안 함
- 결정: v2-table-list의 paginationJSX 내부에 인라인으로 구현
- 근거: 변경이
<span>→<input>+ 핸들러 약 30줄 수준으로 매우 작음
8. currentPage를 fetch의 단일 소스로 사용
- 결정:
fetchTableDataInternal에서tableConfig.pagination?.currentPage || currentPage대신currentPage만 사용 - 근거:
handlePageSizeChange에서setCurrentPage(1)+onConfigChange(...)호출 시,onConfigChange를 통한 부모의tableConfig갱신은 다음 렌더 사이클에서 전파됨. fetch가 실행되는 시점에tableConfig.pagination?.currentPage가 아직 이전 값(예: 4)이고 truthy이므로 로컬currentPage(1) 대신 4를 사용하게 되는 문제 발생. 로컬currentPage는setCurrentPage로 즉시 갱신되므로 이 문제가 없음 - 발견 과정: 페이지 크기를 20→40으로 변경하면 1페이지로 설정되지만 리스트가 빈 상태로 표시되는 버그로 발견
9. handlePageSizeChange에서 onConfigChange 호출 필수
- 결정: 페이지 크기 변경 시
onConfigChange로{ pageSize, currentPage: 1 }을 부모에게 전달 - 근거: 기존 코드는
setLocalPageSize+setCurrentPage(1)만 호출하고onConfigChange를 호출하지 않았음. 이로 인해 부모 컴포넌트의tableConfig.pagination이 갱신되지 않아 후속 동작에서 stale 값 참조 가능 - 발견 과정: 위 8번과 같은 맥락에서 발견
관련 파일 위치
| 구분 | 파일 경로 | 설명 |
|---|---|---|
| 수정 | frontend/lib/registry/components/v2-table-list/TableListComponent.tsx |
paginationJSX 중앙 입력 필드 + fetch 소스 수정 |
| 삭제 | frontend/components/common/PageGroupNav.tsx |
이전 설계 산출물 (삭제 완료) |
기술 참고
로컬 입력 상태와 실제 페이지 상태 분리
pageInputValue (string) — 입력 필드에 표시되는 값 (사용자가 타이핑 중일 수 있음)
currentPage (number) — 실제 현재 페이지 (API 호출의 단일 소스)
동기화:
- currentPage 변경 시 → useEffect → setPageInputValue(String(currentPage))
- Enter/blur 시 → commitPageInput → parseInt + clamp → handlePageChange(보정된 값)
handlePageChange 호출 흐름
입력 필드 Enter/blur
→ commitPageInput()
→ parseInt + clamp(1, totalPages)
→ handlePageChange(clampedPage)
→ setCurrentPage(clampedPage) + onConfigChange
→ useEffect 트리거 → fetchTableDataDebounced
→ fetchTableDataInternal(page = currentPage)
→ 백엔드 API 호출
handlePageSizeChange 호출 흐름
좌측 페이지크기 입력 onChange/onBlur
→ handlePageSizeChange(newSize)
→ setLocalPageSize(newSize)
→ setCurrentPage(1)
→ sessionStorage 저장
→ onConfigChange({ pageSize: newSize, currentPage: 1 })
→ useEffect 트리거 → fetchTableDataDebounced
→ fetchTableDataInternal(page = 1, pageSize = newSize)
→ 백엔드 API 호출