@vircle/sdk-core-ts
v1.3.0
Published
Vircle SDK TypeScript Core
Maintainers
Readme
@vircle/sdk-core-ts
Vircle SDK의 핵심 엔진으로, 모든 플랫폼별 SDK 구현의 기반이 되는 TypeScript 코어 라이브러리입니다.
설치
pnpm add @vircle/sdk-core-ts빠른 시작
import { VircleCore } from '@vircle/sdk-core-ts';
const vircle = new VircleCore({
apiKey: 'your-api-key',
environment: 'production',
});
await vircle.initialize();
// 이벤트 추적
await vircle.track('button_clicked', {
buttonId: 'purchase',
value: 99.99,
});
// 사용자 식별
await vircle.identify('user-123', {
email: '[email protected]',
plan: 'premium',
});
// 크로스 도메인 어트리뷰션용 anonymousId 조회
const anonymousId = vircle.getAnonymousId();
// → "anon_1709500000_abc123xyz"플러그인과 함께 초기화
config.plugins 배열에 플러그인 인스턴스를 전달하면 initialize() 시 자동 등록됩니다.
import { VircleCore } from '@vircle/sdk-core-ts';
import { createCafe24Plugin } from '@vircle/plugin-cafe24';
const vircle = new VircleCore(
{
apiKey: 'your-api-key',
plugins: [createCafe24Plugin()],
},
{ enablePlugins: true },
);
await vircle.initialize();
// → Cafe24Plugin이 자동으로 등록 및 초기화됨설정 옵션
const vircle = new VircleCore(
{
apiKey: 'your-api-key',
environment: 'production', // 'development' | 'production' (기본값: 'production')
batch: {
size: 50, // 배치당 최대 이벤트 수
timeout: 5000, // 배치 대기 시간 (ms)
maxBytes: 500000, // 배치 최대 크기 (bytes)
},
queue: {
maxSize: 1000, // 최대 큐 크기
strategy: 'fifo', // 'fifo' | 'lifo' | 'priority'
},
retry: {
maxAttempts: 3, // 최대 재시도 횟수
initialDelay: 1000, // 초기 재시도 지연 (ms)
maxDelay: 30000, // 최대 재시도 지연 (ms)
multiplier: 2, // 지수 백오프 계수
},
autoCollect: {
device: true, // 기기 정보
app: true, // 앱 정보
page: true, // 페이지 정보
performance: false, // 성능 메트릭
},
plugins: [], // 자동 등록할 VirclePlugin 인스턴스 배열
},
{
enableValidation: true, // 이벤트/설정 검증
enableAutoContext: true, // 자동 컨텍스트 수집
enablePlugins: true, // 플러그인 시스템
enableEncryption: true, // 페이로드 암호화
storageType: 'indexedDB', // 'localStorage' | 'indexedDB' | 'memory'
debug: true, // 디버그 로그
},
);플러그인 시스템
플러그인 생성
import type { VirclePlugin, PluginContext } from '@vircle/sdk-core-ts';
const myPlugin: VirclePlugin = {
name: 'my-plugin',
version: '1.0.0',
async initialize(config, context: PluginContext) {
// context.track()으로 SDK 파이프라인을 통해 이벤트 전송
context.track('plugin_loaded', { pluginName: 'my-plugin' });
},
hooks: {
beforeEventSend: async (event) => {
event.properties = { ...event.properties, enriched: true };
return event;
},
afterEventSend: async (event) => {
console.log('Event sent:', event.name);
},
},
async cleanup() {
console.log('Plugin cleanup');
},
};플러그인 등록 방법
// 방법 1: config.plugins로 자동 등록 (권장)
const vircle = new VircleCore({
apiKey: 'your-api-key',
plugins: [myPlugin],
}, { enablePlugins: true });
// 방법 2: 초기화 후 수동 등록
await vircle.registerPlugin(myPlugin);PluginContext API
플러그인의 initialize(config, context) 에서 전달받는 PluginContext가 제공하는 메서드:
| 메서드 | 설명 |
|--------|------|
| track(eventName, properties?) | VircleCore.track() 파이프라인을 통해 이벤트 전송 |
| identify(userId, traits?) | VircleCore.identify() 파이프라인을 통해 사용자 식별 |
| emit(event, data?) | 플러그인 간 pub/sub 이벤트 발행 |
| on(event, handler) / off(event, handler) | 이벤트 리스너 등록/해제 |
| getConfig() | SDK 설정 조회 |
| getPlugin(name) | 다른 플러그인 인스턴스 조회 |
| logger | debug/info/warn/error 로거 |
| storage | get/set/remove 키-값 저장소 |
context.track()은VircleCore.track()과 동일한 파이프라인(검증 → 훅 → 배치 → 전송)을 거칩니다.context.emit()은 플러그인 간 내부 통신용 pub/sub으로 서버 전송과 무관합니다.
사용 가능한 훅
| 훅 | 설명 |
|----|------|
| beforeEventSend | 전송 전 이벤트 수정 (이벤트 반환) |
| afterEventSend | 전송 성공 후 처리 |
| onError | 에러 처리 |
| onConfigChange | 설정 변경 반응 |
| onUserIdentify | 사용자 식별 반응 |
| onSessionStart / onSessionEnd | 세션 시작/종료 |
타입 안전 이벤트
interface PurchaseEvent {
productId: string;
price: number;
currency: string;
}
await vircle.track<PurchaseEvent>('purchase', {
productId: 'SKU-123',
price: 99.99,
currency: 'USD',
});이벤트 빌더
await vircle
.createEvent('purchase')
.properties({ productId: 'SKU-123', price: 99.99 })
.userId('user-123')
.context({ campaign: { source: 'google' } })
.track();전송 제어
await vircle.flush(); // 대기 중인 이벤트 즉시 전송
const status = vircle.getStatus();
// { isInitialized, sessionId, userId, pluginCount, queueSize }
const anonId = vircle.getAnonymousId(); // 크로스 도메인 어트리뷰션용
await vircle.reset(); // SDK 상태 초기화
await vircle.cleanup(); // 모든 리소스 정리전역 속성
모든 track()/trackBatch() 호출 시 properties에 자동 병합됩니다.
// 설정 — 이후 모든 이벤트에 partnerIdx가 포함됨
vircle.setGlobalProperties({ partnerIdx: 123 });
// track() properties가 globalProperties보다 우선
await vircle.track('click', { partnerIdx: 456 }); // → partnerIdx: 456
// 초기화
vircle.clearGlobalProperties();컨텍스트 관리
vircle.setContext({
experiment: { id: 'exp-123', variant: 'A' },
});
vircle.clearContext();세션 관리
SDK는 세션을 스토리지에 영속화하여 MPA 페이지 전환 간 세션을 유지합니다.
- 30분 비활동 타임아웃: 마지막 활동으로부터 30분 경과 시 새 세션 생성
- 스토리지 기반 복원: 페이지 로드 시 스토리지에서 세션 복원 (MPA 지원)
- Throttled 저장:
track()호출 시 10초 간격으로 활동 시간 갱신 (스토리지 쓰기 최적화)
페이로드 암호화
하이브리드 암호화(AES-256-GCM + RSA-OAEP)로 이벤트 페이로드를 보호합니다.
const vircle = new VircleCore(
{ apiKey: 'your-api-key' },
{ enableEncryption: true },
);- CDN에서 공개키를 자동으로 가져와 암호화
- 별도 코드 변경 없이 모든 이벤트/identify 데이터 자동 암호화
- 암호화 실패 시 전송 중단 (안전한 실패)
환경별 엔드포인트
| 환경 | Events API | Config CDN |
|------|-----------|------------|
| production (기본값) | https://integration.vircle.co.kr/v1/track/events | https://static.vircle.co.kr/sdk/v1/config |
| development | https://dev-integration.vircle.co.kr/v1/track/events | https://dstatic.vircle.co.kr/sdk/v1/config |
에러 처리
import { VircleError, ErrorCode } from '@vircle/sdk-core-ts';
try {
await vircle.track('event');
} catch (error) {
if (error instanceof VircleError) {
console.error(error.code, error.message);
if (error.code === ErrorCode.NETWORK_ERROR) {
// 네트워크 에러 처리
}
}
}아키텍처
VircleCore (중앙 오케스트레이터)
├── EventService — 이벤트 생성, 검증, 큐잉
├── TransportService — 배치 전송, 재시도, 서킷 브레이커
├── StorageService — 다중 어댑터 (Memory, LocalStorage, IndexedDB)
├── PluginService — 플러그인 라이프사이클, 훅 실행, PluginContext 제공
├── RemoteConfigService — CDN 기반 동적 설정
└── ContextService — 디바이스/앱/페이지 컨텍스트 자동 수집데이터 흐름
track() → EventService (검증/보강) → PluginHooks (beforeEventSend)
→ TransportService (배치/암호화) → HTTP POST플랫폼 어댑터 패턴
플랫폼별 SDK(Web, React Native)는 VircleCore를 상속하고 어댑터를 주입합니다:
| 어댑터 인터페이스 | Web 구현 | React Native 구현 |
|------------------|---------|-------------------|
| StorageAdapter | LocalStorage, IndexedDB | AsyncStorage |
| ExtendedCryptoAdapter | Web Crypto API | react-native-quick-crypto |
| ContextAdapter | WebContextCollector | RNContextAdapter |
