Statsig 입문 2편 — SDK Quickstart · 30분 첫 Feature Gate

2026-05-17Statsig 입문에서 운영까지

Statsig 입문 2편. SDK Quickstart 의 4단계 (패키지 설치 → 초기화 → API key → 사용) 종합 실습. Node.js · Python · Java · JavaScript · React 언어별 초기화 코드, Client Key vs Server Secret 분기, 첫 Feature Gate · Dynamic Config · Experiment · logEvent 호출, StatsigUser 객체 설계, environment 옵션, custom IDs, 처음부터 잘 설계해야 하는 자리들까지 풀어쓴 학습 노트.

📚 Statsig 입문에서 운영까지 · 2편 — SDK Quickstart · 30분 첫 Feature Gate

이 글은 Statsig 입문에서 운영까지 시리즈 2편이에요. 1편 에서 Statsig 가 뭘 해주는 플랫폼인가 큰 그림을 봤다면, 이번 2편은 실제로 코드에 박는 첫 30분SDK Quickstart (개발 환경에 라이브러리 붙이는 4단계 가이드)의 4단계예요.

이번 글의 목표

이 글을 끝까지 따라하면 Statsig 계정 → SDK 설치 → 첫 Feature Gate 분기 → 대시보드에서 ON/OFF 까지 end-to-end (앞단 코드부터 운영 대시보드까지 전 구간)가 됩니다.

목표는 30분 안에 첫 gate 박기. 코드 한 줄로 분기되는 기능재배포 없이 대시보드에서 켜고 끄는 경험이에요.

처음 들으면 헷갈리는 자리

Quickstart 가 어렵게 느껴지는 자리가 두 군데예요.

첫째, Client Key 와 Server Secret 의 분기. 두 키가 역할이 다른데 처음엔 어느 코드에 어느 키 인지 헷갈려요.

둘째, 언어별 SDK 의 미묘한 차이. Node.js · Python · Java · React 가 같은 개념 이지만 API 명칭이 조금씩 다름. 공통 패턴 + 언어별 차이 둘 다 봐야 머리에 박혀요.

해결법은 4단계 한 그림 으로 잡는 것. 단계가 분명하면 어느 언어든 똑같이 풀려요.

Quickstart 4단계 — 큰 그림

단계 무엇
1. 패키지 설치 npm/pip/maven 으로 SDK 추가
2. SDK 초기화 앱 시작 시 1회 initialize()
3. API key 박기 Client Key 또는 Server Secret
4. 사용 checkGate · getConfig · getExperiment · logEvent

→ 모든 SDK 가 이 4단계. 언어별 차이는 문법 표면 만이에요.

지원 SDK 종류 — 어떤 걸로 시작할까

Statsig 공식 Quickstart 가 제공하는 SDK 큰 묶음이에요.

Client SDK (브라우저·모바일·데스크탑)

React · JavaScript · React Native · Next.js · Angular · Swift (iOS/macOS/tvOS) · Android · .NET Client · Flutter · Roku · Unity · C++ Client.

Server SDK (백엔드)

Node.js · Python · Java · Go · Ruby · PHP · Rust · .NET Core.

어디부터우리 회사 stack 의 주력 언어 1개 부터예요. 대부분 환경을 보면 웹 SPA (Single Page Application, 페이지 전환 없이 도는 단일 페이지 앱)는 React 또는 JavaScript (브라우저), 백엔드 API 는 Node.js · Java · Python 중 하나, 모바일은 Swift (iOS) · Android (Kotlin) · Flutter (cross) 로 나뉘죠.

처음엔 한 SDK 만 박고 익숙해진 다음 다른 plat 추가하는 흐름이 안전해요.

단계 1: 패키지 설치

Node.js

npm install @statsig/js-server
# 또는
yarn add @statsig/js-server

Python

pip install statsig-python-core

Java (Gradle)

implementation 'com.statsig:javacore:LATEST_VERSION'

Java (Maven)

<dependency>
    <groupId>com.statsig</groupId>
    <artifactId>javacore</artifactId>
    <version>LATEST_VERSION</version>
</dependency>

React

npm install @statsig/react-bindings

JavaScript (Snippet — 빌드 도구 없이)

<script> 한 줄로 CDN (Content Delivery Network, 정적 파일 배포 캐시 망) 에서 직접 로드 가능. 빌드 없는 정적 사이트·랜딩 페이지에 유용해요.

단계 2: SDK 초기화

여기가 언어별로 가장 차이 큰 자리. 패턴만 잡으면 다른 SDK 도 응용 가능해요.

