OKdevTV Docs
Home OKdevTV
ESC
nodejs 8 min read 13.1 KB Raw Markdown
On this page (36)

node.js

JS Warm Up

  • JavaScript platform like JVM of Java
  • JSON

설치

node.js 개요

text
Node.js® is a platform
built on Chrome's JavaScript runtime
for easily building fast, scalable network applications.
Node.js uses an event-driven, non-blocking I/O model
that makes it lightweight and efficient, perfect
for data-intensive real-time applications
that run across distributed devices.

특징

  • JavaScript 기반 플랫폼
  • Server-side
  • Command Tool
  • Desktop Application

장점

  • 쉬운 시작
  • 안정적인 서비스 w/ pm2
  • 모듈 2,663,939 total packages(2024/01/27); https://modulecounts.com
  • 성능 개선
    • linkedin 사례
      • 서버 감축 Ruby + Mongrel 30대 -> node.js 3대
      • Frontend, Backend 개발자 소통 원활
      • 잡다한 작업 감소해서 로직에 집중
    • paypal 사례
      • Java를 Node.js로 대치
      • 더 적은 인원으로 개발 2배 정도 빨라짐
      • 코드량 33%, 파일 40% 감소
      • 성능 개선됨 (15-user: 11.3 vs 21.6 pages/sec)
  • C/C++ Addon

단점

  • No Silver Bullet
    • CPU과다 사용시 이슈
  • 예외처리 실수하면 서버 다운 (pm2로 자동 재시작 가능)
  • Callback Hell (Async로 커버 가능)

비동기 프로그래밍

  • 자바스크립트의 경우 비동기 코드 패턴이 다반사
  • 기존 코드와 달리 콜백 함수를 함께 넘겨주는 형태
  • 이벤트 핸들링에 많이 쓰이는 기법
  • 이벤트 루프 사용으로 싱글쓰레드 동작

blocking, non-blocking

  • Input/Output
  • IO latency
    • L1: 3 cycles
    • L2: 14 cycles
    • RAM: 250 cycles
    • DISK: 41,000,000 cycles
    • NETWORK: 240,000,000 cycles

from: https://www.dropbox.com/s/o9g4m7tug3yt1xx/jsconf2009-nodejs.pdf?dl=0

  • blocking code
text
var result = db.query("select * from T");
// use result
  • non-blocking code
text
db.query("select * from T",
  function(result) {
    // use result
  }
);

이벤트 루프

event loop

from blog.udemy.com/learn-node-js/

  • 이벤트 루프 사용으로 싱글쓰레드 동작
    • 기존 서버는 쓰레드 기반
    • 아파치 등은 커넥션 증가에 따라서 메모리 증가
  • nginx는 이벤트 루프 방식

서버사이드 자바스크립트 개발환경 설치

모듈 만들고 참조하기

  • commonjs
  • const path = require('path')

ES6 setting

  • package.json
  • "type": "module"
  • import path from path

npm 을 통한 확장

socket.io 모듈

json
{
  "name": "socket-chat-example",
  "version": "0.0.1",
  "description": "my first socket.io app",
  "dependencies": {
    "express": "^4.14.0",
    "socket.io": "^4.1.2"
  }
}
  • server.js
js
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);

app.get('/', function (req, res) {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
  socket.on('chat message', function (msg) {
    io.emit('chat message', msg);
  });
});

http.listen(3000, function () {
  console.log('listening on *:3000');
});

  • index.html
html
<!doctype html>
<html lang="ko">

<head>
  <title>Socket.IO chat</title>
  <style>
    - { margin: 0; padding: 0; box-sizing: border-box; }
    form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
    form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
    form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
    #messages { list-style-type: none; margin: 0; padding: 0; }
    #messages li { padding: 5px 10px; }
    #messages li:nth-child(odd) { background: #eee; }
  </style>
</head>

<body>
  <ul id="messages"></ul>
  <form id="form" action="">
    <input id="input" autocomplete="off" /><button>Send</button>
  </form>
  <script src="/socket.io/socket.io.js"></script>
  <script>
    var socket = io();

    var messages = document.getElementById('messages');
    var form = document.getElementById('form');
    var input = document.getElementById('input');

    form.addEventListener('submit', function (e) {
      e.preventDefault();
      if (input.value) {
        socket.emit('chat message', input.value);
        input.value = '';
      }
    });

    socket.on('chat message', function (msg) {
      var item = document.createElement('li');
      item.textContent = msg;
      messages.appendChild(item);
      window.scrollTo(0, document.body.scrollHeight);
    });
  </script>
</body>

</html>

실행

text
npm i
node server.js

expressjs 웹 프레임워크

  • http://expressjs.com/
  • npm install -g express-generator
  • express myapp
  • node.js의 기본 API인 http를 확장
  • 기본 http
