2023. 3. 5. 14:48γμΈμ΄/Javascript(Node, TS...)
NodeJS λ°νμμμ μλ‘μ΄ νλ‘μΈμ€λ₯Ό μμ±νκ³ μΆλ€λ©΄
μΌλ°μ μΌλ‘ Child_process ν¨ν€μ§μ λ€μμ λ©μλλ€μ νμ©ν μ μλ€.
- Child_process.fork()
- Child_process.exec()
- Child_process.spawn()
μ¬κΈ°μμλ μ λ©μλλ€μ΄ μλνλ λ°©μμ λλͺ μ μμ€ν μ½λ€κ³Ό μ°κ΄ μ§μ΄ λΉκ΅νκ³ μ νλ€.
λ€μ΄κ°κΈ° μ μ...
μ΄ κΈμ μ΄ν΄νκΈ° μν΄μλ μμ€ν μ½κ³Ό μμ€ν μ½μ μ’ λ₯μΈ fork()μ exec()μ΄ λ¬΄μμΈμ§ μμμΌνλ€.
μ΄λ€μ λν΄ λ¨Όμ κ°λ¨νκ² μκ°νκ³ λμ΄κ°κ² λ€.
μμ€ν μ½
μμ€ν μ½μ΄λ μ μ λͺ¨λμμ μλνλ νλ‘μΈμ€λ€μ΄ μ΄μ체μ μ κΆνμ΄ νμν μμ μ μ΄μ체μ μ μμ²νκΈ° μν΄ νΈμΆλλ μΈν°νμ΄μ€λ₯Ό μλ―Ένλ€.
νμΌ μ μΆλ ₯μ΄λ νλ‘μΈμ€μ μμ± λ° μ€ν λ±μ μμ μ λν κΆνμ΄ νλ‘μΈμ€λ€μκ² μμ κ²½μ°
μ»΄ν¨ν°λ μΈλΆ 곡격μΌλ‘λΆν° λ§€μ° μ·¨μ½ν΄μ§κΈ° λλ¬Έμ,
ν΄λΉ μμ λ€μ λν κΆνμ μ΄μ체μ μκ² μμΌλ©° νλ‘μΈμ€λ€μ μ΄μ체μ μ μ΄λ₯Ό μμ²νλ λ°©μμΌλ‘ μλνλ€.
fork()
fork() λ νλ‘μΈμ€λ₯Ό μμ±νλ μμ€ν μ½λ‘, λΆλͺ¨ νλ‘μΈμ€λ₯Ό 볡μ¬νλ λ°©μμΌλ‘ μλνλ€.
fork() κ° νΈμΆλ μμ μ μ€ν 컨ν μ€νΈλ₯Ό μμ ν 볡μ¬νκΈ° λλ¬Έμ,
μμ νλ‘μΈμ€λ λΆλͺ¨ νλ‘μΈμ€ μ½λμ μμ μ§μ λΆν° μ€νλλ κ²μ΄ μλ fork() νΈμΆ μ΄νμ μ½λ νλ¦μ΄ μ€νλλ€.
fork() μ λ°ν κ°μ λΆλͺ¨μ μμμμ μλ‘ λ€λ₯Έλ°, λΆλͺ¨ νλ‘μΈμ€μμλ μμ νλ‘μΈμ€μ Idκ° λ°νλκ³ μμ νλ‘μΈμ€μμλ 0μ΄ λ°νλλ€.
λ°λΌμ fork() νΈμΆ μ΄ν if λΆκΈ°λ₯Ό ν΅ν΄ λ€λ₯Έ μ½λ νλ¦μ΄ μ€νλλλ‘ μ½λλ₯Ό ꡬμ±ν μ μλ€.
exec()
exec() λ fork()μλ λ¬λ¦¬ μλ‘μ΄ νλ‘μΈμ€λ₯Ό μμ±νλ μμ€ν μ½μ΄ μλλ€.
exec() μ΄ νΈμΆλλ©΄ κΈ°μ‘΄ νλ‘μΈμ€λ₯Ό μλ‘μ΄ νλ‘μΈμ€λ‘ μμ ν λ체νλ€. λ°λΌμ μλ‘μ΄ μ½λ νλ¦μ΄ μλνκΈ°λ νμ§λ§ κΈ°μ‘΄ νλ‘μΈμ€λ μμ ν μ¬λΌμ§κ² λλ€.
리λ μ€μμλ fork()μ exec()μ μ‘°ν©μ ν΅ν΄ μμ ꡬννκ³ μλ€.
Spawn λ©μλ
μ΄μ λ³Έλ‘ μΌλ‘ λμμμ, Child_process ν¨ν€μ§μ νλ‘μΈμ€ μμ± λ©μλλ€μ λ€μ¬λ€λ³΄μ.
NodeJS 곡μ λ¬Έμμ μμ±λ spawn λ©μλμ μ¬μ© μμλ λ€μκ³Ό κ°λ€.
const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
spawn λ©μλλ λͺ λ Ήμ΄μ μΈμλ€μ μ λ ₯ λ°κ³ μ΄λ₯Ό μ΄μ©νμ¬ μλ‘μ΄ νλ‘μΈμ€λ₯Ό μμ±νλ€.
ν΄λΉ λ©μλλ ChildProcess κ°μ²΄λ₯Ό λ°ννκ³ , μ΄ν νμ€ μ μΆλ ₯μ ν΅ν΄ λΆλͺ¨μ μμ κ° λ°μ΄ν° μ μ‘(IPC)μ΄ κ°λ₯νλ€.
μ΄ λ λ°μ΄ν°λ Streamμ ννλ₯Ό λκ² λλ€.
spawn λ©μλκ° μ€νλλ©΄ μ°¨λ‘λλ‘ fork(), exec() μμ€ν μ½μ΄ νΈμΆλκ³ , μΆκ°μ μΌλ‘ IPCλ₯Ό μν pipe() λ νΈμΆλλ€.
μ΄ λ execμΌλ‘ λͺ λ Ήμ΄λ₯Ό μ§μ μ€ννκΈ° λλ¬Έμ μμ κ΄μ¬νμ§ μλλ€.
Exec λ©μλ
곡μ λ¬Έμμ exec() λ©μλ μμλ λ€μκ³Ό κ°λ€.
const { exec } = require('node:child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});
exec() λ©μλλ exec() μμ€ν μ½κ³Ό λ¬λ¦¬, μλ‘μ΄ νλ‘μΈμ€λ₯Ό μμ±νλ€.
λͺ λ Ήμ΄λ₯Ό νλμ λ¬Έμμ΄μ λͺ¨λ λ΄μ νΈμΆνκ³ , μμκ³Ό λΆλͺ¨ κ°μ ν΅μ μ ν¨κ» μ λ¬λλ μ½λ°± ν¨μλ₯Ό ν΅ν΄ μ΄λ£¨μ΄μ§λ€.
spawn() λ©μλμ κΈ°λ₯ μ μ μ¬ν΄ 보μ΄λ μ΄λ° μ°¨μ΄κ° μ‘΄μ¬νλ μ΄μ κ° λκΉ?
spawn() vs exec()
λ λ©μλμ μ°¨μ΄λ ν¬κ² 2κ°μ§μ΄λ€.
- λͺ λ Ήμ΄ μ λ¬ λ°©μ
- λΆλͺ¨ μμ κ°μ ν΅μ ꡬν λ°©μ
첫λ²μ§Έ μ°¨μ΄μ μ΄μ λ λ°λ‘ μμ μ€ν μ 무μ΄λ€.
spawn()μ μμ μ€νμν€μ§ μμ§λ§ exec()μ μμ μ€νμν¨λ€.
ꡬ체μ μΌλ‘, exec() λ©μλλ λ΄λΆμ μΌλ‘ spawn() λ©μλλ₯Ό μ΄μ©νμ¬ μμ μ€νμν€κ³ ν΄λΉ μμμ λͺ λ Ήμ΄λ₯Ό μ€νμν€λ λ°©μμΌλ‘ μλνλ€.
μ΄λ‘ μΈν΄ exec() λ©μλμμλ μμμ μ 곡νλ κΈ°λ₯μ μ΄μ©μ΄ κ°λ₯νλ€. μμλ‘λ μμ νμ΄ν κΈ°λ₯μ΄ μλ€. (λͺ λ Ήμ΄ μ°κ²° κΈ°λ₯, pipe() μμ€ν μ½κ³Ό μμ ν λ€λ¦)
λ°λΌμ spawn() λ©μλμλ νλμ λͺ λ Ήμ΄λ§ μ λ¬ν μ μμΌλ, exec() λ©μλλ μ¬λ¬ λͺ λ Ήμ΄λ₯Ό μ°κ²°νμ¬ μ λ¬ν μ μλ€.
λλ²μ§Έ μ°¨μ΄μ μ΄μ λ νλ‘μΈμ€ κ° λ°μ΄ν° ν΅μ μ μ΄μ©λλ λ°©μμ μλ€.
spawn() λ©μλλ Streamμ μ΄μ©νλ€. μ΄μ μ€μκ°μΌλ‘ λ°μ΄ν°λ₯Ό μμ ν μ μμ΄μΌνκΈ° λλ¬Έμ μ΄λ²€νΈ λ±λ‘ λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°λλ€.
exec() λ©μλλ Bufferedμ μ΄μ©νλ€. μ¦, μμ νλ‘μΈμ€μ λ°μ΄ν°λ₯Ό 차곑차곑 μμ νλ²μ μ λ¬νκΈ° λλ¬Έμ νλμ μ½λ°±μμ λͺ¨λ μμ μ΄ κ°λ₯νλ€.
μ΄λ¬ν μ°¨μ΄ λλ¬Έμ λκ·λͺ¨ λ°μ΄ν°μ μ‘μμ μ΄ νμν λμλ Streamμ μ΄μ©νλ spawn() λ©μλκ° μ 리νλ€.
exec() λ©μλλ₯Ό νμ©νλ€λ©΄ λ°μ΄ν° μ²λ¦¬λ₯Ό μν μ€λ²ν€λκ° μ»€μ§κ³ , λ°μ΄ν°κ° λ무 컀μ§λ κ²½μ°μλ μμ μλ¬κ° λ°μνλ€.
Fork λ©μλ
곡μλ¬Έμμ fork() λ©μλ μμ λ λ€μκ³Ό κ°λ€.
if (process.argv[2] === 'child') {
setTimeout(() => {
console.log(`Hello from ${process.argv[2]}!`);
}, 1_000);
} else {
const { fork } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const child = fork(__filename, ['child'], { signal });
child.on('error', (err) => {
// This will be called with err being an AbortError if the controller aborts
});
controller.abort(); // Stops the child process
}
μ μμλ μ€μ€λ‘μ 볡μ¬λ³Έμ λ§λλ μμλ‘, μμ€ν μ½μ forkμ μ μ¬νκ² λμνμ§λ§ Child processμ fork() λ©μλλ λ€λ₯Έ js νμΌμ λν΄μλ μλνλ€. μμλ μλμ κ°λ€.
// parent.js
const { fork } = require('child_process');
const path = require('path');
const child = fork(path.join(__dirname, 'child.js'));
child.on('message', (msg) => {
console.log(`Parent process received message: ${msg}`);
});
child.send('Hello from parent process!');
// child.js
process.on('message', (msg) => {
console.log(`Child process received message: ${msg}`);
process.send('Hello from child process!');
});
μ μμλ₯Ό ν΅ν΄ μ μ μλ μ μ μ°μ fork() λ©μλλ μ€μ§ NodeJS (jsνμΌ)μ λν΄μλ§ μλνλ€λ κ²μ΄λ€.
NodeJS 곡μλ¬Έμμμλ fork() λ©μλλ spawn() λ©μλμ μ€νμ μΌμ΄μ€(Node λͺ λ Ήμ΄ μν)λΌκ³ μΈκΈνκ³ μλ€.
The child_process.fork() method is a special case of child_process.spawn() used specifically to spawn new Node.js processes.
λν μμ νλ‘μΈμ€(child.js)μμ νΉλ³ν μ€μ μμ΄ process κ°μ²΄μ μ κ·Όνμ¬ λΆλͺ¨ νλ‘μΈμ€μ ν΅μ μ μννλλ°, μ΄λ fork() λ©μλλ₯Ό ν΅ν΄ μ€νλ νλ‘μΈμ€λ κΈ°λ³Έμ μΌλ‘ λΉνΈμΈ IPC ꡬμ±μ ν¬ν¨νκ³ μκΈ° λλ¬Έμ΄λ€.
λ°λΌμ fork() λ©μλλ₯Ό νμ©νλ©΄ Node νλ‘μΈμ€ κ°μ Stream ν΅μ μ μ½κ² ꡬνν μ μλ€.
μ°Έμ‘°
https://nodejs.org/api/child_process.html#child-process
https://stackoverflow.com/questions/48698234/node-js-spawn-vs-execute
https://stackoverflow.com/questions/17861362/node-js-child-process-difference-between-spawn-fork
'μΈμ΄ > Javascript(Node, TS...)' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Interface vs Abstract Class (in Typescript) (0) | 2023.03.19 |
---|---|
Interface in TS (vs Java) (0) | 2023.03.19 |
TypeScript νμ : any, unknown, never (0) | 2023.03.09 |