Node.js (Server)

import Statsig from '@statsig/js-server';

const statsig = new Statsig("server-SECRET_KEY");
await statsig.initialize();

// 이제 사용 가능

initialize()rule set 을 Statsig 서버에서 fetch 후 메모리 적재하는 일이에요. 앱 시작 시 1회 await 필수. 그 후 매 요청 평가로컬 메모리 lookup 이라 빠르죠.

Python (Server)

from statsig_python_core import Statsig

options = {"environment": "production"}
statsig = Statsig("server-SECRET_KEY", options)
statsig.initialize().wait()

initialize().wait() 패턴은 비동기 초기화 + 완료 대기 의미. Node.js 의 await 와 동일해요.

React (Client)

import { StatsigProvider } from '@statsig/react-bindings';

function App() {
  return (
    <StatsigProvider
      sdkKey="client-PUBLIC_KEY"
      user={{ userID: "user-id" }}
      loadingComponent={<div>Loading...</div>}
    >
      <YourApp />
    </StatsigProvider>
  );
}

StatsigProviderReact Context 로 SDK 주입. 최상위에 한 번 만 wrap 하면 돼요.

loadingComponent = SDK 초기화 중 (network round-trip) 표시할 UI. 잠깐의 blank 상태 회피용이에요.

JavaScript (Snippet)

<script src="https://cdn.jsdelivr.net/npm/@statsig/js-client@3/build/statsig-js-client.min.js?apikey=client-KEY"></script>
<script>
  // initialize 후 사용
</script>

빌드 도구 없는 환경에서 CDN 한 줄 + URL query 의 apikey 로 키 전달이에요.

여기서 시험 함정이 하나 있어요 — CDN snippet 방식은 client key 가 URL 에 박힘 = 누구나 볼 수 있어요. 그래서 Client Key 는 반드시 공개 안전한 키 여야 해요. Server Secret 을 절대 client 측에 두지 말 것.

단계 3: API key — Client Key vs Server Secret

여기서 정말 중요한 시험 함정 — 두 키의 의미가 다름.

항목 Client Key Server Secret
공개 가능? ✓ (브라우저·모바일 코드에 박힘) ✗ (절대 외부 노출 X)
prefix client- secret- 또는 server-
사용 위치 React · JS · Swift · Android Node.js · Python · Java · Go
권한 read-only · 평가만 평가 + event 로깅 + 운영
rotation 정기 교체 권장 유출 시 즉시 rotation

키 발급 위치

Statsig console → Project Settings → API Keys. 거기서 Client KeyServer Secret 별도로 생성해요.

환경 분리

대부분 환경은 Development · Staging · Production 별로 각각 키 발급. 키 prefix 또는 metadata 에서 환경 구분하는 식이에요.

권장 패턴:

// 환경 변수로 분리
const sdkKey = process.env.STATSIG_SERVER_KEY;
const statsig = new Statsig(sdkKey);

코드에 키 하드코딩 금지. env 변수 + secrets manager (AWS Secrets · GCP Secret · Vault) 같은 키 보관소를 써요.

Server Secret 유출 = 즉시 rotation

만약 git push 또는 log 로 Server Secret 노출 됐다면 즉시 rotation + 노출 기간 동안 비정상 activity 점검. Public repo 에 commit 했으면 git history 도 정리 (Bitwarden 같은 secrets scanner 활용).

단계 4: 사용 — Gate · Config · Experiment · Event

Feature Gate 체크

// Node.js
const user = { userID: "user-123", email: "user@example.com" };
const showFeature = statsig.checkGate(user, "show_new_checkout");

if (showFeature) {
  // 새 결제 흐름
} else {
  // 기존 결제 흐름
}
# Python
from statsig_python_core import StatsigUser

user = StatsigUser(user_id="user-123", email="user@example.com")
show_feature = statsig.check_gate(user, "show_new_checkout")
// React (hook 활용)
import { useGate } from '@statsig/react-bindings';

function CheckoutPage() {
  const { value: showFeature } = useGate("show_new_checkout");
  return showFeature ? <NewCheckout /> : <OldCheckout />;
}

checkGate(user, gateName) 의 두 인자 — 사용자 객체 + gate (특정 기능을 켜고 끄는 분기 스위치) 이름. 반환은 boolean 이에요.

Dynamic Config 가져오기

// Node.js
const config = statsig.getConfig(user, "checkout_settings");
const minOrderValue = config.get("min_order_value", 50);    // default 50
const freeShippingFrom = config.get("free_shipping_from", 100);

