Braze 입문 2편 — SDK 통합 · REST API · 첫 캠페인 30분

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

Braze 입문 2편. SDK 통합 + 첫 캠페인 end-to-end 흐름. Web · iOS · Android SDK 5분 설치, REST API (POST /users/track) 의 batch 패턴, External ID 매핑의 의미, User Alias 의 anonymous 단계 처리, Custom Event · Purchase · Attribute 3 모델, console 에서 Segment + Campaign 만들기 흐름, REST API key vs SDK key 보안, baseUrl 지역별 endpoint, rate limit 까지 풀어쓴 학습 노트.

📚 Braze 입문에서 운영까지 · 2편 — SDK 통합 · REST API · 첫 캠페인 30분

이 글은 Braze 입문에서 운영까지 시리즈 2편이에요. 1편큰 그림 다음 — 실제로 코드에 박는 첫 30분. 통합부터 console 에서 첫 메시지 보내기 까지.

이번 글의 목표

이 글을 끝까지 따라하면 Braze workspace → SDK 설치 → 첫 사용자 추적 → 첫 캠페인 발송 까지 end-to-end 가 됩니다.

목표 = 30분 안 첫 메시지 도달. 우리 앱·웹에서 직접 만든 사용자 에게 console 에서 보낸 첫 email · push.

통합의 두 갈래

Braze 와 데이터를 주고받는 방법:

방식 사용
SDK (Software Development Kit, Web · iOS · Android · ...) 사용자 디바이스에서 자동 추적 + 메시지 수신
REST API (HTTP 기반 서버 통신 규약) 서버에서 명시 추적 + 메시지 전송

대부분 운영 = 둘 다 함께. Client SDK = 사용자 행동 자동, Server REST API = 백엔드 이벤트 + 메시지 발송.

Web SDK — 5분 통합

설치

npm install @braze/web-sdk
# 또는
yarn add @braze/web-sdk

초기화

import * as braze from "@braze/web-sdk";

braze.initialize("YOUR_SDK_API_KEY", {
  baseUrl: "sdk.iad-01.braze.com",     // ★ 지역별 endpoint
  enableLogging: false,                  // production = false
  minimumIntervalBetweenTriggerActionsInSeconds: 30
});

여기서 시험 함정이 하나 있어요 — baseUrl 의 지역별 endpoint. Braze 는 workspace 가 어느 region 에 있는지 에 따라 다른 endpoint:

Region baseUrl
US-01 sdk.iad-01.braze.com
US-02 sdk.iad-02.braze.com
US-03 ~ US-08 sdk.iad-03.braze.com ~ sdk.iad-08.braze.com
EU-01 sdk.fra-01.braze.eu
EU-02 sdk.fra-02.braze.eu
AU-01 sdk.au-01.braze.com

console → Settings → APIs and Identifiers 에서 확인.

→ 잘못된 baseUrl = 연결 안 됨. 가장 흔한 초기 실수.

External ID 설정

// 사용자 로그인 시점
braze.changeUser(user.id);              // External ID
braze.getUser().setEmail(user.email);
braze.getUser().setCountry("KR");
braze.getUser().setLanguage("ko");
braze.getUser().setCustomAttribute("tier", "premium");
braze.openSession();

changeUser(externalId) = 가장 중요한 호출. Braze user우리 DB user 의 연결.

Custom Event 박기

braze.logCustomEvent("product_viewed", {
  product_id: "P-123",
  category: "shoes",
  price: 50000
});

braze.logCustomEvent("checkout_completed", {
  cart_value: 150000,
  items_count: 3,
  payment_method: "card"
});

1편의 5 핵심 개념Event 데이터 모델. 동사_명사 + snake_case 권장 (산업 공통).

Purchase 박기 (별도 모델)

braze.logPurchase(
  "product_id",      // 상품 ID
  50000,             // 금액
  "KRW",             // 통화
  1,                 // 수량
  {                  // 추가 속성
    category: "shoes",
    discount_applied: true
  }
);

Purchase 는 Custom Event 와 다른 모델. LTV(고객 생애 가치) · ARPU(사용자당 평균 매출) 분석 자동 + 결제 기반 segment. 결제는 항상 logPurchase, 일반 event 아님.

iOS SDK — 5분 통합

설치 (CocoaPods)

CocoaPods(iOS 의존성 매니저)로 라이브러리를 박는 흐름.

