Minbook
EN
Feature Flag로 CLI 점수 정확도 올리기 — false-pass 문제 해결

Feature Flag로 CLI 점수 정확도 올리기 — false-pass 문제 해결

MJ · · 3 분 소요

MMU 체크리스트의 false-pass 문제를 해결하기 위해 17개 feature flag와 condition marker 시스템을 설계하고, 48개 테스트로 점수 정확도를 개선한 과정 기록

false-pass 문제

MMU의 체크리스트를 초기 사용자에게 테스트해달라고 했을 때, 반복적으로 나온 피드백이 있었습니다:

“Stripe 안 쓰는데 billing fail이 나와요.”

구체적으로:

시나리오체크리스트 항목사용자 상태결과문제
Stripe webhook 검증”Webhook 서명을 검증하고 있는가?”Stripe 미사용❌ Failfalse-fail
환불 정책”환불 정책이 명시되어 있는가?”무료 프로젝트❌ Failfalse-fail
GDPR 동의 배너”GDPR 쿠키 동의 배너가 있는가?”한국 전용 서비스❌ Failfalse-fail
iOS 가이드라인”App Store 리뷰 가이드라인을 준수하는가?”웹 전용❌ Failfalse-fail

534개 항목 중 일부는 특정 조건에서만 해당되는 항목이었습니다. 결제를 안 쓰는 프로젝트에 결제 관련 항목이 fail로 나오면, 체크리스트 전체의 신뢰도가 떨어집니다.

graph TB
    A["534개 체크리스트 항목"] --> B{"모든 항목이\n모든 프로젝트에\n해당되나?"}
    B -->|"아니오"| C["조건부 항목 존재\n~120개"]
    B -->|"예"| D["보편 항목\n~414개"]

    C --> E["false-fail 발생\n(해당 안 되는데 fail)"]
    E --> F["점수 왜곡\n체크리스트 신뢰도 ↓"]

    style E fill:#ffebee,stroke:#f44336
    style F fill:#ffebee,stroke:#f44336

해결 방향: Condition Marker

모든 항목을 모든 프로젝트에 적용하는 대신, 이 항목은 이 조건에서만 유효라는 마커를 추가하기로 했습니다.

설계 원칙

  1. 명시적 선언: 각 조건부 항목에 when 필드 추가
  2. 사용자가 조건을 선택: CLI 실행 시 프로젝트의 특성을 입력
  3. 해당 없는 항목은 skip: fail이 아니라 not-applicable로 처리
  4. 점수 계산에서 제외: skip된 항목은 분모에서도 빠짐

Condition Marker 데이터 구조

{
  "id": "billing-webhook-verification",
  "title": "Webhook 서명을 검증하고 있는가?",
  "category": "billing",
  "priority": "P0",
  "when": {
    "has_billing": true,
    "payment_provider": ["stripe", "lemonsqueezy", "paddle"]
  }
}
{
  "id": "gdpr-cookie-consent",
  "title": "GDPR 쿠키 동의 배너가 있는가?",
  "category": "legal",
  "priority": "P1",
  "when": {
    "target_region": ["eu", "global"]
  }
}

17개 Feature Flag

프로젝트의 특성을 나타내는 flag를 17개로 정리했습니다.

#Flag영향 범위
1has_billingtrue/false결제 관련 48개 항목
2payment_providerstripe/lemonsqueezy/paddle/none결제사별 세부 항목
3has_authtrue/false인증 관련 32개 항목
4auth_providersupabase/firebase/auth0/custom제공자별 세부 항목
5target_regionkr/us/eu/global법적 규제 관련 항목
6platformweb/mobile/desktop/cli플랫폼별 항목
7has_apitrue/falseAPI 보안, 문서화 항목
8has_databasetrue/falseDB 백업, 마이그레이션 항목
9has_file_uploadtrue/false파일 처리, 스토리지 항목
10has_emailtrue/false이메일 발송, 반송 처리 항목
11has_analyticstrue/false분석 도구 연동 항목
12has_ci_cdtrue/falseCI/CD 파이프라인 항목
13is_osstrue/false오픈소스 관련 항목 (라이선스, README)
14team_sizesolo/small/medium팀 규모별 항목
15has_i18ntrue/false다국어 관련 항목
16has_realtimetrue/falseWebSocket, SSE 관련 항목
17has_ai_featurestrue/falseAI/LLM 관련 항목 (프롬프트 인젝션 등)

Flag 수 결정 과정

검토 수결과
5개조건 커버리지 부족 (false-fail 50%만 해결)
10개주요 시나리오 커버 (80% 해결)
17개거의 모든 시나리오 커버 (95%+ 해결)
25개+사용자 입력 부담 과다 → 이탈 위험

17개는 “커버리지와 사용성의 균형점”입니다. CLI에서 Y/N 17개를 묻는 데 약 2분. 그 2분으로 false-fail을 95%+ 제거합니다.


CLI 플로우 변경

Before (flag 없이)

$ npx make-me-unicorn

🦄 Make Me Unicorn - SaaS Launch Checklist

Running all 534 items...

[FAIL] Webhook signature verification missing
[FAIL] Refund policy not found
[FAIL] GDPR cookie consent banner missing
...

Score: 312/534 (58%)

→ 사용자: “나는 결제도 없고 EU 서비스도 아닌데 왜 58%지?”

