#Cascade Screening 쿡북

버전: 0.43.0 | 업데이트: 2026-03-28 | 적용 대상: ranvier-runtime 0.36+ | 카테고리: 쿡북


#개요

Cascade screening은 대상이 여러 독립적인 필터를 순차적으로 통과하는 패턴입니다. 각 필터는 거부(단락)하거나 통과시킬 수 있습니다. 이 패턴은 다음과 같은 경우에 이상적입니다:

  • 각 검사가 독립적으로 유효한 경우
  • 조기 거부가 후속 연산을 절약하는 경우
  • 검사 순서가 중요한 경우 (가장 저렴하거나 빠른 것부터)
  • 각 필터를 독립적으로 테스트하고 교체할 수 있는 경우

#1. 패턴 구조

Input → Screen A → Screen B → Screen C → Screen D → Approved
           ↓           ↓           ↓           ↓
        Reject A    Reject B    Reject C    Reject D

주요 특징:

  • Fail-fast: 첫 번째 거부가 전체 파이프라인을 단락시킴
  • 독립성: 각 필터는 다른 필터에 대해 알지 못함
  • 순서: 효율성을 위해 가장 저렴하거나 빠른 검사를 먼저 배치
  • 감사 가능성: 각 필터가 결정을 로깅함

#2. 적용 도메인: AML/KYC 컴플라이언스

신규 고객을 위한 4단계 컴플라이언스 스크리닝.

let screening = Axon::typed::<CustomerApplication, String>("kyc-screening")
    .then(sanctions_check)         // Screen 1: O(1) list lookup
    .then(pep_check)               // Screen 2: O(1) flag check
    .then(risk_scoring)            // Screen 3: O(n) algorithm
    .then(document_verification);  // Screen 4: expensive external API

// Screen order matters: sanctions check is instant, document
// verification calls an external API. Ordering cheapest-first
// avoids unnecessary API calls for sanctioned applicants.

#각 필터를 Transition으로 구현

#[transition]
async fn sanctions_check(
    applicant: CustomerApplication,
) -> Outcome<CustomerApplication, String> {
    let sanctioned_countries = ["NK", "SY", "IR"];
    if sanctioned_countries.contains(&applicant.country.as_str()) {
        return Outcome::Fault(format!(
            "Screen 1 REJECTED: {} from sanctioned country {}",
            applicant.name, applicant.country
        ));
    }
    Outcome::Next(applicant)
}

#3. 적용 도메인: 콘텐츠 검열

3단계 콘텐츠 검열 파이프라인.

let moderation = Axon::typed::<ContentSubmission, String>("content-moderation")
    .then(spam_filter)          // Fast regex/heuristic check
    .then(toxicity_classifier)  // ML model inference
    .then(policy_enforcer);     // Business rule evaluation

#패턴 인사이트

스팸 필터(마이크로초)는 독성 분류기(밀리초)보다 먼저 실행됩니다. 콘텐츠가 명백한 스팸이면 비용이 많이 드는 ML 모델은 호출되지 않습니다.


#4. 적용 도메인: 세관 신고 스크리닝

수입 신고를 위한 다층 세관 스크리닝.

let customs = Axon::typed::<ImportDeclaration, String>("customs-screening")
    .then(tariff_classification)    // Classify goods by HS code
    .then(restricted_goods_check)   // Check against restricted list
    .then(valuation_check)          // Verify declared value
    .then(origin_verification);     // Country of origin rules

#5. 감사 추적을 위한 Outcome::Emit 결합

각 필터는 파이프라인을 계속 진행하면서 감사 이벤트를 발행할 수 있습니다:

#[transition]
async fn pep_check(
    mut applicant: CustomerApplication,
    bus: &mut Bus,
) -> Outcome<CustomerApplication, String> {
    let is_pep = check_pep_database(&applicant.name).await;

    // Log the screen result to Bus for audit trail
    bus.insert(ScreenResult {
        screen: "pep",
        passed: !is_pep,
        timestamp: chrono::Utc::now(),
    });

    if is_pep {
        Outcome::Fault("PEP check: flagged as politically exposed".into())
    } else {
        Outcome::Next(applicant)
    }
}

#6. Rule Chain과의 차이점

측면 Cascade Screening Rule Chain
초점 필터링/거부 평가/점수 산정
거부 도메인 특화 로직 일반적인 임계값
출력 통과/거부 결정 적격성 결과
순서 성능 중심 로직 중심

둘 다 동일한 Axon 메커니즘(Outcome::Next / Outcome::Fault)을 사용하지만 의도가 다릅니다. Screening은 fail-fast 필터링을 강조하고, rule chain은 포괄적인 평가를 강조합니다.


#빠른 참조

Start Template:  ranvier new my-app --template screening
Example:         cargo run -p cascade-screening
Pattern Tag:     screening

#참고 자료

  • cascade-screening 예제 — 순수 Axon screening 데모
  • compliance-demo 예제 — Guards를 사용한 HTTP screening
  • cookbook_saga_compensation.md — 필터가 보상 가능한 액션을 트리거하는 경우