# Podfile
pod 'BrazeKit'
pod 'BrazeUI'              # in-app message UI
pod 'BrazeNotificationService'
pod install

초기화 (Swift)

import BrazeKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    static var braze: Braze?

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: ...) -> Bool {
        let configuration = Braze.Configuration(
            apiKey: "YOUR_IOS_API_KEY",
            endpoint: "sdk.iad-01.braze.com"
        )
        AppDelegate.braze = Braze(configuration: configuration)
        return true
    }
}

External ID 설정

AppDelegate.braze?.changeUser(userId: user.id)
AppDelegate.braze?.user.setEmail("user@example.com")
AppDelegate.braze?.user.setCustomAttribute(key: "tier", value: "premium")

Event · Purchase

AppDelegate.braze?.logCustomEvent(
    name: "product_viewed",
    properties: ["product_id": "P-123"]
)

AppDelegate.braze?.logPurchase(
    productId: "product_id",
    currency: "KRW",
    price: 50000.0,
    quantity: 1
)

Push 권한 + 토큰 등록

import UserNotifications

UNUserNotificationCenter.current().requestAuthorization(
    options: [.alert, .badge, .sound]
) { granted, _ in
    if granted {
        DispatchQueue.main.async {
            UIApplication.shared.registerForRemoteNotifications()
        }
    }
}

// AppDelegate 의 didRegisterForRemoteNotificationsWithDeviceToken
AppDelegate.braze?.notifications.register(deviceToken: deviceToken)

iOS Push = 권한 요청 + APNs(애플 푸시 알림 서비스) token Braze 등록. 둘 다 필수.

Android SDK — 5분 통합

설치 (Gradle)

// app/build.gradle
dependencies {
    implementation "com.braze:android-sdk-ui:LATEST_VERSION"
}

초기화 (Kotlin)

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()

        val config = BrazeConfig.Builder()
            .setApiKey("YOUR_ANDROID_API_KEY")
            .setCustomEndpoint("sdk.iad-01.braze.com")
            .build()
        Braze.configure(this, config)
    }
}

AndroidManifest.xml:

<application android:name=".MyApp">
    ...
</application>

External ID · Event · Purchase

// 로그인 시점
Braze.getInstance(this).changeUser(user.id)
Braze.getInstance(this).currentUser?.setEmail(user.email)
Braze.getInstance(this).currentUser?.setCustomAttribute("tier", "premium")

// Event
val properties = BrazeProperties()
    .add("product_id", "P-123")
    .add("category", "shoes")
Braze.getInstance(this).logCustomEvent("product_viewed", properties)

// Purchase
Braze.getInstance(this).logPurchase("product_id", "KRW", BigDecimal("50000"), 1)

FCM Push 토큰 등록

FCM(Firebase Cloud Messaging, 구글의 안드로이드 푸시 채널) 토큰을 Braze 에 넘기는 자리.

// FirebaseMessagingService
override fun onNewToken(token: String) {
    Braze.getInstance(applicationContext).registeredPushToken = token
}

REST API — 백엔드 통합

인증 — API Key

Authorization: Bearer YOUR_REST_API_KEY. — 공식 docs

curl -X POST https://rest.iad-01.braze.com/users/track \
  -H "Authorization: Bearer YOUR_REST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "attributes": [...],
    "events": [...],
    "purchases": [...]
  }'

여기서 정말 중요한 시험 함정 — REST API Key 와 SDK Key 는 다름:

항목 SDK Key REST API Key
공개 가능? ✓ (Client SDK 박힘) ✗ (절대 외부 X)
권한 event 로깅 + 메시지 수신 전체 운영 (user 관리 + 메시지 발송 + 분석 등)
위치 Web · iOS · Android Server only
유출 시 비교적 안전 즉시 rotation 필수
prefix (workspace 별) 보통 별도 발급

REST API Key 는 권한별 발급user track 용 · messaging 용 · analytics 용 분리 가능. 최소 권한 원칙.

Endpoint 의 지역별 분리

US-01: https://rest.iad-01.braze.com
US-02: https://rest.iad-02.braze.com
EU-01: https://rest.fra-01.braze.eu
AU-01: https://rest.au-01.braze.com

SDK 의 baseUrl 과 같은 지역 기반. console 에서 확인.

가장 중요한 endpoint — POST /users/track

/users/track = User 프로필 생성/업데이트 + 이벤트 + 결제 기록. — 공식 docs

Body 구조

