Files
2nd/10_Wiki/Topics/Coding/Backend_Feature_Flags_Deep.md
T
2026-05-09 21:08:02 +09:00

4.8 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
backend-feature-flags-deep Feature Flags 심화 — 점진 / A/B / 격리 Coding draft B conceptual 2026-05-09 2026-05-09
backend
feature-flags
ab-testing
vibe-coding
language applicable_to
TS / GrowthBook / LaunchDarkly / Statsig
Backend
Frontend
feature flag
ab test
gradual rollout
GrowthBook
LaunchDarkly
Unleash
kill switch

Feature Flags Deep

단순 on/off 가 아님. % rollout / 사용자 segment / A/B 실험 / kill switch 4종. SDK + dashboard. GrowthBook (open) / LaunchDarkly / Statsig.

📖 핵심 개념

  • Targeting: 사용자 attribute 기반 (plan / country / cohort).
  • Rollout: 0% → 10% → 100% 점진.
  • A/B: variant 분배 + metric 측정.
  • Kill switch: emergency off.

💻 코드 패턴

GrowthBook (open source)

import { GrowthBook } from '@growthbook/growthbook';

const gb = new GrowthBook({
  apiHost: 'https://cdn.growthbook.io',
  clientKey: process.env.GB_KEY,
  attributes: {
    id: user.id,
    plan: user.plan,
    country: user.country,
  },
});

await gb.loadFeatures();

if (gb.isOn('new-checkout')) {
  // 새 flow
}

const variant = gb.getFeatureValue('button-color', 'blue'); // 'red' | 'blue'

LaunchDarkly

import { init, type LDClient } from 'launchdarkly-node-server-sdk';

const ld: LDClient = init(process.env.LD_KEY);
await ld.waitForInitialization();

const flag = await ld.variation('new-checkout', { key: user.id, custom: { plan: user.plan } }, false);

점진 rollout

# Dashboard (GrowthBook)
flag: new-checkout
rules:
  - condition: { plan: 'pro' }
    rollout: 100%
  - condition: { country: 'US' }
    rollout: 10%
  - default: 0%

A/B 실험

flag: button-color
experiment:
  hypothesis: red converts higher than blue
  variants:
    - { id: blue, weight: 50 }
    - { id: red, weight: 50 }
  metric: checkout_completed
const color = gb.getFeatureValue('button-color', 'blue');
analytics.track('button_seen', { variant: color });
// CTA 클릭 시
analytics.track('checkout_completed', { variant: color });

Kill switch

if (gb.isOn('use-new-payment-provider')) {
  await stripeNew.charge(...);
} else {
  await stripeOld.charge(...);
}

// 새 provider 가 깨지면 → flag off → 즉시 fallback

Stable hash (consistent variant)

import { hash } from '@growthbook/growthbook';

// 같은 user.id = 항상 같은 variant
const bucket = hash('exp-key', user.id, 1) * 100;
const variant = bucket < 50 ? 'a' : 'b';

→ 사용자가 새로고침 해도 같은 variant 받음.

Server-side vs client-side

// Server: SDK 직접 호출 — 비밀 attribute 사용 가능
gb.isOn('admin-feature'); // 서버에서

// Client: rules 가 client 에 노출 → 비밀 정보 X
// 또는 server-rendered (Next.js)
const flags = await gb.evaluateAll();
return { props: { flags } };

Type-safe flags

type Flags = {
  'new-checkout': boolean;
  'button-color': 'blue' | 'red' | 'green';
  'max-items': number;
};

function flag<K extends keyof Flags>(key: K): Flags[K] {
  return gb.getFeatureValue(key, defaults[key]) as Flags[K];
}

Cleanup (가장 어려움)

// 모든 flag = TODO 폴더
// "100% rollout 후 14일 → 코드 cleanup"
// CI 가 오래된 flag 알람
# .github/workflows/flag-audit.yml
- run: gb-cli list-flags --age-gt 90d

Local override (dev / test)

// 환경변수로 override
const overrides = JSON.parse(process.env.FLAG_OVERRIDES ?? '{}');
gb.setForcedFeatures(overrides);
// 테스트
gb.setForcedFeatures({ 'new-checkout': true });

Audit log

  • 누가 / 언제 / 무엇을 toggle 했는지.
  • Rollout 변화 history.
  • Compliance 요구.

🤔 의사결정 기준

규모 추천
작은 / 자체 호스트 GrowthBook OSS / Unleash
큰 / 매니지드 LaunchDarkly / Statsig
실험 자동 분석 Statsig (자동 stats)
단순 on/off env var + ConfigMap
Edge runtime Cloudflare Flags / GrowthBook Edge

안티패턴

  • Flag 쌓기 + 정리 안 함: 100+ flag = 코드 스파게티.
  • Cleanup 정책 없음: 누구도 안 지움.
  • Random variant — sticky X: 사용자가 매번 다른 variant.
  • Attribute 안 정의 — global 만: targeting 못 함.
  • Flag 안에 비즈니스 결정: dashboard 가 source of truth — 코드 의도 잃음.
  • Critical path flag check 매번 fetch: cache.
  • Flag failure → 앱 다운: default 명시 + 안전 fallback.

🤖 LLM 활용 힌트

  • 새 feature = flag 부터.
  • % rollout + segment + kill switch 3종.
  • 정리 정책 + audit log 필수.

🔗 관련 문서