커스텀 액션
TypeScript 구별 유니온을 사용한 타입 안전한 액션 정의입니다.
액션 타입 정의
typescript
type MyAction =
| { type: 'paywall'; data: PaywallData }
| { type: 'show_modal'; nudgeId: string }
| { type: 'notification'; message: string }
| { type: 'credit_reward'; points: number };Coordinator 설정
typescript
const coordinator = startCoordinator<MyAction>({
nudgeRules: [
{
nudgeId: 'test',
when: (t) => t.type === 'funnel_completed',
buildAction: (): MyAction => ({
type: 'paywall',
data: { entryType: 'test' },
}),
},
],
});액션 러너 구현
typescript
const runner = {
run: async (action: MyAction) => {
switch (action.type) {
case 'paywall':
showPaywall(action.data);
break;
case 'show_modal':
showModal(action.nudgeId);
break;
case 'notification':
sendNotification(action.message);
break;
case 'credit_reward':
grantPoints(action.points);
break;
}
},
};프로덕션 예제
typescript
type PaywallData = { entryType: string };
type NudgeAction = { type: 'paywall'; data: PaywallData } | { type: 'show_modal'; nudgeId: string };
const paywallRule: NudgeRule<'free' | 'pro', NudgeAction> = {
nudgeId: 'paywall',
when: (t) => t.type === 'funnel_completed',
cooldownDuration: '3d',
maxPerWindow: 3,
windowDuration: '3d',
personalTiers: ['free'],
buildAction: () => ({
type: 'paywall',
data: { entryType: 'exiting_thread' },
}),
};
const coordinator = startCoordinator<'free' | 'pro', NudgeAction>({
nudgeRules: [paywallRule],
runner: {
run: async (action) => {
if (action.type === 'paywall') {
showPaywall(action.data);
}
},
},
});타입 안전성
typescript
// 유효함
const rule: NudgeRule<any, MyAction> = {
nudgeId: 'test',
when: () => true,
buildAction: () => ({
type: 'paywall',
data: { entryType: 'test' },
}),
};
// TypeScript 에러: 유효하지 않은 액션 타입
const badRule: NudgeRule<any, MyAction> = {
nudgeId: 'test',
when: () => true,
buildAction: () => ({
type: 'invalid_type', // 에러!
data: {},
}),
};비동기 액션 처리
typescript
const runner = {
run: async (action: MyAction) => {
try {
switch (action.type) {
case 'credit_reward':
await database.addPoints(userId, action.points);
break;
case 'notification':
await emailService.send(userId, action.message).catch((err) => {
console.error('Failed:', err);
});
break;
}
} catch (error) {
console.error('Action runner error:', error);
}
},
};다음 단계
- 예제 - 통합 예제
- Coordinator API - API 레퍼런스