{
  "attributes": [
    {
      "external_id": "user-123",
      "email": "user@example.com",
      "country": "KR",
      "tier": "premium",
      "last_login_date": "2026-05-17T09:00:00Z"
    }
  ],
  "events": [
    {
      "external_id": "user-123",
      "name": "checkout_completed",
      "time": "2026-05-17T09:15:00Z",
      "properties": {
        "cart_value": 50000,
        "items_count": 3
      }
    }
  ],
  "purchases": [
    {
      "external_id": "user-123",
      "product_id": "P-123",
      "currency": "KRW",
      "price": 50000,
      "quantity": 1,
      "time": "2026-05-17T09:15:00Z"
    }
  ]
}

한 요청에 attributes · events · purchases 동시 batch — 효율적.

Identifier 우선순위

Primary = external_id · user_alias · braze_id. Secondary = email · phone. — 공식 docs

primary 가 있으면 email/phone 은 attribute 로 처리되고, primary 가 없으면 email/phone 으로 사용자 lookup 이 돌아갑니다.

External ID 가 표준. 우리 DB user.id = external_id 매핑.

Batch 한도

Standard customers: 한 요청에 최대 75 objects total (attributes + events + purchases 합산). — 공식 docs

Request 1: attributes 25 + events 30 + purchases 20 = 75  ✓
Request 2: attributes 80                            = 80  ✗ 거부

대량 sync = 75 단위 split. 일반 운영은 보통 한 사용자 1~5 object 라 한도 안 닿음.

Rate Limit

Base: 3,000 requests / 3 seconds
시간당: 250,000 requests

대량 import = exponential backoff(재시도 간격을 지수로 늘리는 방식) + retry 필수.

Python 예제

import requests
from datetime import datetime, timezone

BRAZE_REST_URL = "https://rest.iad-01.braze.com"
BRAZE_API_KEY = os.environ["BRAZE_REST_API_KEY"]

def track_purchase(external_id: str, product_id: str, price: int):
    response = requests.post(
        f"{BRAZE_REST_URL}/users/track",
        headers={
            "Authorization": f"Bearer {BRAZE_API_KEY}",
            "Content-Type": "application/json"
        },
        json={
            "purchases": [{
                "external_id": external_id,
                "product_id": product_id,
                "currency": "KRW",
                "price": price,
                "quantity": 1,
                "time": datetime.now(timezone.utc).isoformat()
            }]
        }
    )
    response.raise_for_status()
    return response.json()

# 사용
track_purchase("user-123", "P-456", 50000)

Node.js 예제

import axios from "axios";

const braze = axios.create({
  baseURL: "https://rest.iad-01.braze.com",
  headers: {
    Authorization: `Bearer ${process.env.BRAZE_REST_API_KEY}`,
    "Content-Type": "application/json"
  }
});

async function trackUser(userId, attributes, events) {
  const response = await braze.post("/users/track", {
    attributes: [{
      external_id: userId,
      ...attributes
    }],
    events: events.map(e => ({
      external_id: userId,
      name: e.name,
      time: new Date().toISOString(),
      properties: e.properties
    }))
  });
  return response.data;
}

External ID 설계 — 처음부터 잘 잡기

여기가 운영의 처음이자 끝. External ID 결정6개월 후의 모든 분석 의 기반.

External ID 선택 원칙

좋은 후보 나쁜 후보
DB의 user.id (BIGINT) email (변경 가능)
UUID (불변) session_id (매번 다름)
외부 SSO subject phone (변경 가능)

핵심불변 + unique + 우리 시스템 내 표준. email · phone 은 변경 가능 해서 부적합. 대부분 = DB user.id 또는 UUID(범용 고유 식별자).

Anonymous 사용자 (로그인 전)

// 가입 전 사용자
braze.changeUser(undefined);             // External ID 없음
// → Braze 가 자동으로 braze_id (anonymous) 생성

// 사용자 행동 추적 (anonymous 상태)
braze.logCustomEvent("landing_viewed", { ... });

// 로그인 시점 — External ID 연결
braze.changeUser(user.id);
// → 이전 anonymous 활동이 user.id 로 merge

Anonymous → 로그인 transition 의 자연스러운 merge. 기존 행동 손실 X.

User Alias — 추가 매핑

braze.getUser().addAlias("legacy_user_id", "legacy");
braze.getUser().addAlias("crm_contact_id", "salesforce");