get(key, defaultValue) — config 에 해당 key 가 없으면 default 반환. production 안전 기본값 필수예요.

Experiment 평가

// Node.js
const experiment = statsig.getExperiment(user, "button_color_test");
const buttonColor = experiment.get("color", "blue");

Dynamic Config 와 거의 동일한 API. 통계적 추적 이 자동으로 백엔드에 기록되는 게 차이예요.

Event 로깅

// Node.js
statsig.logEvent(user, "checkout_completed", "1500", {
  currency: "KRW",
  items_count: 3,
  payment_method: "card"
});

logEvent(user, eventName, value?, metadata?) 의 4 인자는 eventName 이벤트 이름, value 숫자 또는 문자열 (예: 결제 금액), metadata 추가 속성 (object) 으로 나뉘어요.

이 event 가 Product Analytics 의 funnel (구매 전환 단계별 이탈 추적) · retention (재방문 유지율) · cohort (가입 시점 단위 묶음) 에 자동 반영. 1편의 6 차트가 여기서 박은 event 로 만들어져요.

가장 단순한 첫 gate end-to-end

// 1. SDK 초기화 (app start)
const statsig = new Statsig(process.env.STATSIG_SERVER_KEY);
await statsig.initialize();

// 2. 매 요청에서 gate 체크
app.get('/checkout', (req, res) => {
  const user = { userID: req.user.id };
  const useNewFlow = statsig.checkGate(user, "new_checkout_flow");

  if (useNewFlow) {
    return res.render('checkout-v2');
  }
  return res.render('checkout-v1');
});

// 3. 결제 완료 event 로깅
app.post('/checkout/complete', (req, res) => {
  const user = { userID: req.user.id };
  statsig.logEvent(user, "checkout_completed", req.body.amount);
  // ...
});

이게 minimal end-to-end. Statsig console 의 Feature Gates → Create Gate → "new_checkout_flow" 으로 gate 생성 후 10% rollout (전체 사용자 중 일부에게만 단계적 노출) 설정하면 코드 한 줄도 안 바꾸고 10% 사용자만 새 flow 노출돼요.

StatsigUser 객체 설계 — 처음부터 잘 잡아야 하는 자리

StatsigUser (또는 user object) 가 Statsig 의 모든 평가의 기준. user ID 설계 가 운영의 처음이자 끝이에요.

표준 필드

const user = {
  userID: "stable-user-123",          // 로그인 사용자 ID (가장 중요)
  email: "user@example.com",
  ip: "1.2.3.4",
  country: "KR",
  locale: "ko-KR",
  appVersion: "1.5.0",
  userAgent: "...",
  custom: {
    tier: "premium",                    // 비즈니스 속성
    signupDate: "2024-01-01",
    company: "acme-corp"
  }
};

Custom IDs — Multi-tenant 환경

const user = {
  userID: "user-123",
  customIDs: {
    "companyID": "company-456",
    "deviceID": "device-789",
    "sessionID": "session-abc"
  }
};

Custom IDs 가 강력한 이유 — 일반 userID독립적으로 무작위화 가능. 예: B2B SaaS (Business-to-Business, 기업 대상 소프트웨어 서비스) 가 company 단위 로 실험하는 식이에요.

여기서 시험 함정이 하나 있어요 — userID 만으로 실험하면 같은 회사의 사용자 A, B 가 다른 variant (실험에서 사용자에게 노출되는 분기 갈래) 일 수 있어요. B2B 는 customIDs.companyID 로 무작위화 가 일반적이에요.

Anonymous User (로그인 전)

const user = {
  userID: undefined,                   // 로그인 전
  customIDs: {
    "deviceID": getOrCreateDeviceID()  // 디바이스 단위
  }
};

로그인 전 사용자도 experiment 에 포함 가능. device 단위 무작위화 후 로그인 시점에 userID 추가하면 돼요.

user object 의 일관성

같은 사용자 = 모든 SDK 가 같은 user 정보 보내야 함. Server SDK 에서 user.email 박았는데 Client SDK 에서 안 박으면 → 두 SDK 의 평가 결과 다를 수 있어요 (rule 이 email 기반인 경우).

user object 의 구성 코드유틸 함수로 추출 하는 게 안전해요.

SDK 초기화 옵션 — 자주 쓰는 자리

environment

options = {"environment": "production"}      # 또는 "staging" · "development"
statsig = Statsig(SDK_KEY, options)

