우선순위 기반 핸들러 실행
적절한 비즈니스 로직 플로우를 위해 핸들러가 올바른 순서로 실행되도록 하는 우선순위 기반 실행.
기본 우선순위 시스템
우선순위 레벨
핸들러는 내림차순 우선순위 순서로 실행됩니다 (높은 숫자 먼저):
typescript
actionRegister.register('authenticate', validateInput, { priority: 100 }); // 1번째 실행
actionRegister.register('authenticate', checkRateLimit, { priority: 90 }); // 2번째 실행
actionRegister.register('authenticate', performAuth, { priority: 80 }); // 3번째 실행
actionRegister.register('authenticate', logAudit, { priority: 70 }); // 4번째 실행기본 우선순위
우선순위를 지정하지 않으면 핸들러는 기본적으로 우선순위 50을 가집니다:
typescript
// 이 핸들러들은 우선순위 50을 가지며 등록 순서대로 실행됩니다
actionRegister.register('processData', handlerA);
actionRegister.register('processData', handlerB);
actionRegister.register('processData', handlerC);우선순위 카테고리
높은 우선순위 (90-100): 시스템 중요
- 입력 검증
- 보안 검사
- 속도 제한
- 인증
typescript
// 중요한 검사가 먼저 오는 인증 파이프라인
actionRegister.register('authenticate', validateCredentials, { priority: 100 });
actionRegister.register('authenticate', checkSecurityPolicy, { priority: 95 });
actionRegister.register('authenticate', rateLimitCheck, { priority: 90 });중간 우선순위 (50-89): 비즈니스 로직
- 데이터 처리
- 비즈니스 규칙 검증
- 외부 API 호출
- 상태 업데이트
typescript
// 비즈니스 로직을 사용한 데이터 처리
actionRegister.register('processOrder', validateBusinessRules, { priority: 80 });
actionRegister.register('processOrder', calculatePricing, { priority: 70 });
actionRegister.register('processOrder', updateInventory, { priority: 60 });
actionRegister.register('processOrder', sendConfirmation, { priority: 50 });낮은 우선순위 (10-49): 로깅 및 분석
- 감사 로깅
- 분석 추적
- 성능 모니터링
- 정리 작업
typescript
// 로깅과 분석은 마지막에
actionRegister.register('userAction', processAction, { priority: 80 });
actionRegister.register('userAction', trackAnalytics, { priority: 30 });
actionRegister.register('userAction', auditLog, { priority: 20 });
actionRegister.register('userAction', cleanup, { priority: 10 });우선순위 실행 예제
예제 1: 인증 플로우
typescript
interface AuthActions extends ActionPayloadMap {
login: { username: string; password: string };
}
const authRegister = new ActionRegister<AuthActions>();
// 우선순위 100: 중요한 검증
authRegister.register('login', (payload, controller) => {
if (!payload.username || !payload.password) {
controller.abort('인증 정보 누락');
return;
}
controller.setResult({ step: 'validation', valid: true });
return { step: 'input-validation', success: true };
}, { priority: 100, id: 'input-validator' });
// 우선순위 90: 보안 검사
authRegister.register('login', async (payload, controller) => {
const isSuspicious = await checkSuspiciousActivity(payload.username);
if (isSuspicious) {
controller.abort('의심스러운 활동 감지');
return;
}
controller.setResult({ step: 'security', cleared: true });
return { step: 'security-check', success: true };
}, { priority: 90, id: 'security-checker' });
// 우선순위 80: 속도 제한
authRegister.register('login', (payload, controller) => {
const rateLimiter = getRateLimiter(payload.username);
if (!rateLimiter.isAllowed()) {
controller.abort('속도 제한 초과');
return;
}
rateLimiter.consume();
controller.setResult({ step: 'rate-limit', consumed: true });
return { step: 'rate-limiting', success: true };
}, { priority: 80, id: 'rate-limiter' });
// 우선순위 70: 인증
authRegister.register('login', async (payload) => {
const user = await authenticateUser(payload.username, payload.password);
const token = generateJWT(user);
return {
step: 'authentication',
success: true,
user: { id: user.id, username: user.username },
token
};
}, { priority: 70, id: 'authenticator' });
// 우선순위 30: 분석 (낮은 우선순위)
authRegister.register('login', (payload) => {
analytics.track('login_attempt', {
username: payload.username,
timestamp: Date.now()
});
return { step: 'analytics', tracked: true };
}, { priority: 30, id: 'analytics-tracker' });
// 우선순위 10: 감사 로깅 (가장 낮은 우선순위)
authRegister.register('login', (payload, controller) => {
const results = controller.getResults();
const authResult = results.find(r => r.step === 'authentication');
auditLogger.log({
action: 'login',
username: payload.username,
success: authResult?.success || false,
timestamp: Date.now()
});
return { step: 'audit', logged: true };
}, { priority: 10, id: 'audit-logger' });예제 2: 데이터 처리 파이프라인
typescript
interface DataActions extends ActionPayloadMap {
processData: { data: any; options?: ProcessingOptions };
}
const dataRegister = new ActionRegister<DataActions>();
// 우선순위 100: 입력 살균
dataRegister.register('processData', (payload, controller) => {
const sanitized = sanitizeInput(payload.data);
controller.modifyPayload(current => ({
...current,
data: sanitized,
sanitized: true
}));
return { step: 'sanitization', success: true };
}, { priority: 100, id: 'sanitizer' });
// 우선순위 90: 스키마 검증
dataRegister.register('processData', (payload, controller) => {
const isValid = validateSchema(payload.data);
if (!isValid) {
controller.abort('스키마 검증 실패');
return;
}
controller.setResult({ step: 'validation', schema: 'valid' });
return { step: 'schema-validation', success: true };
}, { priority: 90, id: 'schema-validator' });
// 우선순위 80: 비즈니스 규칙
dataRegister.register('processData', (payload, controller) => {
const violations = checkBusinessRules(payload.data);
if (violations.length > 0) {
controller.abort(`비즈니스 규칙 위반: ${violations.join(', ')}`);
return;
}
return { step: 'business-validation', success: true };
}, { priority: 80, id: 'business-validator' });
// 우선순위 70: 데이터 변환
dataRegister.register('processData', (payload) => {
const transformed = transformData(payload.data, payload.options);
return {
step: 'transformation',
success: true,
data: transformed,
originalSize: JSON.stringify(payload.data).length,
transformedSize: JSON.stringify(transformed).length
};
}, { priority: 70, id: 'transformer' });
// 우선순위 60: 데이터베이스 저장
dataRegister.register('processData', async (payload, controller) => {
const results = controller.getResults();
const transformed = results.find(r => r.step === 'transformation')?.data;
const savedId = await database.save(transformed);
return {
step: 'persistence',
success: true,
id: savedId,
timestamp: Date.now()
};
}, { priority: 60, id: 'persister' });
// 우선순위 20: 성능 모니터링
dataRegister.register('processData', (payload, controller) => {
const results = controller.getResults();
const duration = Date.now() - (results[0]?.timestamp || Date.now());
performanceMonitor.track('data_processing', {
duration,
dataSize: JSON.stringify(payload.data).length,
handlersExecuted: results.length
});
return { step: 'monitoring', tracked: true, duration };
}, { priority: 20, id: 'monitor' });우선순위 모범 사례
1. 표준 우선순위 범위 사용
typescript
// 시스템 중요: 90-100
const PRIORITY_CRITICAL = 100;
const PRIORITY_SECURITY = 95;
const PRIORITY_VALIDATION = 90;
// 비즈니스 로직: 50-89
const PRIORITY_BUSINESS_HIGH = 80;
const PRIORITY_BUSINESS_MEDIUM = 70;
const PRIORITY_BUSINESS_LOW = 60;
const PRIORITY_PROCESSING = 50;
// 모니터링/로깅: 10-49
const PRIORITY_ANALYTICS = 30;
const PRIORITY_AUDIT = 20;
const PRIORITY_CLEANUP = 10;2. 관련 핸들러 그룹화
typescript
// 인증 그룹 (90-100)
authRegister.register('login', inputValidator, { priority: 100 });
authRegister.register('login', securityChecker, { priority: 95 });
authRegister.register('login', rateLimiter, { priority: 90 });
// 비즈니스 로직 그룹 (70-80)
authRegister.register('login', authenticator, { priority: 80 });
authRegister.register('login', sessionManager, { priority: 70 });
// 모니터링 그룹 (10-30)
authRegister.register('login', analyticsTracker, { priority: 30 });
authRegister.register('login', auditLogger, { priority: 20 });3. 우선순위 간격 유지
typescript
// ✅ 좋음 - 기존 핸들러 사이에 핸들러를 삽입할 수 있음
actionRegister.register('process', handlerA, { priority: 100 });
actionRegister.register('process', handlerB, { priority: 80 }); // 20의 간격
actionRegister.register('process', handlerC, { priority: 60 }); // 20의 간격
// ❌ 피해야 할 것 - 새 핸들러를 위한 공간이 없음
actionRegister.register('process', handlerA, { priority: 100 });
actionRegister.register('process', handlerB, { priority: 99 }); // 너무 가까움
actionRegister.register('process', handlerC, { priority: 98 }); // 너무 가까움4. 우선순위 근거 문서화
typescript
// 주석에 명확한 우선순위 근거
actionRegister.register('uploadFile', validateFile, {
priority: 100, // 모든 처리 전에 검증해야 함
id: 'file-validator'
});
actionRegister.register('uploadFile', scanVirus, {
priority: 95, // 검증 후 보안 스캔
id: 'virus-scanner'
});
actionRegister.register('uploadFile', processFile, {
priority: 80, // 보안 허가 후에만 처리
id: 'file-processor'
});우선순위 시각화
mermaid
graph TD
A[액션 디스패치] --> B{우선순위 100}
B --> C{우선순위 90}
C --> D{우선순위 80}
D --> E{우선순위 70}
E --> F{우선순위 50}
F --> G{우선순위 30}
G --> H{우선순위 20}
H --> I{우선순위 10}
I --> J[파이프라인 완료]
B --> B1[검증 핸들러]
C --> C1[보안 핸들러]
D --> D1[비즈니스 핸들러]
E --> E1[처리 핸들러]
F --> F1[업데이트 핸들러]
G --> G1[분석 핸들러]
H --> H1[감사 핸들러]
I --> I1[정리 핸들러]실제 예제: 우선순위 성능 데모
우선순위 성능 데모에서 우선순위 기반 실행의 실제 구현을 확인하세요:
typescript
// 높은 우선순위 검증 (100) - 높은 숫자 = 높은 우선순위
useActionHandler('executeHighPriority', handler, { priority: 100 });
// 중간 우선순위 비즈니스 로직 (80)
useActionHandler('executeMediumPriority', handler, { priority: 80 });
// 낮은 우선순위 분석 (30)
useActionHandler('executeLowPriority', handler, { priority: 30 });이 예제는 우선순위가 실제 시나리오에서 실행 순서에 어떻게 영향을 주는지 보여주는 타이밍 측정과 함께 성능 추적을 보여줍니다.