logo MSJO.kr

Rust Web Frameworks 비교

2025-09-03
MsJ
 

Rust는 dotnet(C#)에 비해 성능이 우수하다고 알려져 있다.1 대표적인 Rust의 Web Frameworks에는 대표적으로 Actix Web, Rocket, Warp, Axum, Poem 등이 있는데 각각의 특징을 간략하게 예제(Axum)와 더불어 정리하였다.

학습에 도움이 될 만한 youtube 강좌
TechEmpower 벤치마크 결과 (Round 21)
프레임워크 언어 요청/초 지연시간(ms) CPU 사용률
Actix-web (Rust) Rust 748,051 1.7 98%
Axum (Rust) Rust 723,892 1.8 97%
ASP.NET Core C# 692,345 2.1 95%
Spring Boot Java 153,846 6.5 92%
Express.js Node.js 58,824 17.0 85%

dotNET의 경우 Rust에 비해 떨어지지 않는 성능을 보여준다.

Rust Web Framework vs. .NET WebAPI 성능 비교2
항목 Rust Web Framework .NET WebAPI
동시 처리 매우 우수. Rust의 zero-cost abstraction과 안전한 메모리 모델 덕분에 수천~수만 동시 연결 처리 가능 Kestrel 서버 기반의 .NET Core도 수천 동시 연결 가능. 스레드풀과 async/await로 효율적 처리
동시성 Rust는 기본적으로 데이터 레이스를 방지. Send/Sync 트레이트로 안전하게 동시성 구현 .NET도 스레드 안전성 제공. Task 기반 비동기 모델로 동시성 구현. 그러나 메모리 리스크는 비교적 높음
비동기 처리 async/await, non-blocking IO, Tokio/async-std 등 강력한 지원 async/await, non-blocking IO, 스레드풀 기반 비동기 처리 지원
성능 벤치마크 Actix Web 기준: wrk, techempower benchmarks에서 가장 빠른 성능 자주 기록 (수백만 req/s) ASP.NET Core: wrk, techempower benchmarks에서 상위권. Rust보다 약간 낮거나 비슷한 수준
메모리 사용량 매우 낮음. Rust의 ownership 시스템 덕분에 GC 오버헤드 없음 GC 기반이라 Rust보다 메모리 사용량 많음. 하지만 최적화로 많이 개선됨
안정성 컴파일 타임에 대부분의 오류 검출. 런타임 오류 적음 런타임에서 오류 발견 가능성 더 있음. C# 타입 시스템으로 어느 정도 방지
커뮤니티/생태계 안정적이고 빠르게 성장 중. 크지는 않음 매우 크고 성숙. 다양한 라이브러리와 툴링 지원

기술적 차이점의 요인으로 ‘메모리 관리’, ‘동시성 모델’, ‘네트워킹 스택’을 보면 Rust가 dotNET에 비해 상당히 성능이 우수하다. 그러나 극한의 성능과 안정성보다 생산성, 툴링, 윈도우/엔터프라이즈 환경친화성이 우선이라면 dotNET WebAPI가 더 우수하다고 볼 수 있다.

Rust 프레임워크 비교3
프레임워크 주된 특징 성능 사용 편의성 에코시스템 / 확장성
Actix Web 매우 높은 성능, Actor 기반 아키텍처, WebSocket 및 다양한 기능 내장 최상위권 (최고 처리량, 낮은 레이턴시) 다소 복잡 (액터 모델, 매크로 활용 등) 가장 성숙하고 확장성 높은 생태계 (ORM, 인증, 미들웨어 등)
Rocket 간결하고 타입 안전한 라우팅, Request Guards, Fairings(미들웨어) 좋은 성능, Actix에는 약간 밀림 초보자에게 매우 친숙한 API, 매크로 기반으로 간단 점진적으로 성장 중, 폼 처리 및 DB 등의 지원도 증가 중
Warp 필터 기반의 컴포저형 설계, 하이퍼 기반, 매우 유연함 가볍고 빠름, 오버헤드 최소화 필터 체이닝이 직관적이지만 초기 학습 곡선 존재 에코시스템은 작지만 비동기 유틸리티 중심으로 확장 중
Axum Tokio + Hyper + Tower 기반, macro-free, 라우터 중심 설계 강력한 비동기 성능, 높은 처리량 직관적이고 러스트 초심자에게도 친숙한 API 빠르게 성장 중인 생태계, 웹 관련 크레이트 늘어남
Poem 간결하고 쉬운 사용성, minimalism 지향 빠름 (경량 기반), 규모에 따라 다름 단순하고 배우기 쉬움, 복잡 기능은 외부 크레이트 사용 필요 초기 단계지만 성장 중이고 커뮤니티 활성화 중

사용하기 쉽고 성능에 최적화된 비동기 프레임워크는 Axum이라고 볼 수 있다.

  • 비동기 특화: Tokio + Hyper + Tower 기반 → async/await 친화적
  • 성능: Actix Web과 큰 차이 없는 높은 처리량, 낮은 레이턴시
  • 사용 편의성: 매크로 대신 함수/라우터 기반 API → 러스트 초보자도 직관적으로 사용 가능
  • 에코시스템: Tower 미들웨어, tokio 생태계와 완벽 호환 → 확장성 뛰어남
  • 현대적 설계: 최근 Rust async 웹 개발의 사실상 표준으로 자리잡는 추세
Axum 예제
# Cargo.toml
[package]  
name = "hello"  
version = "0.1.0"  
edition = "2024"  
  
[dependencies]  
axum = "0.8.1"  
tokio = { version = "1.47.1", features = ["full"] }  
serde = { version = "1.0.219", features = ["derive"] }  
serde_json = "1"  
http = "1.3.1"
// main.rs
use axum::{  
    extract::Json,  
    http::StatusCode,  
    response::IntoResponse,  
    routing::post,  
    Router,  
};  
use serde::{Deserialize, Serialize};  
use std::net::SocketAddr;  
use tokio::time::{sleep, Duration};  
  
#[derive(Serialize)]  
struct User {  
    id: u32,  
    name: String,  
}  
  
#[derive(Serialize)]  
struct ErrorResponse {  
    error: String,  
}  
  
#[derive(Deserialize)]  
struct UserRequest {  
    id: u32,  
}  
  
async fn root() -> impl IntoResponse {  
    Json(serde_json::json!({"message": "Hello, World!"}))  
}  
  
async fn get_user(Json(req): Json<UserRequest>) -> impl IntoResponse {  
    // DB 조회 (비동기 처리) 가정  
    sleep(Duration::from_millis(300)).await;  
  
    if req.id == 0 {  
        let err = ErrorResponse {  
            error: "User not found".to_string(),  
        };  
        (StatusCode::NOT_FOUND, Json(err)).into_response()  
    } else {  
        let user = User {  
            id: req.id,  
            name: format!("User{}", req.id),  
        };  
        (StatusCode::OK, Json(user)).into_response()  
    }  
}  
  
#[tokio::main]  
async fn main() {  
    let app = Router::new()  
        .route("/", post(root))  
        .route("/users", post(get_user));  
  
    let addr = SocketAddr::from(([0, 0, 0, 0], 3000));  
    println!("Server listening on {}", addr);  
  
    if let Err(e) = axum::serve(tokio::net::TcpListener::bind(addr).await.unwrap(), app).await {  
        eprintln!("server error: {e:?}");  
    }  
}
예제 테스트
# root API
curl -X POST http://localhost:3000/
# {"message":"Hello, World!"}
# User조회 API(정상)
curl -X POST http://localhost:3000/users -H "Content-Type: application/json" -d "{\"id\": 1}"
# {"id":1,"name":"User1"}
# User조회 API(없음)
curl -X POST http://localhost:3000/users -H "Content-Type: application/json" -d "{\"id\": 0}"
# {"error":"User not found"}
Reference
  1. techempower.com, “TechEmpower Benchmarks”
  2. Github Copilot, https://dev.to/leapcell/rust-web-frameworks-compared-actix-vs-axum-vs-rocket-4bad 기반
  3. ChatGPT, https://dev.to/leapcell/rust-web-frameworks-compared-actix-vs-axum-vs-rocket-4bad 기반

Prεv(Θld)  
Content
Search     RSS Feed     BY-NC-ND