[FE-04] 서버 상태 훅 + mutation 함수 (BFF 소비)
작업 내용 (설계 의도)
변경 사항
화면이 BFF를 소비하는 데이터 계층을 레포 관례(lib/portal/useProducts.ts·lib/admin/auditLogs.ts)대로 구현한다. 컴포넌트는 이 훅/함수만 쓰고 raw fetch를 직접 두지 않는다(no-direct-fetch, no-logic-in-component). 응답은 FE-01 스키마로 .parse해 좁힌다(no-loose-assertion). 근거 설계: ../design-fe-web.md “상태관리 설계 / API 연동 표”.
web/lib/admin/feature-flags/api.ts: BFF fetch 함수 —fetchFeatureFlags({status?,type?}),fetchFeatureFlag(key),createFeatureFlag(input),updateFeatureFlag(key,input),archiveFeatureFlag(key),activateFeatureFlag(key),fetchFlagAuditLogs(key,page,size). 각 함수는/api/admin/feature-flags/...호출 후 zod parse, 실패 응답은{message}파싱해 Error throw.- 감사 로그 total 소비 + 필드명 격리:
fetchFlagAuditLogs가FeatureFlagAuditLogPageSchema(wire)로 파싱한 뒤 canonicalFeatureFlagAuditLogPageView({ logs, total, page, size, totalPages })로 정규화한다.totalPages는 wire에 있으면 그대로, 없으면ceil(total/size)로 계산. BE 최종 형태(Spring Page{content,totalElements,...}vs 경량{items,total})의 필드명 차이는 이 정규화 함수 1곳(toAuditLogPageView)만 수정 — 훅·화면 무영향. web/lib/admin/feature-flags/hooks.ts:useFeatureFlags(filters)·useFeatureFlag(key)·useFlagAuditLogs(key,page,size)—{data,isLoading,error,refetch}반환(useProducts 시그니처 정합).useFlagAuditLogs의data는 canonicalFeatureFlagAuditLogPageView(화면이totalPages로 “1 / N” 계산). cancelled 가드 포함.- 목록(S1) total 흡수 유연화:
fetchFeatureFlags는 wire가 배열이든{content|items,total}이든 흡수해 canonical(현재flags배열, 향후total추가 소비 가능)로 정규화 — senior-be가 목록도 total 통일 시 정규화 함수만 조정. - mutation은 훅이 아닌 명령 함수로 노출 — 성공 시 호출부가 refetch/라우팅 담당.
의존
- FE-01 (스키마/타입)
다이어그램
클래스 의존
flowchart LR Schemas["schemas.ts FE-01"] --> Api["api.ts"] Api --> Hooks["hooks.ts"] Hooks --> Pages["화면 FE-07~10"] Api --> Pages
테스트 케이스
- fetchFeatureFlags 성공 시 zod 파싱된 배열을 반환한다 (fetch mock)
- BFF가 5xx를 반환하면 fetchFeatureFlags가 사용자 메시지 Error를 throw한다
- createFeatureFlag가 400(key 중복) 응답의 message를 담은 Error를 throw한다
- useFeatureFlags가 로딩 중 isLoading=true, 성공 후 data 세팅·isLoading=false로 전이한다
- useFeatureFlags refetch 호출 시 재조회한다
- 컴포넌트 언마운트 후 응답 도착 시 상태 업데이트를 하지 않는다(cancelled 가드)
- fetchFlagAuditLogs가 wire 응답을 canonical
{logs,total,page,size,totalPages}로 정규화한다 - wire에 totalPages가 없으면 total·size로 totalPages를 계산한다(예: total 25, size 10 → 3)