같은 코드 + 다른 환경 키 로 운영. 환경별 *gate · experiment * 분리돼요.

timeout · network 옵션

const options = {
  initTimeoutMs: 3000,          // initialize timeout
  syncInterval: 60_000,         // rule sync 주기 (ms)
};
const statsig = new Statsig(SDK_KEY, options);

initTimeoutMs — Statsig 서버 응답 3초 초과 시 fallback (default value 로 동작). 운영 안전선이에요.

bootstrap (React · Next.js SSR)

// Server-side rendering 환경
<StatsigProvider
  sdkKey="client-key"
  user={user}
  bootstrapValues={prefetchedValuesFromServer}      // 서버에서 미리 가져온 값
>

초기 깜빡임 (flicker) 회피 — 서버에서 evaluated values 미리 가져온 후 client SDK 에 주입. SSR (Server-Side Rendering, 서버에서 HTML 미리 그려 보내는 방식) · Next.js 표준 패턴이에요.

자주 만나는 사고 — 30분 첫 통합

사고 1: initialize() 못 기다림

원인await 누락 → SDK 초기화 전 checkGate 호출.

해결 — Node.js await statsig.initialize(); · Python .initialize().wait(). 초기화 전 모든 호출 = default 값.

사고 2: Client 에 Server Secret 박음

원인 — React 앱 에 secret-... key 사용 → 누구나 브라우저 DevTools 에서 볼 수 있음.

해결 — Client = client-... key 만. immediate rotation if 유출.

사고 3: user.userID 가 동적

원인 — 매 요청마다 다른 userID (예: UUID 매번 생성).

해결stable user ID (DB 의 user.id). anonymous 는 deviceID 로.

사고 4: Event name 오타

원인"checkoutCompleted""checkout_completed" 가 혼용 → analytics 에서 두 event 로 갈림.

해결 — event name 상수화 (const EVENT_CHECKOUT_COMPLETED = "checkout_completed";) + naming convention 정의.

사고 5: Initialize timeout

원인 — Statsig 서버 응답 지연 → initTimeoutMs 초과 → SDK 가 default value 모드.

해결initTimeoutMs 늘림 (5000ms 등) + fallback 시 안전한 default 보장.

사고 6: React 의 SSR flicker

원인 — server-side render = gate OFF, client mount 후 = gate ON → 깜빡임.

해결bootstrapValues 또는 서버에서 evaluated values 주입.

사고 7: Custom 필드 type 불일치

원인user.custom.signupDate어떤 곳은 string, 어떤 곳은 Date 객체.

해결team-wide user schema 정의 (TypeScript interface · Python dataclass).

운영 권장 패턴 — 처음부터 잘 잡기

Pattern 1: User factory 함수

// utils/statsig-user.js
export function buildStatsigUser(req) {
  return {
    userID: req.user?.id,
    email: req.user?.email,
    ip: req.ip,
    country: req.headers['cf-ipcountry'],
    customIDs: {
      "companyID": req.user?.companyId,
      "deviceID": req.cookies.deviceId
    },
    custom: {
      tier: req.user?.tier,
      signupDate: req.user?.createdAt
    }
  };
}

// 사용
const user = buildStatsigUser(req);
const showFeature = statsig.checkGate(user, "...");

모든 호출이 같은 user object 사용. 일관성이 보장돼요.

Pattern 2: 환경별 SDK key

# application.yml
statsig:
  server-key: ${STATSIG_SERVER_KEY}
  environment: ${SPRING_PROFILES_ACTIVE:production}
// Spring Boot
@Value("${statsig.server-key}") private String sdkKey;
@Value("${statsig.environment}") private String environment;

@Bean
public Statsig statsig() {
    StatsigOptions options = StatsigOptions.builder()
        .environment(environment)
        .build();
    Statsig statsig = new Statsig(sdkKey, options);
    statsig.initialize();
    return statsig;
}

profile 별 자동 분리 — local/dev/prod.

Pattern 3: Event 표준 정의

// types/events.ts
export const STATSIG_EVENTS = {
  CHECKOUT_STARTED: "checkout_started",
  CHECKOUT_COMPLETED: "checkout_completed",
  ITEM_VIEWED: "item_viewed",
  // ...
} as const;

export type EventName = typeof STATSIG_EVENTS[keyof typeof STATSIG_EVENTS];

TypeScript 의 as const + union type = event name 오타 컴파일 타임 검출.

Pattern 4: Server + Client 동시 사용

