@vircle/sdk-core-ts
v1.1.0
Published
Vircle SDK TypeScript Core
Maintainers
Readme
@vircle/sdk-core-ts
Vircle SDK의 핵심 엔진으로, 모든 플랫폼별 SDK 구현의 기반이 되는 TypeScript 코어 라이브러리입니다. 이벤트 추적, 사용자 관리, 플러그인 시스템 등 SDK의 모든 핵심 기능을 제공합니다.
📦 설치
npm install @vircle/sdk-core-ts
# or
yarn add @vircle/sdk-core-ts
# or
pnpm add @vircle/sdk-core-ts🚀 주요 기능
핵심 기능
- 타입 안전 이벤트 추적: 제네릭 타입을 지원하는 완전한 TypeScript 지원
- 플러그인 아키텍처: 라이프사이클 훅을 갖춘 확장 가능한 플러그인 시스템
- 자동 컨텍스트 수집: 디바이스, 앱, 사용자 컨텍스트 자동 수집
- 사용자 식별: identify 이벤트를 통한 사용자 정보 서버 전송
성능 및 안정성
- 스마트 전송: 우선순위 기반 배치 처리, 지수 백오프 재시도
- 서킷 브레이커: 장애 격리 및 자동 복구
- 성능 최적화: requestIdleCallback을 활용한 백그라운드 처리
- 컨텍스트 캐싱: 반복적인 계산 방지
데이터 관리
- 유연한 스토리지: 다양한 스토리지 어댑터 지원 (Memory, LocalStorage, IndexedDB)
- 페이로드 암호화: 민감한 데이터를 위한 하이브리드 암호화 (AES-256-GCM + RSA-OAEP)
- 데이터 검증: 이벤트 및 구성 데이터의 포괄적인 검증
운영 지원
- 원격 설정: CDN을 통한 동적 설정 관리
- 환경별 엔드포인트: development/production 자동 전환
- 상세한 에러 시스템: 표준화된 에러 코드와 디버깅 정보
📖 빠른 시작
기본 사용법
import { VircleCore } from '@vircle/sdk-core-ts';
// SDK 초기화 (엔드포인트는 환경에 따라 자동 설정됨)
const vircle = new VircleCore({
apiKey: 'your-api-key',
environment: 'production', // 선택사항: 'development' | 'production'
});
// 사용 전 초기화
await vircle.initialize();
// 이벤트 추적
await vircle.track('button_clicked', {
buttonId: 'purchase',
value: 99.99,
});
// 사용자 식별
await vircle.identify('user-123', {
email: '[email protected]',
plan: 'premium',
});고급 설정
const vircle = new VircleCore(
{
apiKey: 'your-api-key',
environment: 'production', // 'development' | 'production' (기본값: 'production')
// 배치 설정 - 이벤트 전송 최적화
batch: {
size: 50, // 배치당 최대 이벤트 수
timeout: 5000, // 배치 대기 시간 (ms)
flushInterval: 10000, // 자동 플러시 간격 (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, // 기기 정보 (OS, 브라우저 등)
app: true, // 앱 정보 (버전, 빌드 등)
page: true, // 페이지 정보 (URL, 제목 등)
performance: true, // 성능 메트릭 (Core Web Vitals)
},
},
{
// 코어 옵션
enableValidation: true, // 이벤트/설정 검증 활성화
enableAutoContext: true, // 자동 컨텍스트 수집
enablePlugins: true, // 플러그인 시스템 활성화
enableEncryption: true, // 페이로드 암호화 활성화
storageType: 'indexedDB', // 'localStorage' | 'indexedDB' | 'memory'
debug: true, // 디버그 로그 출력
},
);🔌 플러그인 시스템
플러그인 생성
import { VirclePlugin, PluginContext } from '@vircle/sdk-core-ts';
const myPlugin: VirclePlugin = {
name: 'my-plugin',
version: '1.0.0',
// 플러그인 초기화
async initialize(config, context) {
console.log('Plugin initialized with config:', config);
},
// 훅 정의
hooks: {
beforeEventSend: async (event, context) => {
// 전송 전 이벤트 수정
event.properties = {
...event.properties,
pluginProcessed: true,
};
return event;
},
afterEventSend: async (event, context) => {
console.log('Event sent:', event.name);
},
onEventError: async ({ event, error }, context) => {
console.error('Event error:', error);
},
},
// 정리
async cleanup(context) {
console.log('Plugin cleanup');
},
};
// 플러그인 등록
await vircle.registerPlugin(myPlugin);사용 가능한 훅
beforeEventSend: 전송 전 이벤트 수정afterEventSend: 성공적인 이벤트 전송에 반응onEventError: 이벤트 에러 처리onConfigChange: 구성 변경에 반응onUserIdentify: 사용자 식별에 반응onSessionStart: 새 세션 시작onSessionEnd: 세션 종료
📊 이벤트 빌더 패턴
// 플루언트 빌더 패턴 사용
await vircle
.createEvent('purchase')
.properties({
productId: 'SKU-123',
price: 99.99,
currency: 'USD',
})
.userId('user-123')
.context({
campaign: {
source: 'google',
medium: 'cpc',
},
})
.track();🎯 타입 안전 이벤트
// 이벤트 타입 정의
interface PurchaseEvent {
productId: string;
price: number;
currency: string;
quantity?: number;
}
// 완전한 타입 안전성으로 사용
await vircle.track<PurchaseEvent>('purchase', {
productId: 'SKU-123',
price: 99.99,
currency: 'USD',
// TypeScript가 스키마를 강제합니다!
});💾 스토리지 옵션
// 다양한 스토리지 백엔드 사용
const vircle = new VircleCore(config, {
storageType: 'localStorage', // or 'indexedDB', 'memory'
});
// 직접 스토리지 접근
const storage = new StorageService({
type: 'indexedDB',
maxSize: 10 * 1024 * 1024, // 10MB
});
await storage.set('key', { data: 'value' });
const value = await storage.get('key');🛡️ 에러 처리
import { VircleError, ErrorCode } from '@vircle/sdk-core-ts';
try {
await vircle.track('event');
} catch (error) {
if (error instanceof VircleError) {
console.error('Vircle Error:', error.code, error.message);
// 특정 에러 코드 확인
if (error.code === ErrorCode.NETWORK_ERROR) {
// 네트워크 에러 처리
}
// 재시도 가능 여부 확인
if (error.retryable) {
// 재시도 로직
}
}
}🔍 검증
import { EventValidator, ConfigValidator } from '@vircle/sdk-core-ts';
// 이벤트 검증
const eventValidator = new EventValidator({
maxEventNameLength: 50,
maxPropertyValueLength: 1000,
enableSecurityChecks: true,
});
const result = eventValidator.validate(event);
if (!result.isValid) {
console.error('Validation errors:', result.errors);
}
// 구성 검증
const configValidator = new ConfigValidator();
const configResult = configValidator.validate(config);📡 전송 제어
// 대기 중인 이벤트 플러시
await vircle.flush();
// SDK 상태 가져오기
const status = vircle.getStatus();
console.log('Queue size:', status.queueSize);
console.log('Is initialized:', status.isInitialized);
// SDK 상태 리셋
await vircle.reset();
// 리소스 정리
await vircle.cleanup();🔐 페이로드 암호화
민감한 데이터 보호를 위한 하이브리드 암호화를 제공합니다.
암호화 활성화
const vircle = new VircleCore({ apiKey: 'your-api-key' }, { enableEncryption: true });
// 모든 이벤트와 identify 데이터가 자동으로 암호화됨
await vircle.identify('user-123', {
email: '[email protected]', // 암호화되어 전송
creditCard: '**** 1234', // 암호화되어 전송
});암호화 특징
- 하이브리드 암호화: AES-256-GCM (데이터) + RSA-OAEP (키)
- 투명한 처리: 별도 코드 변경 없이 자동 암호화/복호화
- 성능 최적화: 5-10ms 오버헤드 (네트워크 지연 대비 미미)
- 안전한 실패: 암호화 실패 시 전송 중단
자세한 내용은 암호화 가이드를 참조하세요.
🌍 환경별 설정
SDK는 environment 설정에 따라 자동으로 적절한 엔드포인트를 사용합니다:
엔드포인트
| 환경 | 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 |
CDN 설정
⚠️ 중요: 프로젝트 설정은 CDN에서만 가져옵니다. CDN에 설정 파일이 없으면 다음과 같은 오류가 발생합니다:
REMOTE_CONFIG_FETCH_FAILED: Failed to fetch configuration for project {projectId}암호화 기능을 사용하려면 CDN에 다음과 같은 형식의 설정 파일이 필요합니다:
https://{cdn_domain}/sdk/v1/config/{projectId}/config.json환경별 사용 예시
// Production 환경 (기본값)
const vircle = new VircleCore({
apiKey: 'pk_myproject_prod123',
});
// Development 환경
const vircle = new VircleCore({
apiKey: 'pk_myproject_dev456',
environment: 'development',
});🎨 컨텍스트 관리
// 전역 컨텍스트 설정
vircle.setContext({
experiment: {
id: 'exp-123',
variant: 'A',
},
});
// 컨텍스트 지우기
vircle.clearContext();
// 수동 컨텍스트 수집
const contextService = new ContextService(config);
const context = await contextService.collectAutoContext();🏗️ 아키텍처 개요
Vircle SDK Core는 모듈화된 서비스 지향 아키텍처로 설계되었습니다:
┌────────────────────────────────────────────┐
│ VircleCore │
│ (중앙 오케스트레이터 - 모든 서비스 조정) │
└──────────────────────┬─────────────────────┘
│
┌────────────┬────────────┬───────────┬────────────┐
│ │ │ │ │
┌────▼────┐ ┌─────▼─────┐ ┌────▼────┐ ┌────▼─────┐ ┌────▼────┐
│ Event │ │ Transport │ │ Storage │ │ Plugin │ │ Remote │
│ Service │ │ Service │ │ Service │ │ Service │ │ Config │
└─────────┘ └───────────┘ └─────────┘ └──────────┘ └─────────┘📚 핵심 구성 요소
1. VircleCore - 중앙 제어 시스템
SDK의 모든 기능을 조율하는 메인 클래스입니다.
초기화 프로세스
- 생성자 단계: 서비스 인스턴스 생성, 기본 설정 적용
- initialize() 단계:
- 설정 검증
- 원격 설정 로드 (암호화 키, 배치 설정 등)
- 저장된 사용자 정보 복원
- 플러그인 생명주기 시작
주요 메서드
track<T>(name, properties?, context?): 이벤트 추적 및 서버 전송identify<T>(userId, traits?): 사용자 식별 및 속성 저장createEvent(name?): 체이닝 가능한 이벤트 빌더 반환flush(): 대기 중인 모든 이벤트 즉시 전송reset(): SDK 상태 초기화cleanup(): 모든 리소스 정리
2. 서비스 레이어
EventService - 이벤트 처리 엔진
- 역할: 이벤트의 생성, 검증, 보강, 전송 관리
- 이벤트 빌더 패턴 지원
- 자동 컨텍스트 보강
- 플러그인 훅 실행
- 우선순위 기반 큐 관리
TransportService - 네트워크 통신
- 역할: 이벤트를 서버로 안정적으로 전송
- 배치 처리 (여러 이벤트를 하나의 요청으로)
- 지수 백오프 재시도
- 서킷 브레이커 패턴
- HMAC 서명 및 페이로드 암호화
- 우선순위 큐 (CRITICAL > HIGH > NORMAL)
StorageService - 데이터 영속성
- 역할: 로컬 데이터 저장 및 관리
- 다중 어댑터 지원 (localStorage, IndexedDB, Memory)
- TTL (Time-To-Live) 지원
- 환경별 자동 어댑터 선택
PluginService - 확장성
- 역할: SDK 기능 확장을 위한 플러그인 관리
- 생명주기 관리 (initialize, cleanup)
- 다양한 훅 포인트 제공
- 격리된 실행 환경 (PluginContext)
- 실행 시간 초과 감지
RemoteConfigService - 동적 설정
- 역할: CDN에서 프로젝트별 설정 로드
- 싱글톤 패턴
- 메모리 캐싱 (5분)
- 설정 유효성 검증
- 환경별 CDN 엔드포인트
ConfigService - 설정 관리
- 역할: SDK 설정의 중앙 저장소
- 인메모리 설정 관리
- 부분 업데이트 지원
- 다른 서비스들의 설정 소스
3. 유틸리티 레이어
EventUtils - 이벤트 헬퍼
- 이벤트 데이터 병합 및 정규화
- 순환 참조 안전 복제
- 이벤트 크기 계산
- 고유 ID 생성
EncryptionUtils - 보안
- 하이브리드 암호화 (AES-256-GCM + RSA-OAEP)
- Web Crypto API / Node.js crypto 지원
- Base64 인코딩/디코딩
SecurityUtils - 보안 헬퍼
- API 키 마스킹 및 검증
- HMAC 서명 생성
- 타이밍 공격 방지 문자열 비교
PerformanceUtils - 성능 최적화
- requestIdleCallback 기반 태스크 스케줄링
- 우선순위 작업 큐
- UI 블로킹 방지
ContextCache - 캐싱
- 비용이 큰 작업 결과 캐싱
- Thundering Herd 문제 방지
- TTL 기반 캐시 무효화
CircuitBreaker - 장애 격리
- 서비스 장애 감지 및 차단
- 자동 복구 시도
- 3가지 상태: CLOSED, OPEN, HALF_OPEN
PriorityQueue - 우선순위 관리
- 이벤트 중요도별 정렬
- CRITICAL > HIGH > NORMAL 우선순위
- 효율적인 배치 추출
4. 모델 레이어
Config 모델
VircleConfig: 전체 SDK 설정BatchConfig: 배치 처리 설정RetryConfig: 재시도 정책StorageConfig: 저장소 설정
Event 모델
VircleEvent: 이벤트 데이터 구조EventContext: 이벤트 발생 환경 정보EventBuilder: 이벤트 생성 빌더
User 모델
VircleUser: 사용자 정보UserTraits: 사용자 속성Session: 세션 정보
Device 모델
DeviceInfo: 기기 정보DeviceType: 기기 유형 (MOBILE, TABLET, DESKTOP)BrowserInfo,OSInfo: 환경 정보
Context 모델
CollectedContext: 자동 수집된 모든 컨텍스트AppInfo,PageInfo: 앱/페이지 정보PerformanceInfo: 성능 메트릭
Plugin 모델
VirclePlugin: 플러그인 인터페이스PluginHook: 사용 가능한 훅 타입PluginContext: 플러그인 실행 환경
5. 에러 시스템
체계적인 에러 처리를 위한 커스텀 에러 클래스:
- VircleError: 기본 에러 클래스 (cause 체인 지원)
- ConfigurationError: 설정 관련 에러
- ValidationError: 데이터 검증 실패
- NetworkError: 네트워크 통신 에러
- StorageError: 저장소 접근 에러
- PluginError: 플러그인 실행 에러
각 에러는 표준화된 에러 코드(ErrorCode)를 가지며, 디버깅을 위한 상세한 컨텍스트를 포함합니다.
🧪 테스트
// SDK는 쉬운 테스트를 위해 설계되었습니다
const mockStorage = new MemoryStorageAdapter();
const mockTransport = new MockTransportService();
// 의존성 주입 사용 (계획된 기능)
const vircle = new VircleCore(config, options, {
storageService: mockStorage,
transportService: mockTransport,
});🔧 문제 해결
일반적인 문제
암호화 실패
- 원인: CDN에서 암호화 키를 찾을 수 없음
- 해결: CDN에 올바른 프로젝트 설정 파일이 있는지 확인
이벤트 전송 지연
- 원인: 배치 설정이 너무 큼
- 해결:
batch.size와batch.timeout값 조정
메모리 사용량 증가
- 원인: 이벤트 큐가 가득 참
- 해결:
flush()호출 또는queue.maxSize조정
📈 성능 최적화 팁
- 배치 크기 조정: 네트워크 상황에 맞게
batch.size최적화 - 우선순위 활용: 중요한 이벤트에 높은 우선순위 설정
- 캐싱 활용: 자주 사용되는 컨텍스트 데이터는 캐시 활용
- 플러그인 최적화: 무거운 작업은 플러그인에서 비동기 처리
