[FE-01] 피처 플래그 zod 스키마·DTO 타입 (BE 계약 SSOT)
작업 내용 (설계 의도)
변경 사항
BE 계약(../TDD.md “API 계약” 섹션)을 FE의 단일 진실 타입으로 확립한다. 후행 티켓(BFF·훅·컴포넌트·화면)이 전부 이 타입을 import하는 연관 병목이므로 한 티켓으로 묶어 wave 1에 배치한다. 근거 설계: ../design-fe-web.md “API 연동 표 / BE 계약 타입”.
web/lib/admin/feature-flags/schemas.ts신설:strategydiscriminated union —z.discriminatedUnion("strategyType", [...])로 GLOBAL_TOGGLE(enabled)·PERCENTAGE_ROLLOUT(percentage 0~100)·ATTRIBUTE_MATCH(attribute,value)·VARIANT_BUCKETING(variants ≤4, weight 합 100) 표현.- 입력 스키마:
CreateFeatureFlagInputSchema(key,type,description,strategy),UpdateFeatureFlagInputSchema(description,strategy). - 응답 스키마·타입:
FeatureFlagResponseSchema/FeatureFlagResponse,FeatureFlagAuditLogResponseSchema/...Response(배열 원소),FeatureFlagSnapshot. - 감사 로그 total 포함 페이지 응답(senior-be 계약 개정 반영):
FeatureFlagAuditLogPageSchema(wire) — total을 담는 형태로 파싱. BE 최종 형태가 Spring Page({content, totalElements, totalPages, number, size})든 경량({items, total})든 파싱하게 정의하고, 화면이 소비하는 canonical 타입FeatureFlagAuditLogPageView({ logs, total, page, size, totalPages })를 별도로 노출한다. 배열 직반환 전용 스키마·폴백은 두지 않는다. - enum:
FeatureFlagType(RELEASE/OPERATIONAL/EXPERIMENT/ENTITLEMENT),FeatureFlagStatus(ACTIVE/ARCHIVED),StrategyType,ChangeType.
- 필드·타입은 TDD 계약과 1:1 (시각은 ISO 문자열, percentage number, variants name/weight).
- 필드명 격리: wire→canonical 변환은 FE-04
api.ts가 담당한다. 여기서는 wire 스키마(total 포함 전제)와 canonical 타입만 정의 — BE 최종 필드명 확정 시 wire 스키마만 조정하고 canonical(화면 계약)은 고정. - 검증 없는 타입 단언(
as) 금지 — 응답은 후행 훅이.parse로 좁힌다. 여기서는 스키마·타입만 정의.
의존
- 없음
다이어그램
클래스 의존
flowchart LR Zod["zod"] --> Schemas["feature-flags/schemas.ts"] Schemas --> BFF["BFF routes FE-03"] Schemas --> Hooks["훅/함수 FE-04"] Schemas --> Comp["컴포넌트 FE-05·06"]
테스트 케이스
- 유효한 GLOBAL_TOGGLE/PERCENTAGE_ROLLOUT/ATTRIBUTE_MATCH/VARIANT_BUCKETING strategy 4종이 각각 파싱을 통과한다
- percentage가 101이면 PERCENTAGE_ROLLOUT 파싱이 실패한다
- variants weight 합이 90이면 VARIANT_BUCKETING 파싱이 실패한다
- variants가 5개면 파싱이 실패한다(최대 4)
- strategyType이 계약 외 값이면 discriminatedUnion 파싱이 실패한다
- FeatureFlagResponse에 status가 “ACTIVE”/“ARCHIVED” 외면 파싱이 실패한다
- total 포함 감사 페이지 응답이 스키마를 통과하고 total 값이 보존된다
- total 필드가 없는 응답은 FeatureFlagAuditLogPageSchema 파싱이 실패한다