🦀 actix-web 통합 가이드

actix-web 핸들러에서 Ranvier 트랜지션 사용

개요

actix-web은 Rust를 위한 강력하고 실용적이며 매우 빠른 웹 프레임워크입니다. actix 핸들러에 Ranvier 트랜지션을 통합하여 두 프레임워크의 강점을 모두 활용할 수 있습니다:

  • actix-web: 익스트랙터, 미들웨어, 견고한 HTTP 처리
  • Ranvier: Schematic 시각화, Bus 전파, 조합 가능한 로직

통합 패턴

actix 핸들러 내에서 Ranvier 트랜지션을 호출하는 것이 권장 접근법입니다:

예제: actix 핸들러에서 Ranvier 트랜지션 호출

use actix_web::{web, HttpRequest, HttpResponse};
use ranvier_core::{Bus, Outcome};
use ranvier_macros::transition;
use ranvier_runtime::Axon;

// Ranvier 트랜지션 정의
#[transition]
async fn process_order(
    order: Order,
    _res: &(),
    bus: &mut Bus
) -> Outcome<OrderResult, AppError> {
    // 비즈니스 로직
    Outcome::Next(OrderResult { id: order.id, status: "processed" })
}

// actix 핸들러
async fn create_order(
    req: HttpRequest,
    order: web::Json<Order>,
    pipeline: web::Data<Axon<Order, OrderResult, AppError, ()>>
) -> HttpResponse {
    let mut bus = Bus::new();

    // 선택사항: 요청에서 인증 추출 후 Bus에 추가
    if let Some(auth) = req.extensions().get::<AuthContext>() {
        bus.insert(auth.clone());
    }

    // Ranvier 파이프라인 실행
    match pipeline.execute(order.into_inner(), &(), &mut bus).await {
        Outcome::Next(result) => HttpResponse::Ok().json(result),
        Outcome::Fault(err) => HttpResponse::BadRequest().json(err),
        _ => HttpResponse::InternalServerError().finish(),
    }
}

// actix 앱 설정
#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let pipeline = Axon::simple::<AppError>("order-pipeline")
        .then(process_order);

    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(pipeline.clone()))
            .route("/orders", web::post().to(create_order))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

예제: Ranvier와 함께 actix 익스트랙터 사용

use actix_web::{web, HttpResponse, Responder};
use actix_web_httpauth::extractors::bearer::BearerAuth;

async fn protected_handler(
    auth: BearerAuth,  // actix 익스트랙터
    data: web::Json<RequestData>,
    pipeline: web::Data<Axon<RequestData, ResponseData, AppError, ()>>
) -> impl Responder {
    let mut bus = Bus::new();

    // 추출한 토큰을 Bus에 추가하여 Ranvier 트랜지션에서 사용
    bus.insert(auth.token().to_string());

    match pipeline.execute(data.into_inner(), &(), &mut bus).await {
        Outcome::Next(result) => HttpResponse::Ok().json(result),
        Outcome::Fault(err) => HttpResponse::Unauthorized().json(err),
        _ => HttpResponse::InternalServerError().finish(),
    }
}

이 접근법을 사용해야 하는 경우

✅ 적합한 경우:

  • 복잡한 비즈니스 로직에 Ranvier를 추가하는 기존 actix-web 앱
  • actix 익스트랙터와 미들웨어에 익숙한 팀
  • HTTP 처리를 위한 actix의 성능이 필요한 경우
  • 비즈니스 워크플로우를 위한 Ranvier의 Schematic 시각화가 필요한 경우

⚠️ 고려사항:

  • 컨텍스트 브리징: actix 요청 컨텍스트(익스트랙터)를 Ranvier Bus로 수동으로 브리징해야 함
  • 미들웨어 가시성: actix 미들웨어는 Ranvier Schematic에 표시되지 않음
  • 테스팅: actix 통합 테스트 필요 (Ranvier 트랜지션은 별도로 단위 테스트)

트레이드오프

측면장점제한사항
익스트랙터actix의 강력한 익스트랙터 사용 (Json, Query, Path, Auth)Bus로의 수동 브리징 필요
미들웨어actix 미들웨어 생태계 활용Ranvier Schematic에 보이지 않음
비즈니스 로직Schematic 시각화가 있는 Ranvier 트랜지션actix ↔ Ranvier 통합을 위한 추가 보일러플레이트
성능actix의 검증된 HTTP 성능 + Ranvier 로직컨텍스트 브리징의 최소 오버헤드

대안과의 비교

  • 순수 Ranvier와 비교: actix 통합은 actix 익스트랙터/미들웨어를 제공하지만 일부 Schematic 가시성을 잃음
  • Tower 통합과 비교: 유사한 패턴이지만 actix는 다른 익스트랙터 모델 (함수 매개변수 vs request.extensions)
  • Axum 통합과 비교: actix는 트레이트 기반 익스트랙터, Axum은 타입 기반 익스트랙터

다음 단계

참고: 전체 actix-web + Ranvier 예제는 향후 마일스톤에 계획되어 있습니다. 지금은 위의 코드 스니펫을 시작점으로 사용하세요.

통합 패턴에 대해 자세히 알아보려면: