node.js로 server 개발 프로젝트 생성 절차

프로젝트 폴더를 만들어 VS.Code에서 오픈 후 package.json 파일 생성을 위해 터미널에서 다음 명령을 실행한 뒤에 생성된 파일을 편집함

npm init -y

{
  "name": "tstServer",
  "version": "1.0.0",
  "description": "",
  "keywords": [],
  "author": "",
  "license": "ISC"
}

nodemon 설치를 위해 다음 명령 실행

npm i nodemon -D

babel.config.json 파일과 nodemon.json 파일을 생성하고 각각 다음 내용으로 입력

{
    "presets": [ "@babel/preset-env" ]
}
{
    "exec": "babel-node src/index.js"
}

babel 설치를 위해 다음 명령 실행

npm i @babel/core @babel/cli @babel/node @babel/preset-env -D

express 설치를 위해 다음 명령 실행

npm i express

필요할 경우 pug 설치를 위해 다음 명령 실행

npm i pug

package.json에 설치된 항목에 대한 종속성(Dependency)가 존재하는지 확인하고 다음처럼 scripts 속성을 추가(또는 변경)

{
  "name": "tstServer",

  ..

  "scripts": {
    "dev": "nodemon"
  },

  "devDependencies": {
    "@babel/cli": "^7.20.7",
    "@babel/core": "^7.20.7",
    "@babel/node": "^7.20.7",
    "@babel/preset-env": "^7.20.2",
    "nodemon": "^2.0.20"
  },
  "dependencies": {
    "express": "^4.18.2",
    "pug": "^3.0.2"
  }
}

src 폴더 만들어 주고 index.js 파일 생성하고 다음처럼 입력

import express from "express";

const app = express();


const port = 7777;
const handleListen = () => console.log(`Listening on http://localhost:${port}`)
app.listen(port, handleListen);

다음 명령을 실행하여 서버 실행하고 웹브라우저에서 http://localhost:7777/로 접속해서 확인

npm run dev

Node.js에서 독립적인 프로세스를 통한 연산 및 그 결과 얻기

독립적인 프로세스를 통해 얻는 장점은 여러 개의 CPU를 활용하여 보다 더 빠른 결과를 얻을 수 있다는 점인데, 단점은 CPU 간의 데이터 공유가 참조(Reference)가 아닌 복사(Copy)이므로 메모리 사용량이 2배가 된다는 점이다. 하지만 이러한 단점은 특정한 상황에서는 아무런 문제가 되지 않는 경우가 있으므로 Node.js에서 독립적인 프로세스를 이용한 연산은 매우 유용한 경우가 많다.

먼저 독립적인 프로세스에서 수행할 코드는 worker.js 파일에 다음처럼 작성한다.

const process = require("process");

function getSum(arr) {
    let sum = 0;
    arr.forEach(i => {  sum += i; });
    return sum;
}

process.on("message", (message) => {
    if(message.cmd === "sum") {
        process.send({ result: getSum(message.data) });
    }
});

getSum이라는 함수를 처리하며 다른 프로세스로부터 전달 받은 데이터(배열 형태) 안의 숫자 값들의 합계를 전달해 준다.

이 worker.js를 사용하는 소스는 다음과 같다.

const cp = require("child_process");
const worker = cp.fork("./worker.js");

function task(arr) {
    return new Promise((resolve, reject) => {
        function onMessage(message) {
            resolve(message.result);
            worker.removeListener("message", onMessage);
        }

        worker.addListener("message", onMessage);

        worker.send({ 
            cmd: "sum",
            data: arr
        });
    })
}

task([1,2,3,4,5,6,7,8,9,10])
    .then((result) => {
        console.log(result);
        worker.kill();
    })
    .catch(err => {
        console.log(err);
    });

4번 코드에서 독립적인 프로세스에서 수행된 결과를 얻기 위해 Promise API를 사용했다는 점. 20번 코드에서 Prmoise의 일반적인 처리를 위해 then, catch를 사용하여 정상적인 경우와 예외처리를 하고 있다는 점이 코드의 완결성을 느끼게 해준다.