🦀 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은 타입 기반 익스트랙터