Alias = External ID 외 부가 식별자. 여러 시스템 통합 시 유용 — 마이그레이션 중인 legacy 시스템 ID, CRM(Customer Relationship Management) 의 Salesforce contact ID, 외부 마케팅 도구 ID 같은 자리에서 씁니다.

Event · Attribute · Purchase 의 차이

여기서 자주 헷갈리는 자리 — 언제 무엇으로 박나.

정성 (Attribute) vs 정량 (Event)

User Attribute:
  - 사용자 *상태* (현재 값)
  - update 가능, 누적 X
  - 예: tier, country, email, signup_year

Custom Event:
  - 사용자 *행동* (timestamp 있음)
  - append-only, 누적
  - 예: product_viewed, login, search_performed

결제 = Purchase 별도

Custom Event "purchase" 로 박는 것 = 나쁜 패턴
Purchase 별도 모델로 박기 = 올바름

이유 — Purchase 가 LTV · ARPU · 결제 기반 segment 의 표준 자리. Custom Event 로 박으면 이 자동 분석 안 됨.

Subscription State 도 별도

// 이메일 옵트인
braze.getUser().setEmailNotificationSubscriptionType("opted_in");

// 푸시 거부
braze.getUser().setPushNotificationSubscriptionType("unsubscribed");

// SMS 동의
braze.getUser().setSubscriptionGroupSubscriptionState("group-id", "subscribed");

법적 안전 + 발송 자동 필터. 동의·거부 항상 기록.

Console 에서 첫 캠페인 — 5 단계

SDK + REST API 로 데이터 흐름 잡았으면, 이제 console 에서 메시지 보내기.

Step 1: Segment 만들기

Audience > Segments > Create Segment:

Segment 이름: "Active iOS 사용자"

Filter:
  - Most Recent App is "iOS"
  - Last Used App is within 7 days
  - Custom Attribute "tier" is "premium" OR "enterprise"

재사용 가능한 사용자 그룹. 이 segment 를 여러 캠페인/Canvas 에서 사용.

Step 2: Campaign 시작

Engagement > Campaigns > Create Campaign:

Campaign 종류: Push Notification (iOS · Android)
Campaign 이름: "여름 세일 알림"

Step 3: Audience 선택

Audience: Segment "Active iOS 사용자" (Step 1)
Estimated reach: 12,500 사용자

Step 4: Content 작성

Title: "여름 세일 시작!"
Body: "{{ ${first_name} | default: '회원님' }}님, 좋아하시는 상품 30% 할인 중이에요"

Deep link: myapp://sale
Image: (선택)

1편의 Liquid templating{{ first_name }} 으로 개인화. default 필수.

Step 5: Schedule + 발송

Send: One-time
Time: 2026-07-01 09:00 KST
또는: "Send as soon as possible" (즉시 발송)

Launch 클릭 → 발송 시작 → console 에서 delivery · open · click 실시간 추적.

첫 발송 후 확인

Dashboard > Campaign Report:
  - Sent: 12,453
  - Delivered: 12,401 (99.5%)
  - Opened: 4,326 (34.9%)
  - Clicked: 1,234 (28.5% CTR)
  - Conversions: 87 (결제 event)

5편 Product Analytics 와 비슷한 통합 dashboard — Braze 도 발송 → 행동 → 결제 자동 funnel.

End-to-End 30분 예시 — Web 앱

// 1. SDK 초기화 (앱 시작 시 한 번)
import * as braze from "@braze/web-sdk";

braze.initialize(process.env.BRAZE_SDK_KEY, {
  baseUrl: "sdk.iad-01.braze.com",
  enableLogging: process.env.NODE_ENV === "development"
});

// 2. 사용자 로그인 시
async function onLogin(user) {
  braze.changeUser(user.id);
  braze.getUser().setEmail(user.email);
  braze.getUser().setCountry(user.country);
  braze.getUser().setLanguage(user.language);
  braze.getUser().setCustomAttribute("tier", user.tier);
  braze.getUser().setCustomAttribute("signup_year", user.signupYear);
  braze.openSession();
}

// 3. 주요 행동 추적
function trackProductView(product) {
  braze.logCustomEvent("product_viewed", {
    product_id: product.id,
    category: product.category,
    price: product.price
  });
}

function trackCheckoutStart(cart) {
  braze.logCustomEvent("checkout_started", {
    cart_value: cart.total,
    items_count: cart.items.length
  });
}

