[FE-06] 전략 입력 폼 컴포넌트 (4종 분기 + 퍼센티지 슬라이더 + variant 에디터)

작업 내용 (설계 의도)

변경 사항

S2(생성)·S3(수정)가 공유하는 전략 입력 복합 컴포넌트를 정의한다. 설계의 S4(퍼센티지 롤아웃 조정 UI)를 포함한다. 색은 토큰만, 슬라이더/토글은 네이티브 요소(신규 의존성 회피). 근거 설계: ../design-fe-web.md “전략 입력 섹션 / 방안 F”.

  • web/app/admin/feature-flags/_components/StrategyForm.tsx: value: Strategy, onChange, disabled(ARCHIVED 시), flagType(전략 선택지 게이팅) props. 전략 유형 select + 유형별 하위 필드 조건 렌더.
  • 하위 필드(같은 파일 또는 인접):
    • GlobalToggleField — 라벨 있는 on/off 스위치(네이티브 checkbox/button), ON은 text-success.
    • PercentageRolloutField(S4) — <input type="range" min=0 max=100> + 숫자 입력 동기화, “userId 해시 기반 sticky” caption.
    • AttributeMatchField — attribute·value 텍스트 입력.
    • VariantBucketingField — variant(name+weight) 리스트, 추가/삭제(최대 4), weight 합계 표시. 합≠100이면 text-warning 경고 + 유효성 false 신호.
  • 유형 게이팅: flagType === EXPERIMENT → VARIANT_BUCKETING만, 그 외 → 나머지 3종(설계 Open Question대로 BE가 최종 검증).
  • 유효성 결과를 부모에 노출(onValidityChange 또는 value 검증)해 저장 버튼 활성/비활성 제어.
  • 데이터 가공(strategy↔폼 상태 매핑)은 순수 함수로 분리(no-logic-in-component).

의존

  • FE-01 (Strategy 타입/스키마)
  • FE-02 (success/warning 토큰)

다이어그램

클래스 의존

flowchart LR
    Schema["Strategy schema FE-01"] --> SF["StrategyForm"]
    Tokens["tokens FE-02"] --> SF
    SF --> Toggle["GlobalToggleField"]
    SF --> Pct["PercentageRolloutField S4"]
    SF --> Attr["AttributeMatchField"]
    SF --> Var["VariantBucketingField"]
    SF --> Forms["S2/S3 FeatureFlagForm"]

테스트 케이스

  • 전략 유형을 “퍼센티지 롤아웃”으로 바꾸면 슬라이더가 나타나고 토글 필드는 사라진다
  • 슬라이더를 60으로 옮기면 숫자 입력이 60으로 동기화되고 onChange가 percentage=60을 전달한다
  • variant weight 합이 100이 아니면 경고(warning) caption이 뜨고 유효성 false를 알린다
  • variant를 4개 초과로 추가하려 하면 추가 버튼이 비활성된다
  • flagType=EXPERIMENT면 전략 유형 select에 VARIANT_BUCKETING만 노출된다
  • disabled=true(ARCHIVED)면 모든 입력이 비활성된다
  • ATTRIBUTE_MATCH에서 attribute/value 입력이 onChange로 반영된다