μ‚¬μš©μž 도ꡬ

μ‚¬μ΄νŠΈ 도ꡬ


wiki:glossary:server_operations:nodejs

🟒 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. κ΄€λ ¨ μš©μ–΄

  • Express.js - Node.js μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ κ°œλ°œμ„ μœ„ν•œ μ΅œμ†Œν•œμ˜ κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” λΉ λ₯΄κ³  μœ μ—°ν•œ μ›Ή ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€.
  • PM2 - Node.js μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ ν”„λ‘œλ•μ…˜ ν™˜κ²½μ—μ„œ μ•ˆμ •μ μœΌλ‘œ μ‹€ν–‰ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” ν”„λ‘œμ„ΈμŠ€ κ΄€λ¦¬μžμž…λ‹ˆλ‹€.
  • Socket.IO - μ›Ή μ†ŒμΌ“μ„ 기반으둜 μ‹€μ‹œκ°„ μ–‘λ°©ν–₯ 톡신 κΈ°λŠ₯을 μ‰½κ²Œ κ΅¬ν˜„ν•  수 μžˆλ„λ‘ λ•λŠ” λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€. μ±„νŒ… μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 등에 ν™œμš©λ©λ‹ˆλ‹€.
  • Git - μ†ŒμŠ€ μ½”λ“œμ˜ λ³€κ²½ 이λ ₯을 효율적으둜 κ΄€λ¦¬ν•˜κ³  μ—¬λŸ¬ κ°œλ°œμžκ°€ ν˜‘μ—…ν•  수 μžˆλ„λ‘ λ•λŠ” λΆ„μ‚° 버전 관리 μ‹œμŠ€ν…œμž…λ‹ˆλ‹€.
  • JavaScript - μ›Ή νŽ˜μ΄μ§€μ—μ„œ λ³΅μž‘ν•œ κΈ°λŠ₯을 κ΅¬ν˜„ν•  수 있게 ν•΄μ£ΌλŠ” ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ΄μž, Node.js의 핡심 μ–Έμ–΄μž…λ‹ˆλ‹€.

10. κ΄€λ ¨ λ¬Έμ„œ

  • Node.js λ°±μ—”λ“œ μ„€μ • - Node.jsλ₯Ό μ‚¬μš©ν•˜μ—¬ λ°±μ—”λ“œ μ‹œμŠ€ν…œμ„ μ„€μ •ν•˜λŠ” 방법에 λŒ€ν•œ 상세 λ¬Έμ„œμž…λ‹ˆλ‹€.
  • GitHub - Git μ €μž₯μ†Œλ₯Ό ν˜ΈμŠ€νŒ…ν•˜λŠ” μ›Ή μ„œλΉ„μŠ€μ΄μž, μ „ 세계 κ°œλ°œμžλ“€μ΄ μ½”λ“œλ₯Ό κ³΅μœ ν•˜κ³  ν˜‘μ—…ν•˜λŠ” ν”Œλž«νΌμž…λ‹ˆλ‹€.
  • Linux - μ„œλ²„ 운영체제둜 널리 μ‚¬μš©λ˜λŠ” μ˜€ν”ˆ μ†ŒμŠ€ μš΄μ˜μ²΄μ œμž…λ‹ˆλ‹€. Node.js μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 배포에 많이 ν™œμš©λ©λ‹ˆλ‹€.

β€” 이 νŽ˜μ΄μ§€λŠ” μžλ™μœΌλ‘œ μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

wiki/glossary/server_operations/nodejs.txt Β· λ§ˆμ§€λ§‰μœΌλ‘œ μˆ˜μ •λ¨: μ €μž syjang0803

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki