이벤트 구독
배너, Content Cards, 기능 플래그에 대한 Braze SDK 이벤트 구독의 작동 방식을 알아봅니다. 이 문서에서는 각 이벤트가 발생하는 시점과 통합에서 수행해야 할 작업을 설명합니다.
사전 요구 사항
이벤트 구독을 사용하기 위해 필요한 최소 SDK 버전은 다음과 같습니다.
이벤트 구독 소개
각 채널에는 이벤트 구독 메서드가 있습니다. 콜백을 하나 등록하면, SDK는 해당 채널에서 캐시 재생, 완료된 새로고침, 분석 이벤트, 오류 등 무언가 발생할 때마다 콜백을 호출합니다. 각 이벤트는 수신한 이벤트의 종류를 알려줍니다.
이벤트 구독 메서드는 기존의 업데이트 구독 메서드를 대체합니다. 기존 메서드는 현재 데이터만 전달합니다. 이벤트 메서드는 데이터가 변경된 이유, 분석 이벤트가 기록 및 전송된 시점, 요청이 실패한 시점도 함께 알려줍니다.
| 채널 | 이벤트 구독 메서드 | 대체 대상 | 가이드 |
|---|---|---|---|
| 배너 | subscribeToBannersEvents |
subscribeToBannersUpdates |
배너 배치 관리 |
| Content Cards | subscribeToContentCardsEvents |
subscribeToContentCardsUpdates |
Content Cards 만들기 |
| 기능 플래그 | subscribeToFeatureFlagsEvents |
subscribeToFeatureFlagsUpdates |
기능 플래그 만들기 |

subscribeToBannersUpdates, subscribeToContentCardsUpdates, subscribeToFeatureFlagsUpdates는 더 이상 사용되지 않으며 향후 주요 버전에서 제거됩니다. 대신 해당하는 이벤트 구독 메서드를 사용하세요.
| 채널 | 이벤트 구독 메서드 | 대체 대상 | 가이드 |
|---|---|---|---|
| 배너 | braze.banners.subscribeToEvents(_:) |
subscribeToUpdates(_:) |
배너 배치 관리 |
| Content Cards | braze.contentCards.subscribeToEvents(_:) |
subscribeToUpdates(_:) |
Content Cards 만들기 |
| 기능 플래그 | braze.featureFlags.subscribeToEvents(_:) |
subscribeToUpdates(_:) |
기능 플래그 만들기 |
전체 API 참조는 BrazeKit 설명서를 참고하세요.
각 채널에는 동일한 이벤트를 AsyncStream으로 전달하는 eventsStream 속성도 있습니다. Objective-C 앱은 동일한 채널 객체에서 subscribeToEvents: 메서드를 사용합니다.

기존의 subscribeToUpdates(_:) 메서드와 bannersStream 같은 채널별 업데이트 스트림은 더 이상 사용되지 않습니다. 대신 subscribeToEvents(_:) 또는 eventsStream을 사용하세요.
| 채널 | 이벤트 구독 메서드 | 이벤트 클래스 | 대체 대상 | 가이드 |
|---|---|---|---|---|
| 배너 | subscribeToBannersEvents |
BannersEvent |
subscribeToBannersUpdates |
배너 배치 관리 |
| Content Cards | subscribeToContentCardsEvents |
ContentCardsEvent |
subscribeToContentCardsUpdates |
Content Cards 만들기 |
| 기능 플래그 | subscribeToFeatureFlagsEvents |
FeatureFlagsEvent |
subscribeToFeatureFlagsUpdates |
기능 플래그 만들기 |
전체 API 참조는 Braze Android SDK KDoc을 참고하세요.

subscribeToBannersUpdates, subscribeToContentCardsUpdates, subscribeToFeatureFlagsUpdates, subscribeToBannersErrors는 더 이상 사용되지 않습니다. 대신 해당하는 이벤트 구독 메서드를 사용하세요.
플랫폼별 이름
이 문서에서는 이벤트 유형, 업데이트 사유, 재시도 상태, 분석 액션, 오류 사유에 대해 웹 이름을 사용합니다. Swift와 Android는 동일한 개념을 각 플랫폼의 규칙에 따른 이름으로 사용합니다.
| Web | Swift | Android |
|---|---|---|
CACHE_REPLAY |
cacheReplay |
CacheReplay |
CACHE_LOAD |
cacheLoad |
CacheLoad |
DATA_UPDATED |
dataUpdated |
DataUpdated |
IMPRESSION |
impressionEvent |
ImpressionEvent |
CLICK |
clickEvent |
ClickEvent |
DISMISS |
dismissEvent |
DismissEvent |
ERROR |
error |
ErrorEvent |
AUTO_SERVER_REFRESH |
autoServerRefresh |
AUTO_SERVER_REFRESH |
SDK_WILL_RETRY |
sdkWillRetry |
SDK_WILL_RETRY |
ENQUEUED |
enqueued |
ENQUEUED |
SERVER_ERROR |
.common(.serverError) |
Common(ErrorReason.ServerError) |
FEATURE_DISABLED |
.featureDisabled |
FeatureDisabled |
나머지 업데이트 사유, 재시도 상태, 분석 액션, 오류 사유도 같은 패턴을 따릅니다. Swift에서 업데이트 사유 유형은 Braze.ChannelUpdateReason입니다. Android에서는 각 채널에 BannersUpdateReason 같은 고유한 업데이트 사유 유형이 있습니다.
이벤트 전달 방식
SDK는 다음 순서로 이벤트를 전달합니다.
- 구독 시: SDK가 현재 캐시가 포함된
CACHE_REPLAY이벤트로 콜백을 즉시 호출합니다. 채널이 비활성화된 경우FEATURE_DISABLED사유가 포함된ERROR이벤트를 전송합니다. 두 경우 모두 구독은 활성 상태를 유지합니다. - 캐시 변경 시: 서버 새로고침 없이 캐시가 변경된 경우 SDK가
CACHE_LOAD이벤트를, 새로고침이 완료되었거나 로컬에서 데이터를 변경한 경우DATA_UPDATED이벤트를 전송합니다. - 사용자 또는 SDK가 분석을 기록할 때: SDK가
ENQUEUED액션과 함께IMPRESSION,CLICK또는DISMISS이벤트를 전송하고, Braze가 이를 수락한 후FLUSHED액션으로 다시 전송합니다. - 실패 발생 시: SDK가
ERROR이벤트를 전송합니다.
콜백은 이벤트를 유일한 인수로 수신합니다. 이벤트 유형에 대한 switch 문으로 각 종류의 이벤트를 처리하세요. 웹에서는 콜백이 throw한 오류를 SDK가 로그에 기록하면서도 다른 구독자에게는 이벤트를 계속 전달합니다.
import * as braze from "@braze/web-sdk";
// Register the subscription
const subscriptionId = braze.subscribeToBannersEvents((event) => {
switch (event.type) {
case braze.ChannelEventType.CACHE_REPLAY:
// Sent once, right away, with the cached data
break;
case braze.ChannelEventType.DATA_UPDATED:
// A refresh finished or the data changed locally
break;
case braze.ChannelEventType.ERROR:
// A request or analytics operation failed
break;
}
});
// Remove the subscription when you no longer need it
braze.removeSubscription(subscriptionId);

SDK 초기화 후에 이벤트 구독 메서드를 호출하세요. 첫 번째 세션의 이벤트를 콜백으로 수신하려면 openSession() 전에 호출하세요. SDK가 비활성화된 경우 메서드는 undefined을 반환합니다.
// Register the subscription and keep a strong reference to it
let cancellable = AppDelegate.braze?.banners.subscribeToEvents { event in
switch event {
case .cacheReplay(let cacheSnapshot):
// Sent once, right away, with the cached data
break
case .dataUpdated(let cacheSnapshot, let reason):
// A refresh finished or the data changed locally
break
case .error(let reason, let retryState):
// A request or analytics operation failed
break
default:
break
}
}
// Remove the subscription when you no longer need it
cancellable?.cancel()

반환된 cancellable에 대한 강한 참조를 유지하세요. cancellable이 해제되면 SDK가 구독을 취소합니다. SDK는 메인 스레드에서 핸들러를 호출합니다.
// Register the subscription
val subscriber = IEventSubscriber<BannersEvent> { event ->
when (event) {
is BannersEvent.CacheReplay -> {
// Sent once, right away, with the cached data
}
is BannersEvent.DataUpdated -> {
// A refresh finished or the data changed locally
}
is BannersEvent.ErrorEvent -> {
// A request or analytics operation failed
}
else -> Unit
}
}
Braze.getInstance(context).subscribeToBannersEvents(subscriber)
// Remove the subscription when you no longer need it
Braze.getInstance(context).removeSingleSubscription(subscriber, BannersEvent::class.java)

SDK는 백그라운드 스레드에서 구독자를 호출합니다. UI를 업데이트하기 전에 메인 스레드로 전환하세요.
캐시 스냅샷
CACHE_REPLAY, CACHE_LOAD, DATA_UPDATED 이벤트에는 SDK가 현재 사용자를 위해 캐시한 데이터가 포함된 cacheSnapshot 속성정보가 있습니다.
| 채널 | cacheSnapshot의 데이터 |
|---|---|
| 배너 | banners: 각 배치 ID를 해당 캐시된 배너에 매핑한 맵. 배너가 없는 배치는 맵에 포함되지 않습니다. |
| Content Cards | 웹: contentCards, ContentCards 객체. contentCards.cards를 사용하여 카드 목록을 가져옵니다. Swift 및 Android: cards, 카드 목록. |
| 기능 플래그 | featureFlags: 기능 플래그 목록. |
모든 스냅샷에는 현재 사용자의 마지막 성공적인 동기화 시각을 Unix 타임스탬프(초 단위)로 나타낸 lastSyncAt도 포함됩니다. 동기화가 성공한 적이 없으면 값은 0이고, 채널이 비활성화된 경우 null(Swift에서는 nil)입니다.
업데이트 구독에서 마이그레이션
업데이트 구독 메서드는 여전히 작동하지만 더 이상 사용되지 않습니다. 각 구독을 마이그레이션하려면 사전 요구 사항을 충족한 후 다음을 수행합니다.
- 더 이상 사용되지 않는 메서드를 해당 채널의 이벤트 구독 메서드로 교체합니다. 이벤트 구독 소개의 표에 각 쌍이 나열되어 있습니다.
- 콜백을 업데이트합니다. 이전 콜백은 현재 데이터만 수신했습니다. 새 콜백은 이벤트를 수신하므로 이벤트 유형을 확인하세요.
CACHE_REPLAY,CACHE_LOAD,DATA_UPDATED이벤트의 경우cacheSnapshot에서 데이터를 읽고 다시 렌더링합니다. - (선택 사항)
ERROR이벤트를 처리하여 새로고침이나 분석 작업이 실패한 시점을 파악합니다. Android에서는subscribeToBannersErrors를 대체합니다. 자세한 내용은 오류 사유를 참고하세요. - 구독을 제거합니다. Android에서는 레거시
…UpdatedEvent클래스가 아닌 새 이벤트 클래스(BannersEvent,ContentCardsEvent또는FeatureFlagsEvent)를removeSingleSubscription에 전달합니다.
변경 전후 코드는 이벤트 구독 소개의 표에 있는 각 채널 가이드를 참고하세요.
이벤트 유형
모든 이벤트는 이 표에 있는 이벤트 유형 중 하나입니다. 웹에서는 이벤트에 ChannelEventType 값 중 하나를 가진 type 속성정보가 있습니다. Swift와 Android에서는 각 이벤트 유형이 자체 case 또는 클래스입니다. 모든 채널이 모든 이벤트 유형을 전송하는 것은 아닙니다.
| 이벤트 유형 | 전송 주체 | 발생 시점 | 수행할 작업 |
|---|---|---|---|
CACHE_REPLAY |
배너, Content Cards, 기능 플래그 | 구독할 때마다 한 번, 즉시 전송됩니다. 현재 캐시가 포함된 cacheSnapshot이 있습니다. |
네트워크를 기다리지 않고 UI에 콘텐츠를 표시하도록 캐시된 데이터를 렌더링합니다. |
CACHE_LOAD |
배너, Content Cards, 기능 플래그 | 서버 새로고침 없이 캐시가 변경된 경우. 사용자 변경, SDK 데이터 삭제, 채널 비활성화 시 발생합니다. 웹에서는 서비스 워커를 통해 카드가 도착할 때 Content Cards도 이를 전송합니다. Swift와 Android에서는 네트워크 동기화 전에 SDK가 로컬 저장소에서 캐시를 로드할 때도 발생합니다. 새 캐시가 포함된 cacheSnapshot이 있습니다. |
스냅샷에서 다시 렌더링합니다. 사용자 변경 또는 채널 비활성화 후에는 스냅샷이 비어 있을 수 있으므로 이전 사용자의 콘텐츠를 지웁니다. |
DATA_UPDATED |
배너, Content Cards, 기능 플래그 | 캐시가 변경된 경우. SDK는 변경 사항이 없더라도 완료된 모든 새로고침과 닫기 같은 로컬 변경에 대해 이를 전송합니다. cacheSnapshot과 reason이 있습니다. |
스냅샷에서 다시 렌더링합니다. reason을 확인하여 변경이 새로고침에서 비롯된 것인지 자체 작업에서 비롯된 것인지 결정합니다. |
IMPRESSION |
배너, Content Cards, 기능 플래그 | 노출이 기록된 경우. action과 기록된 항목(banner, card 또는 flag)이 있습니다. |
선택 사항. 자체 분석에 노출을 미러링하는 데 사용합니다. |
CLICK |
배너, Content Cards | 클릭이 기록된 경우. action과 클릭된 항목(banner 또는 card)이 있습니다. 배너 클릭의 경우 ID가 있는 버튼에서 클릭이 발생했으면 버튼 ID도 포함됩니다. |
선택 사항. 자체 분석에 클릭을 미러링하는 데 사용합니다. |
DISMISS |
배너, Content Cards | 닫기가 기록된 경우. action과 닫은 항목(banner 또는 card)이 있습니다. |
선택 사항. DISMISS는 분석 이벤트이므로 닫기 이후 발생하는 DATA_UPDATED 이벤트에서 UI를 업데이트하세요. |
ERROR |
배너, Content Cards, 기능 플래그 | 요청 또는 작업이 실패한 경우. reason과 retryState가 있습니다. 웹에서는 rateLimitedUntil이 포함되기도 합니다. Swift와 Android에서는 사용량 제한 시간이 RATE_LIMITED 사유의 일부입니다. |
retryState를 확인하여 재시도 여부를 결정하고, reason을 확인하여 원인을 파악합니다. |
업데이트 사유
DATA_UPDATED 이벤트에는 ChannelUpdateReason 값 중 하나를 가진 reason이 포함됩니다.
| 값 | 의미 | 수행할 작업 |
|---|---|---|
AUTO_SERVER_REFRESH |
SDK가 시작한 새로고침(예: 새 세션 시 새로고침과 재시도 포함)이 완료되었습니다. | 스냅샷에서 다시 렌더링합니다. |
MANUAL_SERVER_REFRESH |
사용자가 요청한 새로고침(재시도 포함)이 완료되었습니다. 예를 들어 웹 및 Android의 requestBannersRefresh(), requestContentCardsRefresh(), refreshFeatureFlags() 또는 Swift의 requestRefresh()가 있습니다. |
스냅샷에서 다시 렌더링합니다. 새로고침 요청 시 표시한 로딩 인디케이터를 숨기는 데 사용합니다. |
CLIENT_ACTION |
서버 응답 대신 배너 또는 Content Cards 닫기 같은 로컬 작업으로 캐시가 변경되었습니다. | 로딩 또는 오류 상태를 표시하지 않고 스냅샷에서 다시 렌더링합니다. 기능 플래그는 현재 이 사유를 전송하지 않지만, 향후 전송할 경우를 대비하여 처리하세요. |
재시도 상태
ERROR 이벤트에는 RetryState 값 중 하나를 가진 retryState가 포함됩니다. SDK가 실패한 작업을 재시도할지 여부와 수행해야 할 작업을 알려줍니다.
| 값 | 의미 | 수행할 작업 |
|---|---|---|
SDK_WILL_RETRY |
SDK가 자동으로 재시도하고 있거나, 사용량 제한이 해제되기를 기다린 후 재시도합니다. | 캐시된 콘텐츠를 계속 표시합니다. SDK가 재시도 완료 시 DATA_UPDATED 또는 다른 ERROR 이벤트를 전송하므로 추가 새로고침을 요청하지 마세요. |
INTEGRATOR_MAY_RETRY |
SDK가 재시도를 중단했습니다. | 캐시된 콘텐츠를 계속 표시합니다. 지연 후 새로고침 메서드를 다시 호출할 수 있습니다. 이벤트에 rateLimitedUntil이 포함된 경우 해당 시간까지 기다리세요. |
DO_NOT_RETRY |
이 작업에 대한 실패가 최종적입니다. 재시도해도 도움이 되지 않습니다. | 재시도하지 마세요. 대신 API 키나 워크스페이스 설정 같은 원인을 수정하세요. 사유가 FEATURE_DISABLED인 경우 해당 채널의 콘텐츠 표시를 중단합니다. |

