Rust로 Node.js Native Addon 만들어보기
문제 상황
이미지 처리 API에서 대량의 메타데이터를 파싱하고 변환하는 작업이 병목이었다. JavaScript로 처리하니 CPU 사용률은 높은데 처리 속도가 느렸다. 특히 10MB 이상의 JSON 파일을 다룰 때 응답 시간이 3초를 넘었다.
Rust + napi-rs 선택
C++로 작성하는 것도 고려했지만, napi-rs를 사용하면 Rust의 안전성과 성능을 모두 가져갈 수 있었다. 메모리 안정성이 컴파일 타임에 보장되는 점이 매력적이었다.
use napi::bindgen_prelude::*;
use serde_json::{Value, from_str};
#[napi]
pub fn parse_and_transform(json_str: String) -> Result<String> {
let data: Value = from_str(&json_str)
.map_err(|e| Error::from_reason(e.to_string()))?;
// 변환 로직
let transformed = transform_data(data);
Ok(serde_json::to_string(&transformed)
.map_err(|e| Error::from_reason(e.to_string()))?)
}
빌드 및 통합
Cargo.toml에 napi 의존성을 추가하고, package.json에 빌드 스크립트를 설정했다.
{
"scripts": {
"build:native": "napi build --platform --release"
}
}
Node.js에서는 일반 모듈처럼 불러서 사용할 수 있다.
const { parseAndTransform } = require('./index.node');
const result = parseAndTransform(largeJsonString);
성과
- 10MB JSON 파싱: 3.2초 → 0.9초
- CPU 사용률은 비슷하지만 처리 시간 70% 단축
- 메모리 사용량도 약간 감소
CI/CD 파이프라인에 각 플랫폼별 빌드를 추가하는 작업이 필요했지만, 성능 개선 효과가 확실해서 만족스러웠다. Rust 학습 곡선이 있지만, 성능이 중요한 부분에는 충분히 투자할 가치가 있다고 판단했다.