Node.js 교과서 - 1

1. 폴더 관리

app.js : 핵심 서버 스크립트

public : 외부에서 접근 가능한 파일들을 모아둔다.

views : 템플릿 파일들을 모아둔다.

routes : 서버의 라우터와 로직들을 모아둔다.


2. Rest API

REST API : REpresentational State Transfer의 약어로 네트워크 구조의 방식중 하나. 서버의 자원을 정의하고, 자원에 대한 주소를 지정하는 방법을 가르킴.

  • GET : 서버의 자원을 가져오고자 할 때 사용함. 용청의 본문(body)에 데이터를 넣지 않음. 데이터는 쿼리스트링을 사용함.

  • POST : 서버에 자원을 새로 등록하고자 할 때 사용함. 요청의 본문에 새로 등록할 데이터를 넣어 보냄.

  • PUT : 서버의 자원을 요청에 들어 있는 자원으로 치환하고자 할 때 사용합니다. 요청의 본문에 치환할 데이터를 넣어 보냅니다.

  • PATCH : 서버 자원의 일부만 수정하고자 할 때 사용함. 요청의 본문에 일부 수정할 데이터를 넣어 보냄.

  • DELETE : 서버의 자원을 삭제하고자 할 때 사용.

put vs patch
유저 리스트에 특정 유저의 정보를 수정 하고자 할때 patch는 해당 유저의 값을 수정하지만 put 은 전체 리스트를 가져온후 수정하여 값을 반환한다.

출처

3. Http와 Https & Http2

https 모듈은 웹 서버에 SSL 암호화를 추가.


  • http
const http = require('http');

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(8080, () => { // 서버 연결
    console.log('8080번 포트에서 서버 대기 중입니다!');
  });

  • https
const https = require('https');
const fs = require('fs');

https.createServer({
  cert: fs.readFileSync('도메인 인증서 경로'),
  key: fs.readFileSync('도메인 비밀키 경로'),
  ca: [
    fs.readFileSync('상위 인증서 경로'),
    fs.readFileSync('상위 인증서 경로'),
  ],
}, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(443, () => {
    console.log('443번 포트에서 서버 대기 중입니다!');
  });

  • http2
const http2 = require('http2');
const fs = require('fs');

http2.createSecureServer({
  cert: fs.readFileSync('도메인 인증서 경로'),
  key: fs.readFileSync('도메인 비밀키 경로'),
  ca: [
    fs.readFileSync('상위 인증서 경로'),
    fs.readFileSync('상위 인증서 경로'),
  ],
}, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(443, () => {
    console.log('443번 포트에서 서버 대기 중입니다!');
  });

http 모듈과 거의 흡사하나, 첫 번째 인자로 인증서에 관련된 옵션 객체를 받는다.

노드의 http2 모듈은 SSl 암호화와 더불어 최신 HTTP 프로토콜인 http2를 사용할 수 있게 해줌. 기존의 http1보다 훨씬 효율적인 요청이 가능(웹의 속도 개선)

출처

4. 비동기 방식을 사용하면 작업이 백그라운드로 보내져서 처리가 되는데, 이 때 끝나는 순서대로 실행이 된다. 이는 운영체제가 결정하는 것이므로 순서가 지켜져야 하는 작업의 경우에는 동기적으로 실행하거나 비동기 방법으로 실행하되 순서를 지켜줘야 한다. 그렇다면 동기적 방법이랑 비동기적 방법이지만 콜백(혹은 promise)을 연달아 사용함으로써 순서를 지키는 방법에는 어떠한 차이가 있을까?


* 비동기적 방식

const fs = require('fs').promises;

fs.writeFile('./wirteme.txt', '글이 입력됩니다.')
.then(() => {
    return fs.readFile('./writeme.txt');
})
.then((data) => {
    console.log(data.toString());
})
.catch((err) => {
    throw err;
});

* 동기적 방식

const fs = require('fs');

const data = fs.readFileSync('./readme.txt');
console.log('1번', data.toString());

두 개의 파일을 다섯번 반복시킨다고 했을 때, 동기적 방법의 파일을 다섯번 실행시키면 첫번째 작업을 모두 수행하고 두번째 작업을 수행하는 식으로 진행된다. 하지만 비동기적 방법의 파일을 다섯번 반복시키면 다섯0 개의 파일 묶음이 백그라운드로 들어가서 비동기적으로 실행되는 차이가 있다.


5. Worker Thread란

6. Cluster란

기본적으로 싱글 스레드인 노드가 CPU 코어를 모두 사용할 수 있게 해주는 모듈.

포트를 공유하는 노드 프로세스를 여러 개 둘 수 있다.

여러개의 CPU를 사용하여 서버의 부하를 분산 시키지만, 세션 공유가 불가하다는 단점이 존재한다.(Redis 등의 서버를 도입하여 해결 가능)
실무에서는 pm2 등의 모듈로 cluster 기능을 사용한다.

새로 고침 했을 때 프로세서가 종료되게 하는 코드

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length; // 내 cpu 개수를 구해준다.
if (cluster.isMaster) { 
  console.log(`마스터 프로세스 아이디: ${process.pid}`); //Master process는 요청을 Round Robin
  // 알고리즘에 의해 워커 프로세스한테 분배해주는 역할을 한다.
  // Master process에서 fork를 해서 CPU 개수만큼 워커 프로세스를 생산
  for (let i = 0; i < numCPUs; i += 1) {
    cluster.fork();
  }
  // 워커가 종료되었을 때
  cluster.on('exit', (worker, code, signal) => {
    console.log(`${worker.process.pid}번 워커가 종료되었습니다.`);
    console.log('code', code, 'signal', signal);
  });
} else {
  // 워커들이 포트에서 대기
  http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.write('<h1>Hello Node!</h1>');
    res.end('<p>Hello Cluster!</p>');
    setTimeout(() => { // 워커 존재를 확인하기 위해 1초마다 강제 종료
      process.exit(1);
    }, 1000);
  }).listen(8086); //원래는 하나의 프로그램은 하나의 프로세스를 차지하고
  //하나의 프로세스는 하나의 포트를 차지한다.
  //하지만 Cluster를 하면 여러 개의 프로세스을 하나의 포트에 묶어 놓을 수 있다.
  console.log(`${process.pid}번 워커 실행`);
}

<결과화면>

코드를 실행시켰을 때localhost에서 새로 고침을 반복하였을 때

이런식으로 실행 순서의 역순으로 워커 프로세서가 종료되며 모두 종료되었을 때 새로고침을 하면 에러가 나게 된다.

끝!

좋은 웹페이지 즐겨찾기