- 학습에 도움이 될 만한 youtube 강좌
- TechEmpower 벤치마크 결과 (Round 21)
- Rust Web Framework vs. .NET WebAPI 성능 비교2
- Rust 프레임워크 비교3
- Axum 예제
- 예제 테스트
- Reference
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
- techempower.com, “TechEmpower Benchmarks”
- Github Copilot, https://dev.to/leapcell/rust-web-frameworks-compared-actix-vs-axum-vs-rocket-4bad 기반
- ChatGPT, https://dev.to/leapcell/rust-web-frameworks-compared-actix-vs-axum-vs-rocket-4bad 기반