Skip to Content
기능 플래그 (Datadog Feature Flags)

기능 플래그 (Datadog Feature Flags)

Datadog Feature Flags 로 기능을 원격 on/off 하고, 점진적 롤아웃과 A/B 실험(Experiments)의 기반을 만듭니다. OpenFeature  표준 위에 구현돼 있습니다.

웹 앱에서는 @datadog/openfeature-browser@openfeature/* 를 직접 호출하지 말고, 반드시 @howmuchhome-web/feature-flags 를 통해 사용하세요.

RUM 과 동일한 credential·env 태그를 쓰도록 패키지가 보장하기 때문입니다. 직접 호출하면 exposure 이벤트가 RUM 이벤트와 조인되지 않아 코호트 분석이 깨집니다.

native(Expo) 예외: provider 가 네이티브 모듈(@datadog/mobile-react-native-openfeature)이라 공유 패키지 facade 로 감싸지 않고, sentry/datadog 와 동일하게 앱(apps/native-app/src/lib/featureFlags)에서 주입합니다 — 이 배선 파일에 한해 @openfeature/*·provider 직접 사용이 허용됩니다. 평가(값 읽기)는 공유 훅·레지스트리(@howmuchhome-web/feature-flags/{hooks,evaluate,flags})를 그대로 재사용하므로 useFeatureFlag('키') 호출부 API 는 web 과 동일합니다. 네이티브 모듈이라 신규 배선은 OTA 불가(스토어 재빌드 필요).

왜 쓰는가

플래그를 평가하면 그 값이 RUM 이벤트·Error Tracking·Session Replay 에 자동으로 태깅됩니다. “이 기능을 켠 사용자만 에러율이 오르는가”를 배포 없이 바로 확인할 수 있고, 문제가 생기면 코드 롤백 없이 Datadog UI 에서 끌 수 있습니다.

지원 범위

대상상태
apps/app (웹뷰), apps/dashboard, apps/binzip, apps/binzip-admin✅ 사용 가능
클라이언트 컴포넌트 ('use client')✅ 사용 가능
RSC / 서버 액션 / route handler❌ 미지원 — 서버 SDK 는 dd-trace 5.116+ 가 필요하고, agentless 모드에서 exposure/experiment 를 지원하지 않음
apps/native-app (Expo)✅ 사용 가능 — @datadog/mobile-react-native-openfeature(네이티브 모듈) 배선됨. useFeatureFlag('키') 호출부 API는 웹과 동일(배선: apps/native-app/src/lib/featureFlags). ⚠️ 네이티브 모듈이라 OTA 불가 — 스토어 재빌드 후에만 반영

서버에서 분기해야 하면 기존 방식(Vercel Edge Config, env 스위치)을 쓰세요.

새 플래그 추가하기

1. Datadog 에서 플래그 생성

Feature Flags  에서 생성합니다. Claude Code 를 쓰면 Datadog MCP 의 create-feature-flag 로도 만들 수 있습니다.

  • 키는 snake_case 만 씁니다. Feature Flag Tracking 이 지원하지 않는 문자가 많습니다 (. : + - = && || > < ! ( ) { } [ ] ^ " ~ * ? \). kebab-case 의 - 도 그 목록에 있으므로 new-checkout 대신 new_checkout 으로 만드세요.
  • 환경은 prod / dev 두 개가 있습니다. 항상 dev 에서 먼저 켜서 확인한 뒤 prod 로 올립니다.

2. 코드 레지스트리에 등록

packages/feature-flags/flags.tsFEATURE_FLAGS 에 한 줄 추가합니다.

export const FEATURE_FLAGS = { feature_flags_smoke_test: {type: 'boolean', defaultValue: false}, my_new_feature: {type: 'boolean', defaultValue: false}, // ← 추가 } satisfies Record<string, FlagDefinition>;

defaultValue플래그가 없거나 · SDK 초기화 전이거나 · credential 미설정일 때 반환되는 값입니다. 반드시 기존 동작(플래그 도입 전 동작) 을 default 로 두세요. 이 값이 곧 장애 시 fallback 입니다.

3. 코드에서 읽기

'use client'; import {useFeatureFlag} from '@howmuchhome-web/feature-flags'; export function MyScreen() { const isNewFlowEnabled = useFeatureFlag('my_new_feature'); return isNewFlowEnabled ? <NewFlow /> : <LegacyFlow />; }

키·타입·기본값이 모두 레지스트리에서 추론되므로, 없는 키나 타입이 안 맞는 훅을 쓰면 컴파일 에러가 납니다.

API

대상용도
useFeatureFlag(key)boolean 플래그 읽기. 대부분 이것만 씁니다
useStringFeatureFlag(key)string(멀티 variant) 플래그
useNumberFeatureFlag(key)number 플래그
useFeatureFlagsReady()provider 초기화 완료 여부
getFeatureFlag(key)훅을 못 쓰는 곳(이벤트 핸들러·유틸 함수)에서 동기 조회
FeatureFlagProvider앱 루트 배선용. 신규 앱을 추가할 때만 씀
FeatureFlagUserSyncprovider 보다 하위에서 사용자가 밝혀질 때 컨텍스트 갱신

깜빡임(flash) 다루기

provider 는 렌더를 블로킹하지 않습니다. 초기화 전에는 defaultValue 가 반환되므로, 값이 true 로 바뀔 때 UI 가 한 번 바뀝니다. 대부분 문제가 안 되지만(default = 기존 동작이므로) 전환이 눈에 거슬리는 화면에서는 useFeatureFlagsReady() 로 게이팅하세요.

const ready = useFeatureFlagsReady(); const enabled = useFeatureFlag('my_new_feature'); if (!ready) return <Skeleton />; return enabled ? <NewFlow /> : <LegacyFlow />;

⚠️ credential 이 없는 환경(로컬 등)에서는 ready 가 계속 false 입니다. 이걸로 콘텐츠를 완전히 감추면 안 됩니다 — 스켈레톤이나 기존 UI 유지 용도로만 쓰세요.

타게팅 컨텍스트

평가 컨텍스트는 packages/feature-flags/context.ts 가 만듭니다.

속성
targetingKey로그인 사용자는 user id, 비로그인은 localStorage 에 영속되는 익명 id — 버킷팅 단위
is_signed_inboolean
servicehowmuchhome-web / howmuchhome-web-dashboard / howmuchhome-binzip / howmuchhome-binzip-admin
user_id로그인 시에만

제약:

  • 속성은 flat primitive(string/number/boolean)만 넣습니다. 중첩 객체나 배열을 넣으면 Datadog 이 exposure 이벤트를 조용히 버립니다(에러도 안 남습니다).
  • PII 를 넣지 않습니다(email·이름 등). exposure 이벤트는 분석 데이터로 장기 보존됩니다.
  • 익명 id 는 packages/loggergenerateAnonymousId()다릅니다. 후자는 호출마다 새 값을 만들어 저장하지 않으므로 버킷팅 키로 쓰면 페이지 이동마다 variant 가 튑니다. 반드시 패키지가 만드는 키를 쓰세요.

환경 매핑

코드 (FLAG_ENV)Datadog flagging environment조건 (web)조건 (native)
prodprod (is_production)NEXT_PUBLIC_ENV === 'production'APP_ENV === 'production' (production 빌드)
devdev그 외 전부 (로컬·프리뷰)그 외 전부 (local·canary·qa 등)

native 는 NEXT_PUBLIC_ENV 가 없고 APP_ENV(EXPO_PUBLIC_APP_ENV)로 판별합니다. production 빌드(yarn *:production·*:local:prod)만 prod, 나머지 빌드는 dev 로 평가되므로 Datadog 플래그 targeting 환경을 빌드에 맞춰야 합니다.

prod / dev 표기는 기존 RUM/Logs 의 env 태그와 맞춘 것입니다. exposure 이벤트와 RUM 이벤트를 Experiments 에서 조인할 때 env 태그가 어긋나면 붙지 않기 때문에 production 같은 다른 표기를 쓰면 안 됩니다.

알려진 한계: RUM 의 env 는 현재 모든 웹 환경에서 'prod' 로 하드코딩돼 있습니다 (packages/logger/provider/client/ClientLogger.tsx). 따라서 dev 트래픽은 exposure 가 env:dev, RUM 은 env:prod 로 남습니다. dev 에서 실험을 정확히 분석해야 할 때 RUM env 를 파라미터화하면 되지만, 기존 대시보드·모니터·Error Tracking 필터가 env:prod 기준이라 재검증이 필요합니다.

필요한 환경변수

RUM 과 동일한 값을 재사용하므로 신규 시크릿은 없습니다.

NEXT_PUBLIC_DATADOG_RUM_APPLICATION_ID=... NEXT_PUBLIC_DATADOG_RUM_CLIENT_TOKEN=... NEXT_PUBLIC_ENV=production # prod 환경에서만

Vercel 프로젝트 설정에 있습니다(저장소의 .env 파일에는 없습니다). 로컬에서 플래그를 확인하려면 .env.shared 나 앱별 .env.local 에 앞의 두 개를 넣으세요. 없으면 provider 가 등록되지 않고 모든 훅이 defaultValue 를 반환합니다(에러 없음).

비용 주의

enableRumFeatureFlagTracking 이 기본 true 입니다. 플래그 평가가 RUM 이벤트에 붙는 대신 RUM 청구 이벤트 수가 늘어날 수 있습니다. 이게 RUM 상관관계 분석의 핵심 기능이라 켜 두었지만, 플래그를 아주 많이 쓰게 되면 packages/feature-flags/provider.tsx 에서 조정하세요.

플래그 정리 (중요)

플래그는 기술 부채입니다. 롤아웃이 100% 로 끝나면:

  1. 코드에서 분기를 걷어내고 승자 경로만 남깁니다.
  2. flags.ts 의 레지스트리에서 키를 지웁니다.
  3. Datadog 에서 플래그를 archive 합니다.

Datadog 이 오래된 플래그를 stale 로 표시해 주고(list-stale-feature-flags), MCP 의 clean-up-flag 로 정리 작업을 도울 수 있습니다.

실험(Experiments)으로 확장하기

지금 세팅은 실험의 전제조건(플래그 + exposure 파이프라인)까지입니다. 실제 실험을 돌리려면 Datadog UI 에서 추가로 필요합니다:

  1. 실험 지표(experiment metric) 정의 — 무엇을 성공으로 볼지
  2. subject type 설정 — 무작위 배정 단위 (우리 targetingKey 와 맞춰야 함)
  3. Product Analytics + Feature Flags 권한

그 후 플래그 상세 페이지에서 바로 실험을 만들 수 있습니다.

참고

Last updated on