[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -2,60 +2,148 @@
|
||||
id: wiki-2026-0508-feature-flags
|
||||
title: Feature Flags
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AI-FE FEATURE-FLAGS]
|
||||
aliases: [Feature Toggles, Feature Switches, Feature Gates]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.98
|
||||
tags: [DevOps, FeatureFlags, Deployment, RiskManagement]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [devops, deployment, experimentation, release-engineering]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: TypeScript/Go
|
||||
framework: LaunchDarkly/Unleash/OpenFeature
|
||||
---
|
||||
|
||||
# [[Feature-Flags|Feature-Flags]] (피처 플래그)
|
||||
# Feature Flags
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> "배포는 하되, 보일지 말지는 스위치로 결정한다." 코드 배포와 기능 출시(Release)를 분리하여, 런타임에 동적으로 기능을 켜고 끄거나 특정 유저에게만 노출할 수 있게 하는 마법의 스위치다.
|
||||
## 매 한 줄
|
||||
> **"매 deploy 와 release 를 매 분리하는 runtime conditional"**. Pete Hodgson 의 매 4-axis taxonomy (release/experiment/ops/permission) 가 매 baseline. 매 modern stack — OpenFeature spec + provider (LaunchDarkly, Unleash, ConfigCat, Statsig) — 매 progressive delivery, A/B test, kill switch 의 매 통합 layer.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **Core Functions**:
|
||||
- **Kill Switch**: 신규 기능에 치명적인 버그가 발견되면 코드 수정 없이 즉시 비활성화.
|
||||
- **Canary Release**: 소수의 유저(예: 1%)에게만 기능을 먼저 공개하여 안정성 검증.
|
||||
- **A/B [[Testing|Testing]]**: 동일한 기능을 두 가지 버전으로 배포하고 성과를 비교.
|
||||
- **Implementation**: `if (flag('new-ui')) { ... }` 식의 조건문으로 감싸고, 중앙 서버(LaunchDarkly 등)에서 상태를 제어한다.
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- 피처 플래그를 방치하면 코드 곳곳에 조건문이 남게 되어 기술 부채(Technical Debt)가 급증한다. 기능이 성공적으로 안착했다면 즉시 플래그 코드를 지우는 '클린업 사이클'이 운영 프로세스에 반드시 포함되어야 한다. 또한 플래그 설정값 자체가 하나의 '전역 상태'이므로, 이에 대한 히스토리 관리가 필수적이다.
|
||||
### 매 4 종류 (Hodgson)
|
||||
- **Release toggle**: dark launch, gradual rollout (short-lived).
|
||||
- **Experiment toggle**: A/B/n test (medium-lived).
|
||||
- **Ops toggle**: kill switch, circuit breaker (medium-lived).
|
||||
- **Permission toggle**: per-user/tenant entitlement (long-lived).
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- Related: [[DevOps-and-UX-Convergence|DevOps-and-UX-Convergence]] , Continuous-Deployment
|
||||
- [[Strategy|Strategy]]: Trunk-Based-Development
|
||||
### 매 axis
|
||||
- Lifetime: hours ↔ years.
|
||||
- Dynamism: build-time → runtime → request-time.
|
||||
- Scope: global → user → request.
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 매 응용
|
||||
1. Trunk-based development + dark launch.
|
||||
2. Canary / progressive rollout (1% → 100%).
|
||||
3. Kill switch (incident mitigation).
|
||||
4. A/B testing & holdout group.
|
||||
5. Tier-based feature gating (free/pro/enterprise).
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
## 💻 패턴
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
### OpenFeature SDK (vendor-neutral)
|
||||
```typescript
|
||||
import { OpenFeature } from '@openfeature/server-sdk';
|
||||
import { LaunchDarklyProvider } from '@openfeature/launchdarkly-server-provider';
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
await OpenFeature.setProviderAndWait(new LaunchDarklyProvider(SDK_KEY));
|
||||
const client = OpenFeature.getClient();
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
const showNew = await client.getBooleanValue('new-checkout', false, {
|
||||
targetingKey: user.id,
|
||||
email: user.email,
|
||||
plan: user.plan,
|
||||
});
|
||||
return showNew ? renderNewCheckout() : renderOldCheckout();
|
||||
```
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
### Percentage rollout (deterministic hash)
|
||||
```go
|
||||
import "hash/fnv"
|
||||
func rollout(flagKey, userID string, percent int) bool {
|
||||
h := fnv.New32a()
|
||||
h.Write([]byte(flagKey + ":" + userID))
|
||||
return int(h.Sum32()%100) < percent
|
||||
}
|
||||
// Same user → same bucket across calls (sticky).
|
||||
```
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
### Kill switch (ops toggle)
|
||||
```typescript
|
||||
async function fetchRecommendations(userId: string) {
|
||||
if (await flags.getBooleanValue('reco-kill-switch', false)) {
|
||||
return []; // disable the feature instantly during incident
|
||||
}
|
||||
return recoService.fetch(userId);
|
||||
}
|
||||
```
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
### Multivariate experiment
|
||||
```typescript
|
||||
const variant = await client.getStringValue('checkout-variant', 'control', ctx);
|
||||
switch (variant) {
|
||||
case 'one-click': return <OneClickCheckout />;
|
||||
case 'wallet': return <WalletCheckout />;
|
||||
default: return <StandardCheckout />;
|
||||
}
|
||||
metrics.track('checkout_view', { variant, userId });
|
||||
```
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
### Local override (dev/test)
|
||||
```typescript
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
OpenFeature.setProvider(new InMemoryProvider({
|
||||
'new-checkout': { defaultVariant: 'on', variants: { on: true, off: false } },
|
||||
}));
|
||||
}
|
||||
```
|
||||
|
||||
### Flag cleanup (technical debt)
|
||||
```bash
|
||||
# Find old flags
|
||||
rg "getBooleanValue\\('old-checkout'" --type ts
|
||||
# Provider audit: list flags > 90 days old, no recent eval, 100% rollout → delete.
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Dark launch / gradual | Release toggle, percentage rollout |
|
||||
| Hypothesis test | Experiment toggle + analytics |
|
||||
| Incident mitigation | Ops toggle (always available) |
|
||||
| Tier / paid features | Permission toggle (long-lived) |
|
||||
| Build-time only | Compile flag (no runtime cost) |
|
||||
|
||||
**기본값**: OpenFeature SDK + managed provider (LaunchDarkly/Unleash). Kill switch 모든 critical path 에 매.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Continuous Delivery]] · [[Progressive Delivery]]
|
||||
- 변형: [[Release Toggle]] · [[Experiment Toggle]] · [[Kill Switch]]
|
||||
- 응용: [[Canary Deployment]] · [[A/B Testing]] · [[Trunk-based Development]]
|
||||
- Adjacent: [[OpenFeature]] · [[LaunchDarkly]] · [[Unleash]] · [[Statsig]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: Release strategy 설계, incident playbook, experiment platform 평가.
|
||||
**언제 X**: Static config — env var / config file 충분.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Flag debt**: 100% rolled-out flag 를 매 안 지움 → cyclomatic complexity 폭발.
|
||||
- **Nested flags**: A&&B&&C — 매 test space 매 explosion.
|
||||
- **Flag in hot loop**: per-request eval 의 매 latency — cache locally.
|
||||
- **No fallback**: provider 다운 시 feature 깨짐 — default + cached value.
|
||||
- **Flag = config 오용**: 진짜 config 는 매 config service 로.
|
||||
- **No analytics linkage**: experiment 인데 evaluation 안 records.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (martinfowler.com Feature Toggles, OpenFeature spec, LaunchDarkly docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — 4-axis taxonomy + OpenFeature/percentage/kill-switch 패턴 |
|
||||
|
||||
Reference in New Issue
Block a user