js
const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

express.js

  • with package.json npm init
  • npm install express --save
  • create exp.js file
js
var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
})
  • 실행 node exp.js

express-generator

  • npm install express-generator -g
  • express.js의 scafold 코드 생성
  • express myweb
  • cd myweb && npm install
  • run npm start
    • or node bin/www
    • or DEBUG=myweb:* node bin/www

basic routing

  • app.METHOD(PATH, HANDLER)
    • app is an instance of express.
    • METHOD is an HTTP request method, in lowercase.
    • PATH is a path on the server.
    • HANDLER is the function executed when the route is matched.

get

js
app.get('/', function (req, res) {
    res.send('Hello World!')
})
  • curl 'localhost:3000'
  • curl -XGET 'localhost:3000'

post

js
app.post('/', function (req, res) {
    res.send('Got a POST request')
})
  • curl -XPOST 'localhost:3000'

put

js
app.put('/user', function (req, res) {
    res.send('Got a PUT request at /user')
})
  • curl -XPUT 'localhost:3000/user'

delete

js
app.delete('/user', function (req, res) {
    res.send('Got a DELETE request at /user')
})
  • curl -XDELETE 'localhost:3000/user'

Routing

methods

get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, propfind, proppatch, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, search, connect.

  • all
js
app.all('/secret', function (req, res, next) {
  console.log('Accessing the secret section ...')
  next() // pass control to the next handler
})

Route Parameters

text
Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }
text
app.get('/users/:userId/books/:bookId', function (req, res) {
  res.send(req.params)
})

MairaDB 설치

MongoDB + node.js

node cluster 시작하기

text
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  // Fork workers.
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`);
  });
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world\n');
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

node.js clustering with PM2

JavaScript Code Quality

  • SonarQube
  • SonarLint

디버깅

개요

  • debugging에서 알아야 할 용어들
    • breakpoint : 중단점입니다. 실행 모드가 아닌 디버그 모드에서 프로그램을 중지하게 되는 지점의 표시입니다. 보통 ide에서 소스 라인 맨 앞 여백을 (더블)클릭하면 생깁니다. 다시 (더블)클릭하면 없어집니다. resume을 실행하면 다음 중단점을 만날 때까지 실행됩니다.
    • step over : 한 줄을 실행합니다. 함수가 있어도 실행 후 다음으로 넘어갑니다.
    • step into : 포커스된 라인에 있는 함수 내부로 들어갑니다.
    • step out : 현재 함수를 끝까지 실행시키고, 호출시킨 곳으로 되돌아 갑니다.
    • resume : 디버그로 한 줄 한 줄 실행시키는 트레이스 모드를 그만두고 다음 브레이크포인트를 만날 때까지 실행합니다.

node.js debug

text
node debug myscript.js
  • myscript.js
text
x = 5;
setTimeout(() => {
  debugger;
  console.log('world');
}, 1000);
console.log('hello');

email

Test Frameworks

서버 모니터링

text
$ cd ~/dev/mongodb/bin
$ mkdir -p ~/data/db
$ ./mongod --dbpath=/Users/kenu/data/db

$ cd ~/dev/mongodb/bin
$ mongo
MongoDB shell version: 2.4.9
connecting to: test
> use uptime
switched to db uptime
> db.addUser('uptime', 'okpass');
{
	"user" : "uptime",
	"readOnly" : false,
	"pwd" : "fdc9e10c8f90fac0c9fe786f28cc04f4",
	"_id" : ObjectId("5577b97a62555c0332f63e6f")
}
> exit


$ git clone git://github.com/fzaninotto/uptime.git
$ cd uptime
$ npm install

영상

  1. 개요, 설치 https://www.youtube.com/watch?v=Z8cOppJwOeU
  2. socket.io, express.js https://www.youtube.com/watch?v=YWaoLdoqSWE
  3. express.js basic routing https://www.youtube.com/watch?v=KOtEZ0j0cic
  4. express.js api https://www.youtube.com/watch?v=-nHp0D4n4Do
  5. express.js resources https://www.youtube.com/watch?v=4bIIX07vN-8
  6. mariadb 연결(Windows) https://www.youtube.com/watch?v=VTBACySodEc
  7. node cluster https://www.youtube.com/watch?v=2v7oRhit8lQ
  8. node debugging https://www.youtube.com/watch?v=TaMYKdcBIGA
  9. Code Quality https://www.youtube.com/watch?v=1931C8MAvdM
  10. jade 2 ejs template https://www.youtube.com/watch?v=IeOoN1LZ4f0
  11. Express + MariaDB(mysql) Web App https://www.youtube.com/watch?v=UocHh8604Lc
  12. Async, Nested SQL https://www.youtube.com/watch?v=PJ7fQnDLmWg
  13. email

ref