철학 / 핵심 패러다임

네 가지 기둥

Ranvier의 정체성은 함께 작동하여 구조 중심의 시각화 가능한 프레임워크를 만드는 네 가지 기본 개념 위에 세워졌습니다.

Transition Outcome Bus Schematic

1. Transition

Transition은 하나의 상태를 다른 상태로 변환하는 순수하고 조합 가능한 함수이며, 타입이 지정된 에러로 실패할 수 있습니다. Ranvier에서 계산의 기본 단위입니다.

주요 특징

순수함: 동일한 입력이 주어지면 항상 동일한 출력 생성 (비동기 I/O 제외)
타입 지정: 입력, 출력, 에러 타입이 명시적
조합 가능: `.pipe()`, `.fanout()`, `.parallel()` 로 체인 구성 가능
테스트 용이: 독립적으로 단위 테스트하기 쉬움

왜 중요한가

  • 타입 안전성: 컴파일러가 빌드 시점에 유효하지 않은 상태 전환을 감지
  • 조합: 단순한 transition을 체인으로 연결하여 복잡한 워크플로우 구축
  • 가시성: 각 transition이 Schematic 그래프의 노드로 나타남
  • 테스팅: 인프라를 건드리지 않고 입출력을 모킹

예제

use ranvier::prelude::*;

#[transition]
async fn validate_input(req: Request) -> Outcome<ValidRequest, ValidationError> {
    if req.body.is_empty() {
        return Outcome::err(ValidationError::EmptyBody);
    }
    Outcome::ok(ValidRequest::from(req))
}

#[transition]
async fn process(input: ValidRequest) -> Outcome<Response, ProcessError> {
    // Business logic here
    let result = compute(&input).await?;
    Outcome::ok(Response::new(result))
}

// Compose:
let pipeline = Axon::simple::<AppError>()
    .pipe(validate_input, process)
    .build();

2. Outcome

Outcome은 명시적 에러 타입과 함께 성공(`ok`) 또는 실패(`err`)를 나타내는 Ranvier의 결과 타입입니다. `Result<T, E>`와 유사하지만 Transition 시스템과 통합됩니다.

주요 특징

명시적 에러: 각 transition이 에러 타입을 선언
Bus 통합: 성공한 outcome이 Bus에 값을 저장할 수 있음
Schematic 메타데이터: Outcome이 시각화를 위한 메타데이터 보유
인체공학적: `?` 연산자와 `.map()`, `.and_then()` 같은 헬퍼 메서드 지원

왜 중요한가

  • 에러 투명성: 타입 시그니처에서 가능한 모든 실패 확인 가능
  • 우아한 저하: 올바른 레벨(transition, 파이프라인, 전역)에서 에러 처리
  • 디버깅: Outcome 메타데이터가 schematic을 통한 실패 추적을 도움

예제

// Transition returns Outcome
#[transition]
async fn fetch_user(id: UserId) -> Outcome<User, DatabaseError> {
    match db.get_user(id).await {
        Ok(user) => Outcome::ok(user),
        Err(e) => Outcome::err(DatabaseError::from(e)),
    }
}

// Outcome values automatically stored in Bus if marked
#[transition]
async fn enrich_user(user: User) -> Outcome<EnrichedUser, EnrichmentError> {
    // 'user' came from Bus (injected automatically)
    let profile = fetch_profile(&user).await?;
    Outcome::ok(EnrichedUser { user, profile })
}

3. Bus

Bus는 단일 실행 컨텍스트 내에서 transition 간 상태를 공유하기 위한 타입 안전한 인메모리 저장소입니다. "데이터를 위한 의존성 주입"으로 생각할 수 있습니다.

주요 특징

타입 인덱스: 타입으로 값을 저장하고 검색 (`TypeMap`과 유사)
자동 주입: Transition이 파라미터를 통해 Bus에서 값을 요청할 수 있음
스코프 지정: 각 실행마다 자체 Bus 인스턴스 보유 (전역 상태 없음)
불변 참조: Transition이 Bus에서 `&T`를 받음 (소유권 이전 없음)

왜 중요한가

  • 명시적 의존성: Transition 시그니처가 필요한 데이터를 표시
  • 마법 같은 전역 변수 없음: 모든 상태가 실행에 명시적으로 스코프 지정됨
  • 테스트 용이성: 테스트를 위해 Bus에 모의 값 주입
  • 컨텍스트 전파: 파이프라인을 통해 인증, 테넌트 ID 등 전달

예제

#[transition]
async fn authenticate(req: Request) -> Outcome<AuthContext, AuthError> {
    let token = extract_token(&req)?;
    let auth = validate(token).await?;
    // AuthContext automatically stored in Bus for downstream transitions
    Outcome::ok(auth)
}

#[transition]
async fn authorize(auth: &AuthContext) -> Outcome<(), AuthError> {
    // 'auth' automatically injected from Bus (by type)
    if !auth.has_role("admin") {
        return Outcome::err(AuthError::Unauthorized);
    }
    Outcome::ok(())
}

#[transition]
async fn handle_request(auth: &AuthContext, req: &Request) -> Outcome<Response, AppError> {
    // Both 'auth' and 'req' injected from Bus
    Ok(Response::new(format!("Hello, {}", auth.user_id)))
}

4. Schematic

Schematic은 transition 파이프라인의 방향성 비순환 그래프(DAG) 표현입니다. 런타임 실행 모델이자 VSCode 같은 도구가 렌더링할 수 있는 시각적 아티팩트(JSON)입니다.

주요 특징

노드: 각 transition이 노드
엣지: Transition 간 데이터 흐름
메타데이터: 타입, 에러 경로, 실행 통계
직렬화 가능: 시각화를 위해 `schematic.json`으로 내보내기

왜 중요한가

  • 가시성: VSCode Circuit 뷰에서 전체 데이터 흐름을 한눈에 확인
  • 문서화: Schematic이 곧 문서 (항상 최신 상태)
  • 디버깅: 그래프를 통해 에러 추적, 실패한 노드 확인
  • 최적화: 병목 지점 식별, 가능한 곳 병렬화

예제

// Build a schematic
let schematic = Axon::simple::<AppError>()
    .pipe(authenticate, authorize, handle_request)
    .build();

// Execute
let outcome = schematic.execute(request).await;

// Export to JSON (for VSCode visualization)
let json = schematic.to_json();
std::fs::write("schematic.json", json)?;
다음 단계: 핵심 패러다임을 이해했으니 왜 명확한 철학을 가진 코어인가?를 살펴보고 Ranvier가 왜 이러한 개념을 반드시 따르는지 확인하세요.