Node.js Express에서 Rust Axum으로의 전환은 단순한 언어 변경이 아닙니다. 메모리 안전성, 제로코스트 추상화, 그리고 async/await 기반의 고성능 비동기 처리까지 — API의 근본적인 체질 개선을 의미합니다.
왜 Rust + Axum인가?
최근 조사에 따르면, Rust 기반 웹 서버는 동일 하드웨어에서 Node.js 대비 약 10-15배의 처리량을 보여줍니다. 특히 Axum은 Tower 미들웨어 생태계와 완벽하게 통합되어, 프로덕션에서 요구하는 Rate Limiting, 인증, 로깅, 트레이싱을 체계적으로 구현할 수 있습니다.
프로젝트 구조 설계
src/
├── main.rs # 엔트리포인트
├── config.rs # 환경변수 관리
├── routes/
│ ├── mod.rs
│ ├── posts.rs # POST 관련 핸들러
│ └── auth.rs # 인증 핸들러
├── models/
│ ├── post.rs
│ └── user.rs
├── middleware/
│ ├── auth.rs # JWT 검증
│ └── logging.rs # 요청 로깅
└── db/
├── pool.rs # SQLx 커넥션 풀
└── migrations/ # 마이그레이션 파일
SQLx를 활용한 타입 안전 쿼리
SQLx의 query_as! 매크로는 컴파일 타임에 SQL 쿼리를 검증합니다. 이는 런타임 에러를 사전에 방지하며, IDE에서의 자동완성도 지원합니다.
let posts = sqlx::query_as!(
Post,
r#"SELECT id, title, slug, content, created_at
FROM posts
WHERE site_id = $1
ORDER BY created_at DESC
LIMIT $2 OFFSET $3"#,
site_id, limit, offset
).fetch_all(&pool).await?;
성능 벤치마크
실제 프로덕션 환경에서 동일한 API 엔드포인트를 비교한 결과:
- 응답 시간 P99: Node.js 45ms → Rust 3ms
- 메모리 사용량: Node.js 150MB → Rust 12MB
- 동시 접속 처리: Node.js 5,000 → Rust 50,000+ req/s
마무리
Rust + Axum 조합은 특히 고성능이 요구되는 API 서버에서 탁월한 선택입니다. 초기 러닝 커브가 있지만, 컴파일러가 잡아주는 버그와 메모리 안전성은 장기적으로 운영 비용을 크게 절감시킵니다.