function trackPurchase(order) {
  for (const item of order.items) {
    braze.logPurchase(
      item.productId,
      item.price,
      "KRW",
      item.quantity,
      { category: item.category }
    );
  }
}

// 4. 로그아웃
function onLogout() {
  braze.changeUser(undefined);    // Anonymous 로 전환
}

서버 측 (Node.js):

// 결제 완료 webhook 에서 다시 한 번 (확실한 추적)
async function onPurchaseWebhook(order) {
  await braze.post("/users/track", {
    purchases: order.items.map(item => ({
      external_id: order.userId,
      product_id: item.productId,
      currency: "KRW",
      price: item.price,
      quantity: item.quantity,
      time: order.completedAt
    }))
  });
}

Client + Server 동시 추적. Client 가 driver + Server 가 안전장치.

자주 만나는 사고 — 통합 단계

사고 1: baseUrl 잘못

원인 — 기본 iad-01 사용 → workspace 가 iad-03 → 연결 X.

해결 — console 에서 정확한 endpoint 확인 + 환경 변수.

사고 2: REST API Key 노출

원인 — Server Key 를 Client 또는 git public 에 박음.

해결 — Server only + secrets manager + 즉시 rotation if 유출.

사고 3: External ID 불일치

원인 — Client 는 user.id 박는데 Server 는 user.email → 두 entity 로.

해결user factory 함수 로 일관. 항상 DB user.id 통일.

사고 4: Anonymous → 로그인 transition 안 됨

원인changeUser(externalId) 호출 시점 잘못 (login 전 또는 너무 늦게).

해결로그인 직후 즉시 changeUser. anonymous 행동 자동 merge.

사고 5: Purchase 를 Custom Event 로

원인logCustomEvent("purchase", { ... }) 로 박음.

해결Purchase 는 항상 logPurchase. LTV 자동 분석.

사고 6: Subscription state 무시

원인opt-out 한 사용자 에게 캠페인 발송 → 법 위반.

해결channel 별 subscription 추적 + 발송 자동 필터.

사고 7: Liquid default 누락

원인{{ first_name }} → 누락된 사용자 = "안녕하세요, !".

해결항상 | default: '회원님'.

사고 8: Rate limit hit

원인 — 대량 user import (10만 명) 가 분당 너무 많은 요청.

해결batch 75 / request + exponential backoff + retry.

사고 9: External ID 너무 큼

원인987 bytes 초과EXTERNAL_USER_ID_TOO_LARGE 에러.

해결짧고 안정 ID (DB BIGINT 또는 UUID). 긴 hash 사용 X.

운영 권장 패턴

Pattern 1: User Factory 함수

// utils/braze-user.ts
export function syncUserToBraze(user: User) {
  braze.changeUser(user.id);
  braze.getUser().setEmail(user.email);
  braze.getUser().setFirstName(user.firstName);
  braze.getUser().setCountry(user.country);
  braze.getUser().setLanguage(user.language);
  braze.getUser().setCustomAttribute("tier", user.tier);
  braze.getUser().setCustomAttribute("signup_year", user.signupYear);
  braze.openSession();
}

모든 sync 가 같은 함수 — 일관성.

Pattern 2: Environment 별 SDK Key

# .env.production
BRAZE_SDK_KEY=xxx-prod
BRAZE_REST_API_KEY=yyy-prod
BRAZE_BASE_URL=sdk.iad-01.braze.com

# .env.development
BRAZE_SDK_KEY=xxx-dev
BRAZE_REST_API_KEY=yyy-dev
BRAZE_BASE_URL=sdk.iad-01.braze.com

workspace 별도 (dev · prod 분리) + env var.

Pattern 3: Event Name 상수화

// types/braze-events.ts
export const BRAZE_EVENTS = {
  PRODUCT_VIEWED: "product_viewed",
  CART_ADDED: "cart_added",
  CHECKOUT_STARTED: "checkout_started",
  CHECKOUT_COMPLETED: "checkout_completed",  // Purchase 도 동시
  SIGNUP_COMPLETED: "signup_completed"
} as const;

// 사용
braze.logCustomEvent(BRAZE_EVENTS.PRODUCT_VIEWED, properties);

오타 = compile error.

Pattern 4: Server-side 안전망

// 결제 완료 webhook 에서 다시 추적
// → Client 추적 누락 (앱 끄거나 네트워크 끊긴 경우) 대비
async function onOrderCompleted(order) {
  await brazeApi.post("/users/track", {
    purchases: [...]
  });
}