After (flag 적용)

$ npx make-me-unicorn

🦄 Make Me Unicorn - SaaS Launch Checklist

Quick setup (2 min):
  Has billing?        [Y/n] n
  Has authentication? [Y/n] y
  Target region?      [kr/us/eu/global] kr
  Platform?           [web/mobile/desktop/cli] web
  Has AI features?    [Y/n] n
  ...

Applying 17 flags → 89 items skipped (not applicable)
Running 445 applicable items...

[PASS] Auth session expiry configured
[FAIL] Password reset flow missing
[SKIP] Webhook verification (no billing)
...

Score: 380/445 (85%)
(89 items skipped as not applicable)

→ 사용자: “85%라니, 거의 다 됐네. 남은 65개만 고치면 되겠다.”

graph LR
    A["534 전체 항목"] -->|"17 flags 적용"| B["445 해당 항목"]
    A -->|"17 flags 적용"| C["89 skip 항목"]

    B --> D["380 PASS"]
    B --> E["65 FAIL"]

    F["Before: 312/534 = 58%"] -->|"false-fail 제거"| G["After: 380/445 = 85%"]

    style F fill:#ffebee,stroke:#f44336
    style G fill:#e8f5e9,stroke:#4caf50

테스트 설계: 48개 회귀 테스트

Feature flag 시스템이 정확하게 작동하는지 검증하기 위해 48개 테스트 케이스를 작성했습니다.

테스트 카테고리

카테고리테스트 수검증 내용
Flag 조합1217개 flag의 대표적 조합에서 올바른 항목이 포함/제외되는지
경계 케이스8모든 flag가 false, 모든 flag가 true, 단일 flag만 true
점수 계산10skip 항목이 분모에서 정확히 제외되는지
역호환성6flag 없이 실행해도 기존 동작(534 전체) 유지
조건 충돌8여러 when 조건이 겹칠 때 올바르게 해석되는지
출력 포맷4skip 항목이 리포트에 올바르게 표시되는지

핵심 테스트 예시

// flag 조합 테스트: 결제 없는 한국 웹 프로젝트
test('billing=false, region=kr should skip billing + GDPR items', () => {
  const flags = {
    has_billing: false,
    target_region: 'kr',
    platform: 'web',
  };

  const result = filterItems(ALL_ITEMS, flags);

  // 결제 관련 48개 항목 skip
  expect(result.skipped).toContain('billing-webhook-verification');
  expect(result.skipped).toContain('refund-policy');

  // GDPR 관련 항목 skip (kr 전용이므로)
  expect(result.skipped).toContain('gdpr-cookie-consent');

  // 한국 개인정보보호법 항목은 포함
  expect(result.applicable).toContain('kr-privacy-policy');
});
// 점수 계산 테스트: skip 항목이 분모에서 제외
test('score calculation excludes skipped items from denominator', () => {
  const flags = { has_billing: false };
  const result = runChecklist(ALL_ITEMS, flags, mockAnswers);

  // 534 - 48(billing) = 486 applicable
  expect(result.total).toBe(486);
  expect(result.score).toBe(result.passed / 486);
  // NOT result.passed / 534
});

점수 정확도 = 신뢰의 핵심

왜 정확도가 중요한가

false-fail이 많으면false-pass가 많으면
”이 도구 쓸모없네” → 이탈”다 통과했네!” → 실제 문제 방치
체크리스트 자체에 대한 불신론칭 후 장애, 법적 문제
사용자가 결과를 무시하기 시작체크리스트의 존재 이유가 사라짐

체크리스트 도구의 가장 중요한 지표는 정확도입니다. 기능이 아닙니다. 기능이 100개여도 결과가 부정확하면 아무도 안 씁니다. Feature flag는 기능 추가가 아니라 정확도 개선입니다.

개선 결과

지표BeforeAfter변화
false-fail 비율~22%~3%-19%p
사용자 체감 점수58% (과소)85% (정확)+27%p
”쓸모없다” 피드백빈번거의 없음해소
완주율 (끝까지 확인)~40%~75%+35%p

교훈

1. 체크리스트는 “보편성”이 아니라 “적합성”이 가치

534개 항목이 모두에게 해당된다는 전제는 틀렸습니다. 가치는 “많은 항목”이 아니라 “나에게 맞는 항목”에서 나옵니다. Feature flag는 534개를 줄이는 것이 아니라, 534개 중 나에게 맞는 것을 정확히 골라주는 것입니다.

2. 정확도와 사용성은 트레이드오프

Flag를 늘리면 정확도가 올라가지만 사용성이 떨어집니다. 17개는 이 트레이드오프의 현재 균형점이며, 사용자 피드백에 따라 조정될 수 있습니다.

3. 테스트는 flag 시스템에 필수

조건부 로직은 버그의 온상입니다. 48개 테스트 없이 17개 flag를 운영하면, flag 추가할 때마다 기존 조합이 깨질 수 있습니다.


정리

핵심내용
문제false-fail — 해당 안 되는 항목이 fail로 나와서 점수 왜곡
해결Condition Marker + 17개 Feature Flag
결과false-fail 22% → 3%, 완주율 40% → 75%
교훈체크리스트의 가치 = 항목 수가 아니라 정확도
공유

관련 글