[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 소비 + 필드명 격리: fetchFlagAuditLogsFeatureFlagAuditLogPageSchema(wire)로 파싱한 뒤 canonical FeatureFlagAuditLogPageView({ 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 시그니처 정합). useFlagAuditLogsdata는 canonical FeatureFlagAuditLogPageView(화면이 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)