wr: 페이징 오류 작업계획

This commit is contained in:
2026-06-25 16:30:29 +09:00
parent 05e9082831
commit 6110abebb4
@@ -0,0 +1,171 @@
# apps/wr 호출 병합 및 페이징 정상화 작업계획
작성일: 2026-06-25
대상 앱: `D:\iipbs\frontend\apps\wr`
대상 화면:
- `apps/wr/app/(with-layout)/ruseFcltMng/fcltSttn/rainSttn/page.tsx`
- 연관 검토 대상: `rswtSttn`, `htdflSttn`
## 1. 작업 배경
- `rainSttn` 화면에서 초기 진입 시 목록은 조회되지만, 바로 페이지를 변경하면 API 호출이 발생하지 않아 페이징이 동작하지 않는다.
- 현재 구조는 초기 진입 시 `init` 계열 호출과 사용자 조회 이후 `search` 호출을 분리하고 있다.
- 이 분리 구조를 제어하기 위해 `searchTrigger`와 `skipNextSearchRef`가 함께 사용되고 있는데, 그 결과 초기 조회 이후의 페이지 이동까지 차단되는 상태가 발생했다.
- 요구사항은 초기 진입 시에도 `search` 호출로 통일하고, 페이징이 항상 같은 목록 조회 경로를 타도록 정리하는 것이다.
## 2. 현재 구조 분석
### 2.1 rainSttn 현재 흐름
- 초기 진입:
- `getLaeSeCdCheck()` 실행
- `laeSeCd` 준비 후 `rainSttnInit(false, 1, rainSttnSize, ...)` 호출
- 이후 페이징/조회:
- `pageNation`, `appliedSearch`, `searchTrigger`를 감시하는 effect에서 `rainSttnSearch(...)` 호출
- 추가 제어:
- `skipNextSearchRef`로 초기 effect 1회를 건너뜀
- `searchTrigger === 0`이면 검색 effect를 중단
### 2.2 실제 문제 지점
- `UiTable`의 `onPageChange={setPageNation}` 자체는 정상이다.
- 그러나 페이지 번호가 바뀐 뒤 실행되는 검색 effect에서 `searchTrigger === 0` 조건으로 return 한다.
- 따라서 사용자가 `조회` 버튼을 한 번도 누르지 않은 초기 상태에서는 페이지 변경만으로는 `rainSttnSearch()`가 호출되지 않는다.
- 결과적으로 첫 진입 후 페이징 클릭 시 API가 호출되지 않는다.
### 2.3 구조적 문제
- 동일한 목록 조회인데 `init`과 `search`를 별도 액션으로 분리해 두었다.
- 화면은 “초기 조회”, “수동 조회”, “페이징 조회”를 서로 다른 상태 플래그로 구분한다.
- 이 구조는 중복 호출 방지에는 일부 도움이 되지만, 목록 조회의 단일 진입점을 없애고 상태 의존성을 높인다.
- 특히 페이징은 “현재 조건으로 특정 페이지를 조회한다”는 단순 동작이어야 하는데, 현재는 “사용자가 조회 버튼을 눌렀는지”까지 알아야 동작한다.
## 3. 목표 구조
### 3.1 조회 호출 단일화
- 초기 진입 시에도 `search` 계열 호출을 사용한다.
- 화면에서 목록 조회는 하나의 함수만 사용한다.
- 같은 파라미터라면 초기 진입, 조회 버튼, 페이지 이동, 엑셀 다운로드가 모두 동일한 검색 조건 계산 방식을 사용한다.
### 3.2 상태 제어 단순화
- `searchTrigger` 제거
- 가능하면 `rainSttnInit` 사용 제거 또는 `rainSttnSearch`로 내부 위임
- 초기 중복 호출 방지는 `init/search` 분리가 아니라 effect 설계 단순화로 해결
- 페이지 이동은 항상 API 호출로 이어지도록 보장
### 3.3 기대 효과
- 초기 진입 직후에도 페이징 정상 동작
- 조회 버튼을 누르기 전/후에 따라 동작이 달라지는 문제 제거
- 목록 조회 흐름이 단일화되어 유지보수 용이성 개선
- `rswtSttn` 같은 유사 화면에도 동일 패턴 적용 가능
## 4. 수정 대상
### 4.1 1차 수정 대상
- `D:\iipbs\frontend\apps\wr\app\(with-layout)\ruseFcltMng\fcltSttn\rainSttn\page.tsx`
- `D:\iipbs\frontend\apps\wr\app\store\ruseFcltMng\fcltSttn\rainSttn\index.tsx`
### 4.2 연계 검토 대상
- `D:\iipbs\frontend\apps\wr\app\(with-layout)\ruseFcltMng\fcltSttn\rswtSttn\page.tsx`
- `D:\iipbs\frontend\apps\wr\app\store\ruseFcltMng\fcltSttn\rswtSttn\index.tsx`
- `D:\iipbs\frontend\apps\wr\app\(with-layout)\ruseFcltMng\fcltSttn\htdflSttn\page.tsx`
## 5. 권장 구현 방향
### 5.1 화면 레벨 정리
- `rainSttn/page.tsx`에서 다음을 정리한다.
- 초기 진입용 `rainSttnInit()` 호출을 `rainSttnSearch()` 호출로 대체한다.
- `searchTrigger` 상태 제거
- `handleSearch()`는 검색 조건을 반영하고 `pageNation`을 1로 되돌린 뒤, 목록 조회를 직접 실행하거나 페이지 effect 하나로 일관되게 처리한다.
- 페이지 변경 시에는 항상 현재의 `appliedSearch` 기준으로 `rainSttnSearch()`가 호출되게 한다.
- 초기 1회 중복 호출만 필요하다면 `skipNextSearchRef` 유지 여부를 최소 범위에서 재판단한다.
### 5.2 store 레벨 정리
- `rainSttn/index.tsx`에서 `rainSttnInit`와 `rainSttnSearch`의 구현이 사실상 동일하므로 병합 후보로 본다.
- 다음 방법으로 수정:
- `rainSttnInit` 제거
- 화면에서는 `rainSttnSearch`만 사용
### 5.3 추천 방식
- 화면에서는 `search`만 사용하도록 통일
- store에서는 당장 외부 참조 영향이 있으면 `init` 시그니처는 남기되 내부는 `search` 재사용으로 정리
- 이후 호출처 정리까지 완료되면 `init` 제거.
## 6. 상세 작업 단계
### 단계 1. rainSttn 화면 호출 흐름 단일화
- `searchTrigger` 제거
- 초기 진입 effect에서 `rainSttnSearch(false, 1, rainSttnSize, initialConValue, "", code)` 호출
- 조회 버튼 클릭 시:
- `appliedSearch` 갱신
- 페이지를 1로 초기화
- 조건에 따라 직접 `rainSttnSearch()` 호출하거나, page 1 변경 effect에서 1회만 호출되도록 정리
- 페이지 이동 시:
- 현재 `appliedSearch`로 항상 `rainSttnSearch()` 호출
### 단계 2. 중복 호출 방지 로직 최소화
- 초기 진입 시점에 실제로 중복 호출이 발생하는지 확인
- 불필요하면 `skipNextSearchRef`도 제거하고 `useEffect` 수를 축소
### 단계 3. store 액션 병합
- `rainSttnInit`는 제거 `rainSttnSearch`로 공통 URL 조합 로직 정리
- 엑셀/일반 조회 분기만 남기고 목록 조회 경로를 단일화
### 단계 4. 유사 화면 점검
- `rswtSttn`은 `searchTrigger` 구조가 동일하므로 같은 페이징 불량 가능성이 높다.
- `rainSttn` 수정 후 동일 방식으로 `rswtSttn` 동시 정리 여부를 판단한다.
- `htdflSttn`은 이미 `searchTrigger` 없이 동작하므로 참조 구현으로 활용한다.
## 7. 구현 시 주의사항
- 검색 조건 입력값(`objSearch`)과 실제 적용 조건(`appliedSearch`)을 구분하는 구조는 유지할 수 있다.
- 다만 API 호출은 반드시 `appliedSearch` 기준으로만 가야 한다.
- `setPageNation(1)` 직후 effect 호출 시점 때문에 중복 조회가 생기지 않도록, “직접 호출”과 “effect 기반 호출” 중 하나만 선택해야 한다.
- 엑셀 다운로드는 전체 건수 기준 조회를 유지하되, 검색 조건 계산 로직은 일반 목록 조회와 동일해야 한다.
- `resetPageNo` 플래그가 테이블 페이지 번호 UI 초기화용이라면, API 호출 조건과 분리해서 관리해야 한다.
## 8. 검증 계획
### 8.1 rainSttn 검증
- 초기 진입 시 1페이지 목록이 조회된다.
- 초기 진입 직후 조회 버튼을 누르지 않고 2페이지로 이동하면 API가 호출되고 목록이 바뀐다.
- 조회 조건 변경 후 조회 버튼 클릭 시 1페이지로 이동하며 API가 1회만 호출된다.
- 조회 후 2페이지, 3페이지 이동 시 동일 조건으로 API가 정상 호출된다.
- 엑셀 다운로드 시 현재 적용된 조건으로 전체 건수 조회가 수행된다.
### 8.2 회귀 검증
- 상세 모달 열기 동작 유지
- 권한별 `laeSeCd` 초기 조건 유지
- 시도/시군구 선택 제한 유지
- 검색어 없는 상태/있는 상태 모두 페이징 정상 동작
## 9. 후속 권장사항
- `rainSttn`, `rswtSttn`, `htdflSttn`의 목록 조회 패턴을 공통화하는 것이 바람직하다.
- 가능하면 다음 공통 원칙으로 정리한다.
- “초기 진입도 search”
- “페이지 이동도 search”
- “조회 버튼도 search”
- “엑셀만 isExcel=true search”
- 이 원칙으로 맞추면 `init/search` 이원화에서 반복적으로 발생하는 상태 꼬임을 줄일 수 있다.
## 10. 결론
- 현재 문제의 직접 원인은 `searchTrigger` 가드이지만, 근본 원인은 `init`과 `search`를 분리한 화면 구조다.
- 이번 작업은 단순 버그 수정이 아니라 “목록 조회 진입점 단일화” 관점으로 진행하는 것이 맞다.
- 우선 `rainSttn`에서 초기 진입을 `search`로 통일하고 페이징이 항상 API를 타도록 수정한다.
- 이후 동일 패턴의 `rswtSttn`까지 함께 정리하면 재발 가능성을 크게 줄일 수 있다.