====== π’ Node.js ======
Node.jsλ JavaScriptλ₯Ό μ¬μ©νμ¬ μΉ μλ²λ λ€μν λ€νΈμν¬ μ ν리μΌμ΄μ
μ λ§λ€ μ μκ² ν΄μ£Όλ νΉλ³ν λꡬμ
λλ€. μΉ λΈλΌμ°μ λ°μμλ JavaScript μ½λλ₯Ό μ€νν μ μλλ‘ ν΄μ£Όμ΄, μλ² κ°λ°μ λ§€μ° μ μ©νκ² μ¬μ©λ©λλ€.
===== 1. μ μ =====
**Node.js**λ Chromeμ V8 JavaScript μμ§μ κΈ°λ°μΌλ‘ λ§λ€μ΄μ§ **μλ² μ¬μ΄λ JavaScript λ°νμ νκ²½**μ
λλ€. μ¬κΈ°μ ''V8 μμ§''μ Google Chrome μΉ λΈλΌμ°μ κ° JavaScript μ½λλ₯Ό λ§€μ° λΉ λ₯΄κ² μ€νν μ μλλ‘ ν΄μ£Όλ ν΅μ¬ κΈ°μ μ
λλ€. Node.jsλ μ΄ κ°λ ₯ν μμ§μ νμ©νμ¬, μΉ λΈλΌμ°μ μμ΄λ μ»΄ν¨ν°μμ JavaScript μ½λλ₯Ό μ§μ μ€νν μ μκ² ν©λλ€.
Node.jsλ **μ΄λ²€νΈ κΈ°λ°(Event-driven)**, **λ
ΌλΈλ‘νΉ I/O(Non-blocking I/O)** λͺ¨λΈμ μ¬μ©νμ¬ κ°λ²Όμ°λ©΄μλ ν¨μ¨μ μΈ μ ν리μΌμ΄μ
μ κ°λ°ν μ μλλ‘ μ€κ³λμμ΅λλ€. μ΄λ λμμ λ§μ μ¬μ©μμ μμ²μ λΉ λ₯΄κ³ μμ μ μΌλ‘ μ²λ¦¬ν΄μΌ νλ μΉ μλΉμ€μ νΉν μ 리ν©λλ€.
===== 2. μ£Όμ νΉμ§ =====
----
==== 1) μ΄λ²€νΈ κΈ°λ° (Event-driven) ====
Node.jsλ 'μ΄λ²€νΈ'κ° λ°μνλ©΄ 미리 μ μλ 'μ½λ°± ν¨μ'λ₯Ό μ€ννλ λ°©μμΌλ‘ λμν©λλ€. μλ₯Ό λ€μ΄, μ¬μ©μκ° μΉ νμ΄μ§μ μ μνκ±°λ νμΌ μ½κΈ°κ° μλ£λλ©΄, Node.jsλ ν΄λΉ μ΄λ²€νΈλ₯Ό κ°μ§νκ³ λ―Έλ¦¬ μ½μλ μμ
μ μνν©λλ€.
* **λμ μ리**: λ§μΉ λ μ€ν λμμ μ£Όλ¬Έμ΄ λ€μ΄μ€λ©΄ μ리μ¬κ° μ리 μ€μλ λ€μ μ£Όλ¬Έμ λ¨Όμ λ°κ³ , μλ¦¬κ° μμ±λλ©΄ "μ΄λ²€νΈ"λ₯Ό λ°μμμΌ μλΉνλ κ²κ³Ό λΉμ·ν©λλ€. νλμ μμ²μ΄ λλ λκΉμ§ κΈ°λ€λ¦¬μ§ μκ³ , μ¬λ¬ μμ²μ λμμ μ²λ¦¬ν μ€λΉλ₯Ό ν©λλ€.
* **μ₯μ **: λΉλκΈ° νλ‘κ·Έλλ°μ μ§μνμ¬ λμμ λ§μ μμ²μ ν¨μ¨μ μΌλ‘ μ²λ¦¬ν μ μμ΅λλ€. μ΄λ μλ²μ μλ΅ μλλ₯Ό ν₯μμν€κ³ , λ λ§μ μ¬μ©μλ₯Ό μμ©ν μ μκ² ν©λλ€.
----
==== 2) λ
ΌλΈλ‘νΉ I/O (Non-blocking I/O) ====
'I/O'λ 'Input/Output'μ μ½μλ‘, νμΌ μμ€ν
μ κ·Ό(νμΌ μ½κΈ°/μ°κΈ°), λ°μ΄ν°λ² μ΄μ€ 쿼리, λ€νΈμν¬ μμ²(λ€λ₯Έ μλ²μ ν΅μ )κ³Ό κ°μ μμ
μ μλ―Έν©λλ€. 'λΈλ‘νΉ(Blocking)' λ°©μμ μ΄λ¬ν I/O μμ
μ΄ μλ£λ λκΉμ§ λ€λ₯Έ μμ
μ λ©μΆκ³ κΈ°λ€λ¦¬λ κ²μ λ§ν©λλ€.
* **λμ μ리**: Node.jsλ λ
ΌλΈλ‘νΉ λ°©μμΌλ‘ μλνμ¬ I/O μμ
μ΄ μ§ν μ€μΌ λ λ€λ₯Έ μμ
μ κ³μ μ²λ¦¬ν©λλ€. μλ₯Ό λ€μ΄, μλ²κ° λ°μ΄ν°λ² μ΄μ€μμ λ°μ΄ν°λ₯Ό μμ²νλ©΄, κ·Έ λ°μ΄ν°κ° λμ°©ν λκΉμ§ κΈ°λ€λ¦¬μ§ μκ³ λ€λ₯Έ μ¬μ©μμ μμ²μ μ²λ¦¬νκ±°λ λ€λ₯Έ μ½λλ₯Ό μ€νν©λλ€. λ°μ΄ν°κ° μ€λΉλλ©΄ κ·Έλ λ€μ ν΄λΉ μμ²μ μ²λ¦¬ν©λλ€.
* **μ₯μ **: νΉμ μμ
μ΄ μ§μ°λλλΌλ μ 체 μλ²μ λμμ΄ λ©μΆμ§ μμ λμ μ±λ₯κ³Ό νμ₯μ±μ μ 곡ν©λλ€. λκ·λͺ¨ λμ μ μ νκ²½μμ νΉν μ 리ν©λλ€.
----
==== 3) ν¬λ‘μ€ νλ«νΌ (Cross-platform) ====
Node.jsλ νΉμ μ΄μ체μ μ μ’
μλμ§ μκ³ λ€μν νκ²½μμ μ€νλ μ μμ΅λλ€.
* **μ₯μ **: κ°λ°μλ Windows, macOS, Linux λ± μ΄λ€ μ΄μ체μ μμλ λμΌν Node.js μ½λλ₯Ό μμ±νκ³ μ€νν μ μμ΅λλ€. μ΄λ κ°λ° λ° λ°°ν¬ κ³Όμ μ κ°μννκ³ , νμ κ°μ νμ
μ μ©μ΄νκ² ν©λλ€.
===== 3. 기본 ꡬ쑰 =====
Node.js μ ν리μΌμ΄μ
μ ν΅μ¬μ μΈ λμ λ°©μμ μ΄ν΄νκΈ° μν λ κ°μ§ μμ λ₯Ό μ΄ν΄λ΄
λλ€.
----
==== 1) κ°λ¨ν HTTP μλ² μμ ====
μΉ μλ²λ ν΄λΌμ΄μΈνΈ(μΉ λΈλΌμ°μ λ±)μ μμ²μ λ°μ μλ΅μ 보λ΄μ£Όλ μν μ ν©λλ€. λ€μ μ½λλ Node.jsλ‘ κ°μ₯ κΈ°λ³Έμ μΈ μΉ μλ²λ₯Ό λ§λλ λ°©λ²μ 보μ¬μ€λλ€.
const http = require('http'); // 1. Node.jsμ λ΄μ₯λ 'http' λͺ¨λμ κ°μ Έμ΅λλ€.
// μ΄ λͺ¨λμ μΉ μλ²λ₯Ό λ§λ€κ³ HTTP μμ²μ μ²λ¦¬νλ κΈ°λ₯μ μ 곡ν©λλ€.
const server = http.createServer((req, res) => { // 2. 'http' λͺ¨λμ μ¬μ©νμ¬ μλ²λ₯Ό μμ±ν©λλ€.
// μ΄ ν¨μλ ν΄λΌμ΄μΈνΈ μμ²μ΄ μ¬ λλ§λ€ μ€νλ©λλ€.
// 'req'λ μμ²(Request) μ 보, 'res'λ μλ΅(Response) κ°μ²΄μ
λλ€.
res.writeHead(200, { 'Content-Type': 'text/plain' }); // 3. μλ΅ ν€λλ₯Ό μ€μ ν©λλ€.
// '200'μ μ±κ³΅μ μΈ μλ΅μ μλ―Ένκ³ ,
// 'Content-Type'μ ν΄λΌμ΄μΈνΈμκ² λ³΄λ΄λ λ°μ΄ν°μ μ’
λ₯λ₯Ό μλ €μ€λλ€.
res.end('Hello World\n'); // 4. ν΄λΌμ΄μΈνΈμκ² 'Hello World'λΌλ ν
μ€νΈλ₯Ό μλ΅μΌλ‘ 보λ
λλ€.
// 'res.end()'λ μλ΅ μ μ‘μ μλ£νκ³ μ°κ²°μ λ«μ΅λλ€.
});
server.listen(3000, () => { // 5. μλ²λ₯Ό 3000λ² ν¬νΈμμ 'μμ λκΈ°' μνλ‘ λ§λλλ€.
// μ΄μ μΉ λΈλΌμ°μ μμ 'http://localhost:3000'μΌλ‘ μ μνλ©΄
// μμμ μ μν 'Hello World' μλ΅μ λ°μ μ μμ΅λλ€.
console.log('μλ²κ° ν¬νΈ 3000μμ μ€ν μ€μ
λλ€.'); // 6. μλ²κ° μ±κ³΅μ μΌλ‘ μμλλ©΄ μ½μμ λ©μμ§λ₯Ό μΆλ ₯ν©λλ€.
});
* **μ€λͺ
**: μ΄ μ½λλ 3000λ² ν¬νΈμμ μμ²μ κΈ°λ€λ¦¬λ κ°λ¨ν μΉ μλ²λ₯Ό λ§λλλ€. ν΄λΌμ΄μΈνΈκ° μ΄ μλ²μ μ μνλ©΄ "Hello World"λΌλ ν
μ€νΈλ₯Ό μλ΅μΌλ‘ 보λ
λλ€. μ΄λ Node.jsκ° μ΄λ»κ² μΉ μμ²μ λ°μ μ²λ¦¬νκ³ μλ΅μ 보λ΄λμ§ λ³΄μ¬μ£Όλ κ°μ₯ κΈ°λ³Έμ μΈ μμμ
λλ€.
----
==== 2) λͺ¨λ μμ€ν
====
μ ν리μΌμ΄μ
μ κ·λͺ¨κ° 컀μ§μλ‘ μ½λλ₯Ό μ¬λ¬ νμΌλ‘ λλμ΄ κ΄λ¦¬νλ κ²μ΄ μ€μν΄μ§λλ€. Node.jsλ 'λͺ¨λ μμ€ν
'μ ν΅ν΄ μ΄λ¬ν μ½λ λΆν λ° μ¬μ¬μ©μ κ°λ₯νκ² ν©λλ€.
* **νμμ±**: μ½λλ₯Ό λͺ¨λλ‘ λλλ©΄ κ° λͺ¨λμ΄ νΉμ κΈ°λ₯λ§μ λ΄λΉνκ² λμ΄ μ½λλ₯Ό μ΄ν΄νκ³ μ μ§λ³΄μνκΈ° μ¬μμ§λλ€. λν, λ€λ₯Έ νλ‘μ νΈμμλ ν΄λΉ λͺ¨λμ μ¬μ¬μ©ν μ μμ΄ κ°λ° ν¨μ¨μ±μ΄ λμμ§λλ€.
* **λμ μ리**:
* ''module.exports'': λ€λ₯Έ νμΌμμ μ¬μ©ν μ μλλ‘ νΉμ κ°(λ³μ, ν¨μ, κ°μ²΄ λ±)μ λ΄λ³΄λΌ λ μ¬μ©ν©λλ€.
* ''require()'': λ€λ₯Έ νμΌμ μλ λͺ¨λμ νμ¬ νμΌλ‘ κ°μ Έμ¬ λ μ¬μ©ν©λλ€.
// math.js νμΌ (λͺ¨λ λ΄λ³΄λ΄κΈ°)
// μ΄ νμΌμ λ§μ
κ³Ό λΊμ
κΈ°λ₯μ μ 곡νλ λͺ¨λμ
λλ€.
module.exports = { // 'module.exports'λ₯Ό μ¬μ©νμ¬ 'add'μ 'subtract' ν¨μλ₯Ό μΈλΆλ‘ λ΄λ³΄λ
λλ€.
add: (a, b) => a + b,
subtract: (a, b) => a - b
};
// app.js νμΌ (λͺ¨λ κ°μ Έμ€κΈ° λ° μ¬μ©)
// μ΄ νμΌμ μμμ λ§λ 'math.js' λͺ¨λμ κ°μ Έμ μ¬μ©ν©λλ€.
const math = require('./math'); // './math'λ νμ¬ λλ ν 리μ μλ 'math.js' νμΌμ μλ―Έν©λλ€.
// 'require()' ν¨μλ₯Ό μ¬μ©νμ¬ 'math' λ³μμ λͺ¨λμ΄ λ΄λ³΄λΈ κ°μ²΄λ₯Ό ν λΉν©λλ€.
console.log(math.add(5, 3)); // 8 // 'math' κ°μ²΄μ 'add' ν¨μλ₯Ό νΈμΆνμ¬ λ§μ
μ μνν©λλ€.
===== 4. ν¨ν€μ§ κ΄λ¦¬ =====
Node.js μνκ³μμ κ°λ°μ ν¨μ¨μ μΌλ‘ νκΈ° μν΄μλ λ€λ₯Έ κ°λ°μλ€μ΄ λ§λ μ μ©ν μ½λ λ¬Άμ(ν¨ν€μ§ λλ λΌμ΄λΈλ¬λ¦¬)μ κ°μ Έμ μ¬μ©νλ κ²μ΄ μΌλ°μ μ
λλ€.
----
==== 1) npm (Node Package Manager) ====
''npm''μ Node.jsμ κΈ°λ³Έ **ν¨ν€μ§ κ΄λ¦¬μ**μ
λλ€. μ μΈκ³ κ°λ°μλ€μ΄ 곡μ νλ μλ§μ Node.js ν¨ν€μ§λ€μ μ½κ² μ€μΉνκ³ κ΄λ¦¬ν μ μλλ‘ λμμ€λλ€.
* **μ£Όμ κΈ°λ₯**:
* **ν¨ν€μ§ μ€μΉ**: νμν λΌμ΄λΈλ¬λ¦¬λ₯Ό λͺ
λ Ή ν μ€λ‘ μ½κ² μ€μΉν μ μμ΅λλ€ (μ: ''npm install express'').
* **μμ‘΄μ± κ΄λ¦¬**: νλ‘μ νΈκ° μ΄λ€ ν¨ν€μ§λ€μ μ¬μ©νλμ§ κΈ°λ‘νκ³ , ν΄λΉ ν¨ν€μ§λ€μ΄ μ λλ‘ μ€μΉλλλ‘ κ΄λ¦¬ν©λλ€.
* **μ€ν¬λ¦½νΈ μ€ν**: κ°λ°, ν
μ€νΈ, λ°°ν¬ λ± νλ‘μ νΈμμ μμ£Ό μ¬μ©νλ λͺ
λ Ήλ€μ 미리 μ μν΄λκ³ κ°νΈνκ² μ€νν μ μμ΅λλ€.
----
==== 2) package.json μμ ====
''package.json'' νμΌμ Node.js νλ‘μ νΈμ **μ€λͺ
μ**μ κ°μ΅λλ€. νλ‘μ νΈμ μ΄λ¦, λ²μ , μ€λͺ
, μ€ν μ€ν¬λ¦½νΈ, κ·Έλ¦¬κ³ μ΄λ€ μΈλΆ ν¨ν€μ§(μμ‘΄μ±)λ₯Ό μ¬μ©νλμ§ λ±μ μ 보λ₯Ό λ΄κ³ μμ΅λλ€.
{
"name": "my-project", // νλ‘μ νΈμ μ΄λ¦
"version": "1.0.0", // νλ‘μ νΈμ νμ¬ λ²μ
"description": "νλ‘μ νΈ μ€λͺ
", // νλ‘μ νΈμ λν κ°λ¨ν μ€λͺ
"main": "index.js", // μ΄ νλ‘μ νΈμ μμμ (λ©μΈ νμΌ)μ μ§μ ν©λλ€.
"scripts": { // μμ£Ό μ¬μ©νλ λͺ
λ Ήμ΄λ₯Ό μ μν©λλ€.
"start": "node index.js", // 'npm start'λ₯Ό μ
λ ₯νλ©΄ 'node index.js'κ° μ€νλ©λλ€.
"dev": "nodemon index.js", // 'npm run dev'λ₯Ό μ
λ ₯νλ©΄ 'nodemon index.js'κ° μ€νλ©λλ€.
"test": "jest" // 'npm test'λ₯Ό μ
λ ₯νλ©΄ 'jest' ν
μ€νΈ νλ μμν¬κ° μ€νλ©λλ€.
},
"dependencies": { // μ ν리μΌμ΄μ
μ΄ 'μ€μ λ‘ λμν λ' νμν ν¨ν€μ§λ€μ
λλ€.
"express": "^4.18.2", // μΉ μ ν리μΌμ΄μ
νλ μμν¬
"socket.io": "^4.7.2" // μ€μκ° μλ°©ν₯ ν΅μ λΌμ΄λΈλ¬λ¦¬
},
"devDependencies": { // μ ν리μΌμ΄μ
μ 'κ°λ°ν λ' νμν ν¨ν€μ§λ€μ
λλ€.
// μ€μ λ°°ν¬ νκ²½μμλ νμνμ§ μμ μ μμ΅λλ€.
"nodemon": "^3.0.1" // κ°λ° μ€ μ½λ λ³κ²½ μ μλ²λ₯Ό μλ μ¬μμν΄μ£Όλ λꡬ
}
}
* **μ€λͺ
**: μ΄ νμΌμ νλ‘μ νΈμ λ©νλ°μ΄ν°λ₯Ό μ 곡νκ³ , ''npm''μ΄ νλ‘μ νΈλ₯Ό κ΄λ¦¬νκ³ μ€ννλ λ° νμν λͺ¨λ μ 보λ₯Ό λ΄κ³ μμ΅λλ€.
===== 5. κ°λ° νκ²½ =====
ν¨μ¨μ μΈ Node.js κ°λ°μ μν΄ μ μ©ν λꡬμ μ€μ λ°©λ²μ μμλ΄
λλ€.
----
==== 1) nodemon ====
κ°λ° μ€μλ μ½λλ₯Ό μμ ν λλ§λ€ μλ²λ₯Ό κ»λ€κ° λ€μ μΌμΌ νλ λ²κ±°λ‘μμ΄ μμ΅λλ€. ''nodemon''μ μ΄λ¬ν λΆνΈν¨μ ν΄μν΄μ£Όλ λꡬμ
λλ€.
* **νμμ±**: ''nodemon''μ μμ€ μ½λ νμΌμ λ³κ²½μ μλμΌλ‘ κ°μ§νκ³ , λ³κ²½μ΄ μμ λλ§λ€ Node.js μ ν리μΌμ΄μ
μ μλμΌλ‘ μ¬μμν΄μ€λλ€. μ΄λ κ°λ°μκ° μ½λλ₯Ό μμ νκ³ κ²°κ³Όλ₯Ό μ¦μ νμΈν μ μλλ‘ νμ¬ κ°λ° μλλ₯Ό ν¬κ² ν₯μμν΅λλ€.
* **μ¬μ©λ²**:
# nodemon μ€μΉ
# '-g' μ΅μ
μ nodemonμ μ μμΌλ‘ μ€μΉνμ¬ μ΄λ€ νλ‘μ νΈμμλ μ¬μ©ν μ μκ² ν©λλ€.
npm install -g nodemon
# κ°λ° μλ² μ€ν
# 'app.js'λ κ°λ° μ€μΈ Node.js μ ν리μΌμ΄μ
μ μμ νμΌμ
λλ€.
nodemon app.js
----
==== 2) νκ²½ λ³μ κ΄λ¦¬ ====
μ ν리μΌμ΄μ
μ λ°μ΄ν°λ² μ΄μ€ μ°κ²° μ 보, API ν€, ν¬νΈ λ²νΈ λ± νκ²½μ λ°λΌ λ¬λΌμ§κ±°λ λ―Όκ°ν μ 보λ₯Ό ν¬ν¨ν μ μμ΅λλ€. μ΄λ¬ν μ 보λ€μ μ½λ μμ μ§μ μμ±νλ κ²μ 보μμ μ’μ§ μμΌλ©°, νκ²½μ΄ λ°λ λλ§λ€ μ½λλ₯Ό μμ ν΄μΌ νλ λΆνΈν¨μ΄ μμ΅λλ€. **νκ²½ λ³μ**λ μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°ν΄μ€λλ€.
* **νμμ±**: νκ²½ λ³μλ₯Ό μ¬μ©νλ©΄ λ―Όκ°ν μ 보λ₯Ό μ½λ μΈλΆμ μ μ₯νκ³ , κ°λ° νκ²½, ν
μ€νΈ νκ²½, νλ‘λμ
νκ²½ λ± κ°κΈ° λ€λ₯Έ νκ²½μ λ§κ² μ½κ² μ€μ ν μ μμ΅λλ€. μ΄λ 보μμ κ°ννκ³ , λ°°ν¬ κ³Όμ μ μ μ°νκ² λ§λλλ€.
* **μ¬μ©λ²**: ''dotenv''μ κ°μ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ '''.env''' νμΌμ νκ²½ λ³μλ₯Ό μ μνκ³ μ ν리μΌμ΄μ
μμ μ κ·Όν μ μμ΅λλ€.
// dotenv ν¨ν€μ§λ₯Ό μ¬μ©νμ¬ .env νμΌμ μ μλ νκ²½ λ³μλ₯Ό λ‘λν©λλ€.
// μ΄ μ½λλ λ³΄ν΅ μ ν리μΌμ΄μ
μ κ°μ₯ μλ¨μ μμΉν©λλ€.
require('dotenv').config();
// process.env κ°μ²΄λ₯Ό ν΅ν΄ νκ²½ λ³μμ μ κ·Όν μ μμ΅λλ€.
// λ§μ½ PORT νκ²½ λ³μκ° μ€μ λμ΄ μμ§ μμΌλ©΄ κΈ°λ³Έκ°μΌλ‘ 3000μ μ¬μ©ν©λλ€.
const port = process.env.PORT || 3000;
// DATABASE_URL νκ²½ λ³μμ μ μ₯λ λ°μ΄ν°λ² μ΄μ€ μ°κ²° λ¬Έμμ΄μ κ°μ Έμ΅λλ€.
const dbUrl = process.env.DATABASE_URL;
===== 6. νλ‘λμ
λ°°ν¬ =====
κ°λ°μ΄ μλ£λ Node.js μ ν리μΌμ΄μ
μ μ€μ μ¬μ©μλ€μ΄ μ κ·Όν μ μλλ‘ μλ²μ λ°°ν¬νλ κ²μ μ€μν κ³Όμ μ
λλ€. λ°°ν¬ νκ²½μμλ μ ν리μΌμ΄μ
μ΄ μμ μ μΌλ‘ κ³μ μ€νλλλ‘ κ΄λ¦¬νλ κ²μ΄ μ€μν©λλ€.
----
==== 1) PM2 μ¬μ© ====
''PM2''λ Node.js μ ν리μΌμ΄μ
μ μν κ°λ ₯ν **νλ‘μΈμ€ κ΄λ¦¬μ**μ
λλ€. νλ‘λμ
νκ²½μμ μ ν리μΌμ΄μ
μ΄ λ©μΆμ§ μκ³ μμ μ μΌλ‘ μ€νλλλ‘ λμμ€λλ€.
* **νμμ±**: Node.js μ ν리μΌμ΄μ
μ΄ μ€λ₯λ‘ μΈν΄ μ€λ¨λκ±°λ μλ²κ° μ¬λΆν
λ λ μλμΌλ‘ λ€μ μμν΄μ£Όλ κΈ°λ₯μ΄ νμν©λλ€. λν, μ¬λ¬ CPU μ½μ΄λ₯Ό ν¨μ¨μ μΌλ‘ μ¬μ©νκΈ° μν λ‘λ λ°Έλ°μ± κΈ°λ₯λ μ€μν©λλ€. PM2λ μ΄λ¬ν κΈ°λ₯μ μ 곡νμ¬ μ ν리μΌμ΄μ
μ μμ μ±κ³Ό μ±λ₯μ ν₯μμν΅λλ€.
* **μ£Όμ κΈ°λ₯**:
* **μλ μ¬μμ**: μ ν리μΌμ΄μ
μ΄ μκΈ°μΉ μκ² μ’
λ£λκ±°λ μλ²κ° μ¬λΆν
λ λ μλμΌλ‘ λ€μ μμν©λλ€.
* **ν΄λ¬μ€ν° λͺ¨λ**: μλ²μ μ¬λ¬ CPU μ½μ΄λ₯Ό νμ©νμ¬ μ ν리μΌμ΄μ
μ μ±λ₯μ κ·Ήλνν©λλ€.
* **λͺ¨λν°λ§**: μ ν리μΌμ΄μ
μ μν, CPU μ¬μ©λ, λ©λͺ¨λ¦¬ μ¬μ©λ λ±μ μ€μκ°μΌλ‘ λͺ¨λν°λ§ν μ μμ΅λλ€.
# PM2 μ€μΉ
# '-g' μ΅μ
μΌλ‘ μ μ μ€μΉνμ¬ μ΄λμλ PM2 λͺ
λ Ήμ΄λ₯Ό μ¬μ©ν μ μκ² ν©λλ€.
npm install -g pm2
# μ ν리μΌμ΄μ
μμ
# 'app.js' νμΌμ PM2λ‘ μ€ννκ³ , 'my-app'μ΄λΌλ μ΄λ¦μΌλ‘ κ΄λ¦¬ν©λλ€.
pm2 start app.js --name "my-app"
# ν΄λ¬μ€ν° λͺ¨λ
# μλ²μ CPU μ½μ΄ μλ§νΌ μ컀 νλ‘μΈμ€λ₯Ό μμ±νμ¬ λ‘λ λ°Έλ°μ±μ μλμΌλ‘ μ²λ¦¬ν©λλ€.
# 'max'λ μ¬μ© κ°λ₯ν λͺ¨λ CPU μ½μ΄λ₯Ό μ¬μ©νλΌλ μλ―Έμ
λλ€.
pm2 start app.js -i max
===== 7. μ±λ₯ μ΅μ ν =====
Node.js μ ν리μΌμ΄μ
μ μ±λ₯μ μ΅λν λμ΄μ¬λ¦¬κ³ μμ μ±μ ν보νκΈ° μν κΈ°λ²λ€μ μμλ΄
λλ€.
----
==== 1) λ©λͺ¨λ¦¬ κ΄λ¦¬ ====
Node.jsλ JavaScriptλ₯Ό μ¬μ©νλ©°, JavaScriptλ 'κ°λΉμ§ 컬λ μ
(Garbage Collection)'μ ν΅ν΄ μλμΌλ‘ λ©λͺ¨λ¦¬λ₯Ό κ΄λ¦¬ν©λλ€. νμ§λ§ λλλ‘ λ©λͺ¨λ¦¬ λμ(Memory Leak)κ° λ°μνκ±°λ, νΉμ μμ μ λ©λͺ¨λ¦¬ μ¬μ©λμ νμΈν΄μΌ ν νμκ° μμ΅λλ€.
* **νμμ±**: λ©λͺ¨λ¦¬ λμλ μ ν리μΌμ΄μ
μ΄ λΆνμν λ©λͺ¨λ¦¬λ₯Ό κ³μ μ μ νμ¬ κ²°κ΅ μλ²μ μ±λ₯ μ νλ₯Ό μΌμΌν€κ³ , μ¬νλ©΄ μ ν리μΌμ΄μ
μ΄ κ°μ μ’
λ£λ μ μμ΅λλ€. λ©λͺ¨λ¦¬ μ¬μ©λμ λͺ¨λν°λ§νκ³ κ΄λ¦¬νλ κ²μ μ΄λ¬ν λ¬Έμ λ₯Ό μλ°©νλ λ° μ€μν©λλ€.
* **κ°λΉμ§ 컬λ μ
**: μ¬μ©νμ§ μλ λ©λͺ¨λ¦¬λ₯Ό μλμΌλ‘ ν΄μ νλ κ³Όμ μ
λλ€. Node.jsλ V8 μμ§μ κ°λΉμ§ 컬λ ν°λ₯Ό μ¬μ©ν©λλ€.
// κ°λ° λλ λλ²κΉ
λͺ©μ μΌλ‘ κ°λΉμ§ 컬λ μ
μ κ°μ λ‘ μ€νν μ μμ§λ§,
// μ€μ νλ‘λμ
νκ²½μμλ κΆμ₯λμ§ μμ΅λλ€. V8 μμ§μ΄ μ΅μ μ μμ μ μνν©λλ€.
if (global.gc) {
global.gc();
}
// νμ¬ Node.js νλ‘μΈμ€μ λ©λͺ¨λ¦¬ μ¬μ©λμ λͺ¨λν°λ§ν©λλ€.
// 'heapUsed'λ V8 μμ§μ΄ μ¬μ© μ€μΈ ν(Heap) λ©λͺ¨λ¦¬ μμ λνλ
λλ€.
const used = process.memoryUsage();
console.log(`λ©λͺ¨λ¦¬ μ¬μ©λ: ${Math.round(used.heapUsed / 1024 / 1024)} MB`);
----
==== 2) ν΄λ¬μ€ν° λͺ¨λ ====
Node.jsλ κΈ°λ³Έμ μΌλ‘ λ¨μΌ μ€λ λ(Single-threaded) λ°©μμΌλ‘ λμν©λλ€. μ΄λ νλμ CPU μ½μ΄λ§ μ¬μ©νμ¬ μμ
μ μ²λ¦¬νλ€λ μλ―Έμ
λλ€. νμ§λ§ μ΅μ μλ²λ λλΆλΆ μ¬λ¬ κ°μ CPU μ½μ΄λ₯Ό κ°μ§κ³ μμ΅λλ€. 'ν΄λ¬μ€ν° λͺ¨λ'λ μ΄λ¬ν λ€μ€ μ½μ΄λ₯Ό ν¨μ¨μ μΌλ‘ νμ©ν μ μκ² ν΄μ€λλ€.
* **νμμ±**: λ¨μΌ μ€λ λ λ°©μμΌλ‘λ μλ²μ λͺ¨λ CPU μ½μ΄λ₯Ό νμ©ν μ μμ΄, λκ·λͺ¨ νΈλν½μ μ²λ¦¬ν λ μ±λ₯ νκ³μ λΆλͺν μ μμ΅λλ€. ν΄λ¬μ€ν° λͺ¨λλ μ¬λ¬ μ컀 νλ‘μΈμ€λ₯Ό μμ±νμ¬ κ° μμ»€κ° νλμ CPU μ½μ΄λ₯Ό λ΄λΉνκ² ν¨μΌλ‘μ¨, μλ²μ μ²λ¦¬λμ ν¬κ² λλ¦¬κ³ μμ μ±μ λμ
λλ€.
* **λμ μ리**: 'λ§μ€ν° νλ‘μΈμ€'κ° μ컀 νλ‘μΈμ€λ€μ κ΄λ¦¬νκ³ , λ€μ΄μ€λ μμ²λ€μ μ컀λ€μκ² λΆλ°°ν©λλ€. κ° 'μ컀 νλ‘μΈμ€'λ Node.js μ ν리μΌμ΄μ
μ λ
립μ μΈ μΈμ€ν΄μ€μ
λλ€.
const cluster = require('cluster'); // Node.js λ΄μ₯ 'cluster' λͺ¨λμ κ°μ Έμ΅λλ€.
const numCPUs = require('os').cpus().length; // μλ²μ CPU μ½μ΄ μλ₯Ό κ°μ Έμ΅λλ€.
if (cluster.isMaster) { // νμ¬ νλ‘μΈμ€κ° λ§μ€ν° νλ‘μΈμ€μΈμ§ νμΈν©λλ€.
// λ§μ€ν° νλ‘μΈμ€: μ컀 νλ‘μΈμ€λ€μ μμ±νκ³ κ΄λ¦¬νλ μν μ ν©λλ€.
console.log(`λ§μ€ν° νλ‘μΈμ€ ${process.pid}κ° μ€ν μ€μ
λλ€.`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork(); // CPU μ½μ΄ μλ§νΌ μ컀 νλ‘μΈμ€λ₯Ό μμ±ν©λλ€.
}
cluster.on('exit', (worker, code, signal) => {
console.log(`μ컀 νλ‘μΈμ€ ${worker.process.pid}κ° μ’
λ£λμμ΅λλ€. λ€μ μμν©λλ€.`);
cluster.fork(); // μ컀 νλ‘μΈμ€κ° λΉμ μμ μΌλ‘ μ’
λ£λλ©΄ μλ‘μ΄ μ컀λ₯Ό λ€μ μμ±νμ¬ μμ μ±μ μ μ§ν©λλ€.
});
} else {
// μ컀 νλ‘μΈμ€: μ€μ μ ν리μΌμ΄μ
μ½λλ₯Ό μ€ννλ μν μ ν©λλ€.
console.log(`μ컀 νλ‘μΈμ€ ${process.pid}κ° μμλμμ΅λλ€.`);
require('./app.js'); // μ컀 νλ‘μΈμ€μμ μ€μ Node.js μ ν리μΌμ΄μ
νμΌ(μ: app.js)μ μ€νν©λλ€.
}
===== 8. λλ²κΉ
=====
μ ν리μΌμ΄μ
μ κ°λ°νλ€ λ³΄λ©΄ μ€λ₯(λ²κ·Έ)κ° λ°μνκΈ° λ§λ ¨μ
λλ€. μ΄λ¬ν μ€λ₯λ₯Ό μ°Ύμλ΄κ³ μμ νλ κ³Όμ μ **λλ²κΉ
**μ΄λΌκ³ ν©λλ€. ν¨κ³Όμ μΈ λλ²κΉ
μ κ°λ° μκ°μ λ¨μΆνκ³ μ ν리μΌμ΄μ
μ νμ§μ λμ΄λ λ° νμμ μ
λλ€.
----
==== 1) λ΄μ₯ λλ²κ±° μ¬μ© ====
Node.jsλ μ½λλ₯Ό ν μ€μ© μ€ννλ©° λ³μ κ°μ νμΈνκ³ νλ‘κ·Έλ¨μ νλ¦μ μ μ΄ν μ μλ κ°λ ₯ν λ΄μ₯ λλ²κ±°λ₯Ό μ 곡ν©λλ€.
* **νμμ±**: λ¨μν ''console.log()''λ₯Ό μ¬μ©νλ κ²λ³΄λ€ ν¨μ¬ μ λ°νκ² μ½λμ λ¬Έμ λ₯Ό νμ
ν μ μμ΅λλ€. νΉμ μ§μ μμ μ€νμ λ©μΆκ³ (λΈλ μ΄ν¬ν¬μΈνΈ), λ³μ κ°μ λ³κ²½ν΄λ³΄κ±°λ, λ€μ μ€λ‘ λμ΄κ°λ λ± μμΈν μ‘°μμ΄ κ°λ₯ν©λλ€.
* **μ¬μ©λ²**:
# λλ²κ·Έ λͺ¨λλ‘ Node.js μ ν리μΌμ΄μ
μ μ€νν©λλ€.
# μ΄ λͺ
λ Ήμ μ€ννλ©΄ Chrome κ°λ°μ λꡬμ κ°μ μΈλΆ λλ²κ±°λ₯Ό μ°κ²°ν μ μλ μ£Όμκ° μ½μμ μΆλ ₯λ©λλ€.
node --inspect app.js
# μ½λ λ΄μμ νΉμ μ§μ μ μ€νμ λ©μΆκ³ μΆμ λ 'debugger;' ν€μλλ₯Ό μ½μ
ν©λλ€.
# λλ²κ·Έ λͺ¨λλ‘ μ€ν μ€ μ΄ ν€μλλ₯Ό λ§λλ©΄ μ€νμ΄ μΌμ μ€μ§λ©λλ€.
----
==== 2) λ‘κΉ
====
**λ‘κΉ
**μ μ ν리μΌμ΄μ
μ μ€ν μ€μ λ°μνλ μ€μν μ 보(μ€λ₯, κ²½κ³ , μΌλ° μ 보 λ±)λ₯Ό κΈ°λ‘νλ κ³Όμ μ
λλ€. νΉν νλ‘λμ
νκ²½μμλ λλ²κ±°λ₯Ό μ§μ μ¬μ©ν μ μμΌλ―λ‘, λ‘κ·Έ νμΌμ λ¬Έμ ν΄κ²°μ ν΅μ¬ λ¨μκ° λ©λλ€.
* **νμμ±**: μ ν리μΌμ΄μ
μ΄ μ΄λ»κ² λμνκ³ μλμ§, μ΄λ€ λ¬Έμ κ° λ°μνλμ§ λ±μ νμ
νλ λ° νμμ μ
λλ€. μ¬μ©μ μμ² νλ¦ μΆμ , μ±λ₯ λ¬Έμ λΆμ, 보μ κ°μ¬ λ± λ€μν λͺ©μ μΌλ‘ νμ©λ©λλ€. ''winston''κ³Ό κ°μ λ‘κΉ
λΌμ΄λΈλ¬λ¦¬λ λ‘κ·Έ λ 벨(μ 보, κ²½κ³ , μ€λ₯ λ±)λ³λ‘ λ‘κ·Έλ₯Ό λΆλ₯νκ³ , νμΌμ΄λ λ°μ΄ν°λ² μ΄μ€ λ± λ€μν κ³³μ μ μ₯ν μ μκ² ν΄μ€λλ€.
const winston = require('winston'); // winstonμ κ°λ ₯νκ³ μ μ°ν λ‘κΉ
λΌμ΄λΈλ¬λ¦¬μ
λλ€.
const logger = winston.createLogger({ // λ‘κ±° μΈμ€ν΄μ€λ₯Ό μμ±ν©λλ€.
level: 'info', // 'info' λ 벨 μ΄μμ λ‘κ·Έ(info, warn, error)λ₯Ό κΈ°λ‘ν©λλ€.
format: winston.format.json(), // λ‘κ·Έλ₯Ό JSON νμμΌλ‘ μΆλ ₯νμ¬ λΆμνκΈ° μ½κ² λ§λλλ€.
transports: [ // λ‘κ·Έλ₯Ό μ΄λλ‘ λ³΄λΌμ§(μ μ₯ν μ§) μ μν©λλ€.
// 'error.log' νμΌμλ 'error' λ 벨μ λ‘κ·Έλ§ κΈ°λ‘ν©λλ€.
new winston.transports.File({ filename: 'error.log', level: 'error' }),
// 'combined.log' νμΌμλ 'info' λ 벨 μ΄μμ λͺ¨λ λ‘κ·Έλ₯Ό κΈ°λ‘ν©λλ€.
new winston.transports.File({ filename: 'combined.log' })
]
});
===== 9. κ΄λ ¨ μ©μ΄ =====
* [[wiki:glossary:web_technologies:express|Express.js]] - Node.js μΉ μ ν리μΌμ΄μ
κ°λ°μ μν μ΅μνμ κΈ°λ₯μ μ 곡νλ λΉ λ₯΄κ³ μ μ°ν μΉ νλ μμν¬μ
λλ€.
* [[wiki:glossary:server_operations:pm2|PM2]] - Node.js μ ν리μΌμ΄μ
μ νλ‘λμ
νκ²½μμ μμ μ μΌλ‘ μ€ννκ³ κ΄λ¦¬νλ λ° μ¬μ©λλ νλ‘μΈμ€ κ΄λ¦¬μμ
λλ€.
* [[wiki:glossary:server_operations:socketio|Socket.IO]] - μΉ μμΌμ κΈ°λ°μΌλ‘ μ€μκ° μλ°©ν₯ ν΅μ κΈ°λ₯μ μ½κ² ꡬνν μ μλλ‘ λλ λΌμ΄λΈλ¬λ¦¬μ
λλ€. μ±ν
μ ν리μΌμ΄μ
λ±μ νμ©λ©λλ€.
* [[wiki:glossary:development_tools:git:git|Git]] - μμ€ μ½λμ λ³κ²½ μ΄λ ₯μ ν¨μ¨μ μΌλ‘ κ΄λ¦¬νκ³ μ¬λ¬ κ°λ°μκ° νμ
ν μ μλλ‘ λλ λΆμ° λ²μ κ΄λ¦¬ μμ€ν
μ
λλ€.
* [[wiki:glossary:web_technologies:javascript|JavaScript]] - μΉ νμ΄μ§μμ 볡μ‘ν κΈ°λ₯μ ꡬνν μ μκ² ν΄μ£Όλ νλ‘κ·Έλλ° μΈμ΄μ΄μ, Node.jsμ ν΅μ¬ μΈμ΄μ
λλ€.
===== 10. κ΄λ ¨ λ¬Έμ =====
* [[wiki:it:dream_of_enc:metaverse:nodejs|Node.js λ°±μλ μ€μ ]] - Node.jsλ₯Ό μ¬μ©νμ¬ λ°±μλ μμ€ν
μ μ€μ νλ λ°©λ²μ λν μμΈ λ¬Έμμ
λλ€.
* [[wiki:glossary:development_tools:git:github|GitHub]] - Git μ μ₯μλ₯Ό νΈμ€ν
νλ μΉ μλΉμ€μ΄μ, μ μΈκ³ κ°λ°μλ€μ΄ μ½λλ₯Ό 곡μ νκ³ νμ
νλ νλ«νΌμ
λλ€.
* [[wiki:glossary:server_operations:linux|Linux]] - μλ² μ΄μ체μ λ‘ λ리 μ¬μ©λλ μ€ν μμ€ μ΄μ체μ μ
λλ€. Node.js μ ν리μΌμ΄μ
λ°°ν¬μ λ§μ΄ νμ©λ©λλ€.
---
//μ΄ νμ΄μ§λ μλμΌλ‘ μμ±λμμ΅λλ€.//