Skip to content

Commit 4e022be

Browse files
committed
docs(n-api): Node-API 문서 작성
1 parent 713ed4b commit 4e022be

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

_posts/js/n-api/addon.webp

27.7 KB
Loading

_posts/js/n-api/cover.webp

16.1 KB
Loading

_posts/js/n-api/docs.mdx

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
---
2+
title: 'N-API(Node-API) 얕게 알아보기(feat. Rust)'
3+
description: 'N-API를 이해하고 Node.js Addon에 Rust를 붙이는 방법을 알아보자.'
4+
tags: ['nodejs', 'addon', 'node-api', 'rust']
5+
coverImage: 'cover.webp'
6+
date: '2025-03-16T12:37:30.218Z'
7+
---
8+
9+
![cover](cover.webp 'cover')
10+
11+
> 이미지 출처: https://medium.com/ai-innovation/a-guide-for-javascript-developers-to-build-c-add-ons-with-node-addon-api-28c84a0c0cb1
12+
13+
최근 Rust를 공부 하면서 Rust 컴파일 파일이 Node.js Addon에 어떻게 연결되는지 궁금했다. 따라서 이번 기회에 N-API에 대해 "얕게" 알아보려고 한다.
14+
15+
이 글은 다음과 같은 내용을 다룬다.
16+
17+
1. Node-API란?
18+
2. Node-API의 장점
19+
3. Rust와 N-API를 사용한 Node.js Addon 개발
20+
21+
[N-API는 2021년 Node-API로 이름이 변경](https://medium.com/@nodejs/renaming-n-api-to-node-api-27aa8ca30ed8)되었다. 따라서 앞으로는 Node-API로 표기하겠다.
22+
23+
## Node-API란?
24+
25+
![node-api flow](flow.webp 'l')
26+
27+
Node-API는 [Node.js v8에서 Stable로 소개](https://nodejs.org/docs/latest-v8.x/api/n-api.html#n_api_n_api)되었다.
28+
29+
Node-API는 Node.js 네이티브 애드온(C/C++)을 개발하기 위한 API이다. 기본 JavaScript 런타임(예: V8)과 독립적이며 Node.js 자체의 일부로 유지 관리되고 있다.
30+
31+
이 API는 Node.js의 모든 버전에서 [ABI 안정적](https://nodejs.org/en/learn/modules/abi-stability)이다.
32+
33+
> ABI(Application Binary Interface): 응용 프로그램이 컴파일된 이후에도 호환성을 유지하기 위한 인터페이스.
34+
35+
기본 JavaScript 엔진의 변경 사항으로부터 애드온을 보호하고 특정 버전에 대해 컴파일된 모듈을 재컴파일 없이 이후 버전의 Node.js에서 실행할 수 있도록 하는 것이 목적이다.
36+
37+
## Node-API의 장점
38+
39+
![addon chart](addon.webp 'l')
40+
41+
Node-API가 탄생한 배경을 이해하면 Node-API의 장점을 이해할 수 있다.
42+
43+
Node.js는 JavaScript를 브라우저 외부에서 실행시킬 수 있는 앱이다. 따라서 다양한 기능을 충족시키기 위해 C/C++ 네이티브 애드온을 통해 Node.js를 확장시키고자 하는 노력을 기울여 왔다.
44+
45+
이러한 노력은 유지보수의 어려움이 있었다. 내부적으로 의존하는 V8 엔진 및 Libuv 등은 지속적으로 업데이트되며 새로운 기능이 추가되거나 변경된다. 이러한 변화는 C/C++로 개발된 애드온의 ABI 안정성을 보장하기 어렵게 만들었다.
46+
47+
> 애드온 C++에서 V8에 직접 접근한 경우 Node.js는 안정성을 보장할 방법이 없기 때문.
48+
49+
또한 C/C++ 애드온을 개발하고자 하는 개발자는 인터페이스 가이드를 받지 못하기 때문에 숙련된 개발자가 아니면 애드온을 적용하기가 어려웠다.
50+
51+
이러한 문제를 해결하기 위해 Node-API가 등장하게 되었다.
52+
53+
### 1. ABI 안정성
54+
55+
Node.js의 업데이트로 인해 애드온이 깨지는 문제를 해결한다.
56+
57+
### 2. 개발자 친화적
58+
59+
Node-API는 C/C++ 개발자가 아니더라도 사용할 수 있도록 설계되었다.
60+
61+
주요 인터페이스를 제공하고 이를 통해 Node.js와 상호작용할 수 있도록 한다.
62+
63+
### 3. 최적화
64+
65+
기존 C/C++ 애드온은 GC 메모리 관리를 직접해야 했으며 멀티 스레딩도 직접 구현해야 했다. 이는 애드온 개발자에게 추가적인 부담을 준다.
66+
67+
## Rust와 Node-API를 사용한 Node.js Addon 개발
68+
69+
바로 실전으로 이해해보자.
70+
71+
Rust로 컴파일된 목적 파일을 Node.js Addon에 연결하여 JavaScript 파일에서 사용하는 과정을 다루고자 한다.
72+
73+
### 1. Node-gyp 설치
74+
75+
```sh
76+
$ npm i -g node-gyp
77+
```
78+
79+
Node-API 에서 제공하는 헤더, C 코드 등이 포함되어 있는 [node-gyp](https://github.com/nodejs/node-gyp)를 설치한다.
80+
81+
### 2. binding.gyp 파일 생성
82+
83+
```json
84+
// binding.gyp
85+
{
86+
"targets": [
87+
{
88+
"target_name": "mycalc_addon",
89+
"sources": ["mycalc_addon.c"],
90+
"libraries": [
91+
"/PATH/libmycalc.so"// 동적 로딩을 사용하기 위해 추가
92+
],
93+
}
94+
]
95+
}
96+
```
97+
98+
### 3. Rust 파일 목적 파일로 컴파일
99+
100+
```rs
101+
// mycalc.rs
102+
// rust_mul 이라는 곱셈 함수를 export 할 예정.
103+
#[no_mangle]
104+
pub extern "C" fn rust_mul(a: isize, b: isize) -> isize {
105+
a * b
106+
}
107+
```
108+
109+
```sh
110+
# compile
111+
$ rustc --crate-type="dylib" mycalc.rs -o libmycalc.so
112+
```
113+
114+
### 4. Addon C 파일 작성
115+
116+
```c
117+
// mycalc_addon.c// node_api를 가져옴(node-gyp에 있을 것이므로 바로 사용한다)
118+
#include <node_api.h>
119+
#include <stdio.h>
120+
// Rust 파일의 함수를 C로 가져온다(so 파일에 있을 예정).
121+
int rust_mul(int a, int b);
122+
// 두 숫자를 더하는 C 함수
123+
napi_value Mul(napi_env env, napi_callback_info info)
124+
{
125+
napi_status status;
126+
// 인자 개수와 인자 배열
127+
size_t argc = 2;
128+
napi_value argv[2];
129+
status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
130+
if (status != napi_ok)
131+
{
132+
napi_throw_error(env, NULL, "Failed to parse arguments");
133+
return NULL;
134+
}
135+
// 인자가 2개인지 확인
136+
if (argc < 2)
137+
{
138+
napi_throw_error(env, NULL, "Wrong number of arguments");
139+
return NULL;
140+
}
141+
// 인자를 double로 변환
142+
double value1, value2;
143+
status = napi_get_value_double(env, argv[0], &value1);
144+
if (status != napi_ok)
145+
{
146+
napi_throw_error(env, NULL, "Invalid argument 1");
147+
return NULL;
148+
}
149+
status = napi_get_value_double(env, argv[1], &value2);
150+
if (status != napi_ok)
151+
{
152+
napi_throw_error(env, NULL, "Invalid argument 2");
153+
return NULL;
154+
}
155+
// rust 모듈을 활용해 결과 계산 //////////////////////////////////////////////
156+
double result = rust_mul(value1, value2);
157+
// 결과를 napi_value로 변환
158+
napi_value result_value;
159+
status = napi_create_double(env, result, &result_value);
160+
if (status != napi_ok)
161+
{
162+
napi_throw_error(env, NULL, "Failed to create result value");
163+
return NULL;
164+
}
165+
return result_value;
166+
}
167+
// 모듈 초기화 함수
168+
napi_value Init(napi_env env, napi_value exports)
169+
{
170+
napi_status status;
171+
// 함수 등록
172+
napi_value fn;
173+
status = napi_create_function(env, NULL, 0, Mul, NULL, &fn);
174+
if (status != napi_ok)
175+
{
176+
napi_throw_error(env, NULL, "Failed to create function");
177+
return NULL;
178+
}
179+
// exports 객체에 함수 추가
180+
status = napi_set_named_property(env, exports, "mul", fn);
181+
if (status != napi_ok)
182+
{
183+
napi_throw_error(env, NULL, "Failed to set named property");
184+
return NULL;
185+
}
186+
return exports;
187+
}
188+
// 모듈 등록
189+
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
190+
```
191+
192+
### 5. Addon 빌드
193+
194+
```sh
195+
$ node-gyp configure && node-gyp build
196+
```
197+
198+
### 6. JavaScript 파일에서 사용하기
199+
200+
```js
201+
// index.js
202+
const addon = require("./build/Release/mycalc_addon");
203+
console.log(addon.mul(3, 5));// 15 출력
204+
```
205+
206+
## 마치며
207+
208+
Node-API를 이해하는 과정에서 애드온에 대한 이해도가 높아졌다.
209+
210+
Node.js의 내부에 한층 더 깊게 파고들어간 것 같아 뿌듯하다.
211+
212+
## 참고
213+
214+
- https://nodejs.org/docs/latest/api/addons.html
215+
- https://medium.com/ai-innovation/a-guide-for-javascript-developers-to-build-c-add-ons-with-node-addon-api-28c84a0c0cb1

_posts/js/n-api/flow.webp

21.7 KB
Loading

0 commit comments

Comments
 (0)