클라이언트 오류(429를 제외한 HTTP 4xx 응답) 후에는 새로고침이 자동으로 재시도되지 않습니다. SDK는 이러한 오류를 DO_NOT_RETRY 재시도 상태로 보고합니다. HTTP 429, HTTP 5xx, 네트워크 장애에 대해서는 여전히 재시도합니다.
분석 액션
IMPRESSION, CLICK, DISMISS 이벤트에는 AnalyticsAction 값 중 하나를 가진 action이 포함됩니다. 각 분석 이벤트는 두 번 전송됩니다. 먼저 ENQUEUED로, 그다음 FLUSHED로 전송됩니다.
| 값 | 의미 | 수행할 작업 |
|---|---|---|
ENQUEUED |
SDK가 분석 이벤트를 로컬에 저장했습니다. Braze가 아직 수신하지 않았습니다. | UI나 자체 로깅을 즉시 업데이트하는 데 사용합니다. |
FLUSHED |
SDK가 성공적인 네트워크 응답을 통해 분석 이벤트를 Braze로 플러시했습니다. | 이벤트가 플러시되었음을 확인하는 데 사용합니다. |
오류 사유
ERROR 이벤트에는 ChannelErrorReason 값 중 하나를 가진 reason이 포함됩니다. 모든 사유는 모든 채널에 적용될 수 있습니다.
| 값 | 의미 | 수행할 작업 |
|---|---|---|
SERVER_ERROR |
Braze가 서버 측 실패(예: HTTP 5xx 응답 또는 사용 가능한 Retry-After 헤더가 없는 HTTP 429 응답)를 반환했거나, 요청이 Braze에 도달하지 못했습니다. |
retryState를 따르세요. SDK가 먼저 재시도한 후 INTEGRATOR_MAY_RETRY를 보고합니다. 캐시된 콘텐츠를 계속 표시합니다. |
CLIENT_ERROR |
Braze가 요청을 거부했습니다(예: 429를 제외한 HTTP 4xx 응답 또는 SDK 인증 오류). 웹에서 기능 플래그의 경우 SDK가 노출을 로컬에 저장하지 못한 경우를 의미할 수도 있습니다. | retryState를 따르세요. HTTP 4xx 응답은 즉시 DO_NOT_RETRY입니다. SDK 인증 오류의 경우 SDK가 먼저 재시도한 후 DO_NOT_RETRY를 보고합니다. API 키, SDK 엔드포인트, SDK 인증 설정을 확인하세요. |
RATE_LIMITED |
요청이 사용량 제한에 걸렸습니다. 이벤트에는 다른 시도가 성공할 수 있는 가장 이른 시간인 rateLimitedUntil 날짜가 포함됩니다. |
retryState가 SDK_WILL_RETRY이면 기다리세요. INTEGRATOR_MAY_RETRY이면 rateLimitedUntil까지 기다린 후 다시 새로고침하세요. 이전 요청이 다시 실패할 수 있기 때문입니다. 자세한 내용은 사용량 제한을 참고하세요. |
SDK_DISABLED |
SDK가 로컬에서 비활성화되어 네트워크 요청을 하지 않습니다. | 최종 상태로 처리하고 재시도하지 마세요. |
INVALID_SERVER_DATA |
Braze가 SDK에서 해석할 수 없는 데이터를 반환했습니다. | 재시도하지 마세요. retryState는 DO_NOT_RETRY입니다. 캐시된 콘텐츠를 계속 표시하고, 문제가 지속되면 Braze 지원팀에 문의하세요. |
FEATURE_DISABLED |
이 워크스페이스에서 채널이 비활성화되어 있습니다. SDK는 Braze에서 첫 번째 구성을 수신할 때까지 채널을 비활성화 상태로 보고합니다. | 해당 채널의 UI를 숨기세요. 이는 빈 콘텐츠 목록과 다릅니다. 구독을 유지하세요. Braze가 채널을 활성화하면 SDK가 새로고침하고 DATA_UPDATED 이벤트를 전송합니다. |

채널이 워크스페이스에서 활성화되어 있더라도, SDK가 Braze에서 첫 번째 구성을 수신하기 전에 구독하면 FEATURE_DISABLED 오류를 수신할 수 있습니다. 구독을 활성 상태로 유지하고 이어서 발생하는 DATA_UPDATED 이벤트를 처리하세요.