[브라우저]                   [Server]
React Client SDK           Node.js Server SDK
   ↓                          ↓
client-PUBLIC_KEY          server-SECRET_KEY
   ↓                          ↓
같은 user.userID 사용 →   같은 variant 결정

같은 user ID 면 Statsig 의 deterministic hashing (같은 입력은 항상 같은 분기로 가는 해시) 으로 모든 SDK 가 같은 variant. UI 일관 + 서버 측 metric 정확하게 나와요.

Pattern 5: Bootstrap (Next.js SSR)

// app/page.tsx (server component)
import { headers } from 'next/headers';

async function getStatsigBootstrap(user) {
  // Server SDK 로 evaluated values 가져오기
  return await serverStatsig.getClientInitializeResponse(user);
}

export default async function Page() {
  const user = { userID: getCurrentUserId() };
  const bootstrapValues = await getStatsigBootstrap(user);

  return (
    <StatsigProvider sdkKey="client-..." user={user} bootstrapValues={bootstrapValues}>
      <App />
    </StatsigProvider>
  );
}

서버에서 미리 평가 → client 에 inject → flicker 없는 SSR.

시험 직전 한 번 더 — SDK Quickstart 함정 압축 노트

  • Quickstart 4 단계 = 패키지 설치 → SDK 초기화 → API key → 사용
  • 지원 SDK 약 22종 (Client + Server)
  • 시작 권장 = 주력 언어 1개 부터, 익숙해진 다음 plat 추가
  • 단계 1 패키지 설치 — npm · pip · maven · gradle
  • 단계 2 SDK 초기화 = 앱 시작 시 1회 initialize()
  • Node.js = await statsig.initialize()
  • Python = statsig.initialize().wait()
  • Java = Statsig.initialize() (builder 옵션 활용)
  • React = <StatsigProvider sdkKey user loadingComponent>
  • JS Snippet = CDN script + URL query apikey
  • rule set 메모리 적재 = 초기화의 의미, 매 요청 = 로컬 lookup (빠름)
  • 단계 3 API key = Client Key (client-) vs Server Secret (secret- / server-)
  • Client Key = 공개 안전, brower/mobile 에 박힘
  • Server Secret = 절대 외부 X, 유출 시 즉시 rotation
  • 환경별 (Dev/Staging/Prod) 별도 key
  • 코드 하드코딩 X, env var + secrets manager
  • 단계 4 사용 = checkGate · getConfig · getExperiment · logEvent
  • checkGate(user, gateName) → boolean
  • getConfig(user, name) → config object, .get(key, default) 로 값
  • getExperiment(user, name) → 같은 패턴 + 통계 자동 추적
  • logEvent(user, name, value, metadata) → Product Analytics 의 데이터 원천
  • StatsigUser 표준 필드 = userID · email · ip · country · locale · appVersion · userAgent · custom
  • customIDs = multi-tenant 환경의 무작위화 단위 (companyID · deviceID · sessionID)
  • B2B = customIDs.companyID 로 무작위화 (B2C 는 userID)
  • Anonymous user = userID undefined + deviceID
  • user object 일관성 — Server·Client·iOS·Android 모두 같은 user 필드
  • user factory 함수 권장 (utils/statsig-user.js)
  • environment 옵션 = production · staging · development
  • initTimeoutMs = 초기화 timeout (운영 안전선)
  • syncInterval = rule sync 주기
  • bootstrapValues (React/Next.js SSR) = flicker 회피
  • 함정 — initialize await 누락 → default 값 모드
  • 함정 — Client 에 Server Secret = 즉시 유출
  • 함정 — user.userID 가 동적 (UUID 매번) → 같은 사용자도 다른 variant
  • 함정 — Event name 오타 (checkoutCompleted vs checkout_completed) → 두 event 갈림
  • 함정 — initialize timeout → fallback default 값
  • 함정 — React SSR flicker → bootstrapValues
  • 함정 — custom 필드 type 불일치 → user schema 정의
  • 패턴 — user factory 함수
  • 패턴 — 환경별 SDK key (env var · profile)
  • 패턴 — event name 상수 + TypeScript as const
  • 패턴 — Server + Client 동시 사용 (deterministic hashing)
  • 패턴 — Next.js SSR bootstrap
  • 결과 — 코드 한 번 + 대시보드에서 ON/OFF · rollout · A/B

공식 문서: Statsig SDK Quickstart 에서 원문을 확인할 수 있어요.

시리즈 다른 편 (앞뒤 글 모음)

이전 글:

다음 글:

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!