Client + Server 동시 추적Client 가 빠른 UX, Server 가 정확성 보장.

Pattern 5: 배치 import (legacy 데이터)

async def bulk_import_users(users: list):
    """기존 사용자 10만 명을 Braze 로 import"""
    for batch in chunks(users, 75):
        payload = {
            "attributes": [
                {
                    "external_id": u.id,
                    "email": u.email,
                    "country": u.country,
                    "tier": u.tier,
                    "signup_year": u.signup_year
                }
                for u in batch
            ]
        }
        for attempt in range(3):
            try:
                resp = await braze_client.post("/users/track", json=payload)
                resp.raise_for_status()
                break
            except RateLimitError:
                await asyncio.sleep(2 ** attempt)  # exponential backoff
        await asyncio.sleep(0.1)  # rate limit 안전선

대량 import 의 표준 패턴.

시험 직전 한 번 더 — SDK 통합 + 첫 캠페인 함정 압축 노트

  • 통합 두 갈래 = SDK (Client · 자동) + REST API (Server · 명시)
  • 대부분 운영 = 둘 다 함께
  • Web SDK = npm install @braze/web-sdk + initialize(key, options) + changeUser + setEmail + logCustomEvent
  • iOS SDK = CocoaPods BrazeKit + Swift Configuration · APNs token 등록
  • Android SDK = Gradle braze-android-sdk-ui + Kotlin BrazeConfig + FCM token
  • baseUrl 지역별 endpoint = US-01~08 · EU-01~02 · AU-01 (workspace 별 확인)
  • 잘못된 baseUrl = 가장 흔한 초기 실수
  • External ID = 가장 중요한 호출 (changeUser)
  • 불변 + unique + 우리 시스템 표준 (DB user.id 또는 UUID)
  • email/phone 은 변경 가능 — 부적합
  • External ID < 987 bytes
  • Anonymous → 로그인 transition = changeUser 직후 자동 merge
  • User Alias = External ID 외 부가 식별자 (legacy ID · CRM · 외부 도구)
  • REST API Key vs SDK Key — Server only vs Client 안전
  • REST API Key 권한별 발급 (user track · messaging · analytics 분리)
  • REST API Key 유출 = 즉시 rotation
  • POST /users/track = 가장 중요한 endpoint
  • body = attributes + events + purchases (한 요청 batch)
  • Primary identifier = external_id · user_alias · braze_id
  • Secondary = email · phone (primary 있으면 attribute 처리)
  • Batch 한도 = 75 objects total / request (Standard)
  • Rate limit = 3,000 req / 3 sec · 시간당 250,000
  • 대량 import = batch 75 + exponential backoff
  • Attribute vs Event vs Purchase:
  • Attribute = 상태 (update 가능)
  • Event = 행동 (timestamp, append-only)
  • Purchase = 결제 (LTV · ARPU 자동 분석 위해 별도)
  • Subscription State = channel 별 동의 (email/push/SMS)
  • Console 5 단계 = Segment 만들기 → Campaign 시작 → Audience → Content (Liquid) → Schedule + Launch
  • Liquid default 필수{{ first_name | default: '회원님' }}
  • 함정 — baseUrl 잘못
  • 함정 — REST API Key 노출 (즉시 rotation)
  • 함정 — External ID 불일치 (user factory)
  • 함정 — Anonymous transition 시점 잘못
  • 함정 — Purchase 를 Custom Event 로 (LTV 분석 누락)
  • 함정 — Subscription state 무시 (법 위반)
  • 함정 — Liquid default 누락 ("안녕하세요, !")
  • 함정 — Rate limit hit (batch + backoff)
  • 함정 — External ID 너무 큼 (987 bytes 초과)
  • 패턴 — User Factory 함수
  • 패턴 — Environment 별 SDK Key (dev/prod workspace 분리)
  • 패턴 — Event Name TypeScript 상수
  • 패턴 — Server-side 안전망 (Client + Server 동시 추적)
  • 패턴 — 배치 import (75 chunk + exponential backoff)
  • 결과 — SDK + REST API + Console 한 흐름으로 첫 메시지 도달

공식 문서: Braze API Basics · POST /users/track 에서 원문을 확인할 수 있어요.

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

이전 글:

다음 글:

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

답글 남기기

error: Content is protected !!