ADR-0003: 관측·기능플래그 SDK는 공유 패키지 facade로만 쓴다
소급 기록입니다.
Context
관측 SDK(Datadog RUM·Logs, Sentry)와 기능플래그 SDK(OpenFeature + Datadog provider)는 초기화 시점의 설정값이 데이터의 품질을 결정합니다. 특히:
- RUM 이벤트와 플래그 exposure 이벤트는 같은 credential·같은
env태그로 보내야 Datadog에서 조인됩니다. 어긋나면 코호트 분석(“플래그 A를 본 사용자의 에러율”)이 조용히 깨집니다 — 에러가 나지 않고 숫자만 틀립니다 - 앱이 8개(
apps/*)라 각자 초기화하면 태그 규칙이 8벌로 갈라집니다
즉 이건 스타일 문제가 아니라 데이터 정합성 문제입니다.
검토한 대안
| 대안 | 채택 안 한 이유 |
|---|---|
| 각 앱이 SDK를 직접 초기화하고 컨벤션 문서로 통일 | 문서로 강제되지 않음. 어긋나도 빌드·테스트가 통과하고 대시보드 숫자만 조용히 틀림 |
| ESLint 규칙으로 직접 import만 금지 | 초기화 설정값 자체를 강제하지 못함 |
Decision
@datadog/browser-rum·@datadog/browser-logs·@sentry/nextjs·@datadog/openfeature-browser·@openfeature/*를 앱 코드에서 직접 호출하지 않는다. 각각 공유 패키지 facade를 통해서만 쓴다.
@howmuchhome-web/logger—Logger.log()/addAction()/startView()/captureError()@howmuchhome-web/feature-flags—useFeatureFlag('키'). 플래그 정의는flags.ts의FEATURE_FLAGS가 단일 소스
부수적으로 얻는 것: API 에러는 fetcher가 자동으로 Sentry에 보내므로 호출부가 신경 쓰지 않아도 됩니다.
native(Expo) 예외
native의 Datadog·Sentry·OpenFeature provider는 네이티브 모듈(@datadog/mobile-react-native-openfeature 등)이라 web용 facade로 감쌀 수 없습니다. 그래서 provider 주입만 앱(apps/native-app/src/lib/featureFlags)에서 직접 합니다.
단, 평가(값 읽기)는 공유 훅·레지스트리를 그대로 재사용하므로 호출부 API(useFeatureFlag('키'))는 web과 동일합니다. 즉 예외는 배선 파일 한 곳에 갇혀 있고, 이 경계 밖에서 @openfeature/*를 직접 쓰는 것은 여전히 금지입니다.
Consequences
좋아지는 것
- 태그·credential 규칙이 한 곳에서 보장된다. 앱이 늘어도 규칙이 갈라지지 않는다
- SDK 교체·업그레이드의 영향 범위가 패키지 내부로 한정된다
- 플래그 키 목록이 코드에 하나만 존재한다
감수하는 것
- facade가 노출하지 않는 SDK 기능을 쓰려면 패키지를 먼저 고쳐야 한다. 급할 때 우회하고 싶어지는 지점이며, 우회가 곧 이 결정의 실패다
- native 예외 때문에 “직접 호출 금지”에 단서가 붙는다. 규칙이 100% 균일하지 않다는 비용을 감수한다
- native 플래그 provider는 네이티브 모듈이라 OTA로 배선을 못 바꾼다. 신규 provider 배선은 스토어 재빌드가 필요하다 (플래그 값 변경은 원격이라 무관)
이 결정을 다시 열어야 할 때
- Datadog가 RSC·서버 액션·route handler를 지원하기 시작할 때 (현재 미지원이라 플래그는 클라이언트 컴포넌트 전용)
- native provider가 순수 JS 구현으로 제공될 때 → 예외를 없애고 web과 완전히 통일할 수 있다
Last updated on