[BE-02] FeatureFlag MySQL 영속화 (Repository 구현)

작업 내용 (설계 의도)

변경 사항

BE-01 도메인 인터페이스의 MySQL 구현. 근거 TDD: ../TDD.md “시스템 역할 경계”·ERD. @Query 금지 → QueryDSL CustomImpl 패턴(선례 infrastructure/operator/mysql/*, infrastructure/mcp/mysql/McpAuditLog*).

  • FeatureFlagJpaRepository (Spring Data): 기본 CRUD + findByFlagKey 파생 쿼리(Optional은 RepositoryImpl에서 ?:null로 풀어 도메인 밖으로 누출 금지).
  • FeatureFlagQueryDslRepository + ...Impl: findAll(status?, type?) 동적 필터, findAllActive()(status=ACTIVE) — BooleanBuilder.
  • FeatureFlagRepositoryImpl: JpaRepository + QueryDSL 결합, FeatureFlagRepository 구현. existsByKey.
  • FeatureFlagAuditLogJpaRepository + FeatureFlagAuditLogRepositoryImpl: findByFlagKey(key, pageable: Pageable): Page<FeatureFlagAuditLog>(occurred_at desc — Pageable/Page 반환, 레포 McpAuditLogRepository 선례). total 포함 응답(FE “1/3”)의 근거이므로 totalElements 정확성 검증.
  • @Entity 자체는 BE-01 도메인 클래스(단일 클래스)이므로 여기서 JPA 엔티티를 새로 만들지 않는다. strategy_config/before_snapshot/after_snapshot TEXT는 BE-01의 @Type(JsonStringType::class) 매핑을 그대로 사용 — round-trip 검증만 담당.
  • 대상 테이블: feature_flags·feature_flag_audit_logs(DB-01 마이그레이션 산출물, senior-dba/mysql). 테이블 부재 시 in-progress.

의존

  • BE-01 (도메인 인터페이스·엔티티)
  • DB-01 (마이그레이션 — senior-dba/mysql-implementer, 병행 선행)

다이어그램

클래스 의존

flowchart LR
    FeatureFlagRepositoryImpl -.->|implements| FeatureFlagRepository["domain.FeatureFlagRepository"]
    FeatureFlagRepositoryImpl --> FeatureFlagJpaRepository
    FeatureFlagRepositoryImpl --> FeatureFlagQueryDslRepositoryImpl
    AuditLogRepositoryImpl -.->|implements| AuditLogRepo["domain.FeatureFlagAuditLogRepository"]
    AuditLogRepositoryImpl --> AuditLogJpaRepository

테스트 케이스 (Testcontainers MySQL)

  • save 후 findByKey로 동일 플래그를 조회한다(strategy TEXT round-trip 일치)
  • findAllActive는 ARCHIVED 플래그를 제외하고 ACTIVE만 반환한다
  • findAll(status=null, type=RELEASE)는 타입 필터만 적용한다(동적 조건)
  • 존재하지 않는 key의 findByKey는 null을 반환한다(Optional 누출 없음)
  • existsByKey는 중복 key 존재 시 true, 없으면 false
  • 감사 로그 findByFlagKey는 occurred_at 내림차순 페이징으로 반환한다
  • VariantBucketing 전략 저장/조회 시 variants 리스트가 손실 없이 복원된다