코어 개발이 한창 진행되던 중, 이제 러스트로 만든 코드를 실제로 쓸 수 있는 환경을 만들어야 했다.
목표는 Node.js에서 러스트 코드를 실행하는 것이었고, 가장 먼저 선택한 게 NAPI-RS였다.
사실 선택의 여지가 없었다.
러스트로 Node.js 네이티브 모듈을 만드는 방법 중 NAPI-RS가 사실상 유일한 현실적인 선택지였다.
Neon 같은 대안도 있긴 하지만 이미 비주류가 되어버린 상태였고, NAPI-RS가 표준처럼 자리잡은 상황이었다.
그래서 코어 개발이 진행 중이던 11월 22일, 가장 먼저 NAPI-RS 환경 설정을 시작했다.
NAPI-RS는 세팅을 도와주는 napi new 명령어를 제공한다.
이 명령어를 실행하면 인터랙티브 메뉴가 나타나서 프로젝트 이름, 타겟 플랫폼, 라이선스 등을 물어본다.
하지만 우리는 이미 모노레포 구조로 프로젝트를 시작했기 때문에, napi new로 새 프로젝트를 만드는 것보다는 기존 구조에 맞춰서 설정을 추가하는 방향으로 갔다.
초기 커밋을 보면 packages/hwpjs 폴더에 NAPI-RS 프로젝트가 생성되었고, 기본적인 설정 파일들이 추가되었다:
Cargo.toml: 러스트 프로젝트 설정package.json: Node.js 패키지 설정src/lib.rs: 러스트 바인딩 코드build.rs: 빌드 스크립트.github/workflows/CI.yml: GitHub Actions CI 설정NAPI-RS는 여러 플랫폼을 지원하지만, 실제로 빌드하려면 각 플랫폼별로 별도의 바이너리가 필요하다.
초기 설정에서는 윈도우와 맥 두 환경만 지원하기로 했다:
x86_64-pc-windows-msvc: 윈도우 64비트x86_64-apple-darwin: 맥 인텔aarch64-apple-darwin: 맥 애플 실리콘리눅스는 나중에 추가할 계획이었지만, 일단은 내가 개발할 수 있는 환경부터 확보하는 게 우선이었다.
NAPI-RS의 기본 가이드는 GitHub Actions를 통한 CI/CD를 전제로 하고 있다.
운영체제별로 크로스 컴파일이 어렵기 때문에, 각 플랫폼에서 직접 빌드하는 게 가장 확실한 방법이기 때문이다.
하지만 가난한 개발자는 GitHub Actions로 사치를 부릴 생각이 없었다.
GitHub Actions는 무료 플랜이 있긴 하지만, 빌드 시간이 길어지면 제한이 걸리고, 여러 플랫폼을 빌드하려면 시간도 오래 걸린다.
그리고 사실 그냥 비용 내기 싫었다.
그래서 로컬에서 빌드하는 게 당연한 선택이었다.
하지만 이게 생각보다 삽질이었다.
맥에서 윈도우 빌드는 cargo-xwin을 써서 잘 되더라.
예전에 npai-rs 2 일 떄는 cargo-xwin으로 하다가 실패해서 그냥 윈도우에서 빌드한 기억이 있는데, 그떄 이후로 개선이 된건지 내가 잘못 한건지 잘 모르겠지만, 그 때의 나를 소환해서 원인 분석할 자신이 없으므로 지금은 잘 되는 문제에 대해 크게 고민하지 않기로 했다.
리눅스는 그냥 빌드 될 줄 알았다. 맥도 Unix 기반이고 리눅스랑 크게 차이가 없어서..
근데 실제 빌드 해보니 안되고, 이리저리 검색해보니 도커를 권장하고 있었다. 도커 외에 기타 빠르다는 툴도 여러가지 있었는데 해보니 잘 안되서 포기.
결국 선택한 게 Docker였다.
Dockerfile을 만들고, 러스트 툴체인을 설치하고, 빌드 스크립트를 작성하고...
생각보다 간단할 줄 알았는데 또 삽질이었다.
먼저 Docker 이미지 크기 문제가 있었다.
러스트 툴체인만 설치해도 이미지가 엄청 커졌다.
멀티 스테이지 빌드를 써서 최적화를 해봤지만, 여전히 크긴 했다.
그리고 빌드 시간도 문제였다.
Docker 컨테이너 안에서 빌드하니까 로컬보다 훨씬 느렸다.
캐시를 활용해도 여전히 느렸다.
하지만 일단 작동은 했다.
리눅스용 바이너리도 빌드할 수 있게 됐고, 나중에 최적화는 천천히 하기로 했다.
결국 로컬 빌드를 위한 삽질을 다 끝내고 나니,
각 플랫폼별로 바이너리를 빌드할 수 있게 됐다.
그래도 가난한 개발자는 삽질을 선택했다.
비용을 내기 싫었으니까.(하지만 알고 보면 가난한 개발자가 아니라 하는 노력에 비해 지능이 떨어져서 고생만 하는 바보였다)
머리가 나쁘면 몸이 고생을 한다.
하지만 일단 빌드가 성공하고 나니, 러스트 코드를 Node.js에서 호출할 수 있는 기본 틀은 완성되었다.
NAPI-RS로 Node.js 환경 설정을 가장 먼저 시작했고, 기본적인 빌드 환경을 구축했다.