[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_snapshotTEXT는 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 리스트가 손실 없이 복원된다