Actix
Rust의 고성능 웹 프레임워크
Rust의 고성능 웹 프레임워크
Actix는 Rust 언어로 작성된 고성능 웹 프레임워크로, 액터 모델(Actor Model)을 기반으로 설계되었습니다. 2017년 Nikolay Kim이 개발을 시작했으며, TechEmpower 웹 프레임워크 벤치마크에서 꾸준히 상위권을 차지하며 세계에서 가장 빠른 웹 프레임워크 중 하나로 인정받고 있습니다.
Actix-web은 Actix 액터 프레임워크 위에 구축된 웹 프레임워크입니다. 비동기 I/O를 위해 Tokio 런타임을 사용하며, Rust의 소유권 시스템과 타입 안전성을 활용해 메모리 안전하면서도 C/C++ 수준의 성능을 제공합니다. HTTP/1.x와 HTTP/2를 모두 지원하고, WebSocket도 내장되어 있습니다.
액터 모델은 각 액터가 독립적인 상태를 가지며 메시지를 통해서만 통신하는 동시성 모델입니다. 이 방식은 공유 상태로 인한 데이터 레이스를 원천적으로 방지하며, 수천 개의 동시 연결도 효율적으로 처리할 수 있습니다. Actix는 이를 통해 확장성 높은 마이크로서비스 구축에 이상적입니다.
실무에서 Actix는 높은 처리량이 필요한 API 서버, 실시간 데이터 스트리밍, 고성능 프록시 서버 등에 사용됩니다. Discord, Cloudflare 등 대규모 트래픽을 처리하는 기업들이 Rust 기반 서비스에 Actix를 채택하고 있으며, 특히 초당 수십만 요청을 처리해야 하는 환경에서 Go나 Node.js 대비 현저히 낮은 메모리 사용량과 지연 시간을 보여줍니다.
use actix_web::{web, App, HttpServer, HttpResponse, Responder};
use serde::{Deserialize, Serialize};
// 1. JSON 요청/응답을 위한 구조체 정의
#[derive(Deserialize)]
struct CreateUser {
name: String,
email: String,
}
#[derive(Serialize)]
struct User {
id: u64,
name: String,
email: String,
}
// 2. 핸들러 함수 정의
async fn hello() -> impl Responder {
HttpResponse::Ok().body("안녕하세요! Actix-web입니다.")
}
async fn create_user(user: web::Json<CreateUser>) -> impl Responder {
let new_user = User {
id: 1,
name: user.name.clone(),
email: user.email.clone(),
};
HttpResponse::Created().json(new_user)
}
async fn get_user(path: web::Path<u64>) -> impl Responder {
let user_id = path.into_inner();
let user = User {
id: user_id,
name: "홍길동".to_string(),
email: "hong@example.com".to_string(),
};
HttpResponse::Ok().json(user)
}
// 3. 서버 시작
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("서버 시작: http://127.0.0.1:8080");
HttpServer::new(|| {
App::new()
.route("/", web::get().to(hello))
.route("/users", web::post().to(create_user))
.route("/users/{id}", web::get().to(get_user))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
"이 API 서버는 초당 10만 요청을 처리해야 합니다. Node.js로는 메모리 사용량이 너무 높아지는데, Actix-web으로 전환하면 동일 스펙에서 3배 이상의 처리량과 70% 낮은 메모리 사용량을 기대할 수 있습니다."
"Actix-web은 액터 모델을 기반으로 하며, Tokio 런타임 위에서 비동기 I/O를 처리합니다. Rust의 소유권 시스템 덕분에 데이터 레이스 없이 안전한 동시성을 구현할 수 있고, TechEmpower 벤치마크에서 상위권 성능을 보여줍니다."
"이 핸들러에서 blocking I/O를 직접 호출하면 안 됩니다. web::block으로 감싸서 별도 스레드풀에서 실행하거나, 비동기 버전의 라이브러리를 사용해주세요. 그렇지 않으면 전체 런타임이 블록됩니다."
sync 데이터베이스 드라이버나 파일 I/O를 직접 호출하면 전체 런타임이 멈춥니다. `web::block()`을 사용하거나 sqlx, tokio-postgres 같은 async 드라이버를 사용하세요.
Rust의 Result 타입을 제대로 처리하지 않고 `.unwrap()`을 남용하면 프로덕션에서 패닉이 발생합니다. `?` 연산자와 커스텀 에러 타입을 활용해 graceful한 에러 처리를 구현하세요.
핸들러 간 상태(DB 커넥션 풀 등)를 공유할 때 `App::app_data()`와 `web::Data<T>`를 사용하세요. Arc로 감싸면 여러 워커 스레드에서 안전하게 접근할 수 있습니다.