Node.js 새로운 프로젝트 생성

npm init -y
npm i express
npm i --save-dev nodemon
npm run devStart

위의 devStart가 의미를 가지려면 package.json 파일의 “scripts”의 값을 다음처럼 변경해야 합니다.

"scripts": {
  "devStart": "nodemon server.js"
},

Node.js에서 Thread 사용

서버 개발 시에 Node.js를 사용할 때 스레드를 이용해 사용자의 요청을 동시에 처리할 수 있습니다.

먼저 서버에 대한 기본 코드입니다.

const express = require("express");
const app = express();

app.get("/", (req, res) => {
    let total = 0;
    for(let i=0; i<10000000000; i++) {
        total++;
    }

    res.status(200).json({total});
});

app.listen(3000);

웹브라우저에서 localhost:3000으로 접속하면 몇초간 응답이 없다가 결과가 표시됩니다. 이 몇초간의 무응답은 서버의 모든 것들이 이 하나의 클라이언트 요청을 처리하는데 전념한다는 점입니다. 이 몇초간 또 다른 클라이언트의 요청이 들어온다면... 서버는 응답은 커녕 듣지도(listen) 못합니다.

이 문제를 개선하기 위한 코드를 살펴보면.. 먼저 위의 코드를 다음처럼 변경합니다.

const express = require("express");
const app = express();
const { Worker } = require("worker_threads");

app.get("/", (req, res) => {
    const worker = new Worker("./worker.js");
    worker.on("message", (data) => {
        res.status(200).json({total: data});
    })
});

app.listen(3000);

worker_threads라는 모듈을 추가했고 클라이언트 요청에 대한 연산을 worker.js로 분리시켰습니다. worker.js가 바로 스레드가 수행하는 코드이고 완료되면 message라는 이벤트가 호출되어 그 결과가 전달됩니다. worker.js의 코드는 다음과 같습니다.

const { parentPort } = require("worker_threads");

let total = 0;
for(let i=0; i<10000000000; i++) {
    total++;
}

parentPort.postMessage(total);

무거운 연산이 완료되면 parentPort.postMessage를 통해 결과를 전달합니다.

gwcConfirm, gwcMessage에 외부 UI(차트 예시) 넣기

사용자에게 정보를 전달하거나 의사를 묻는 gwcMessage와 gwcConfirm API에 어떤 메세지를 넣을 수 있습니다. 텍스트 메세지 뿐만 아니라 다양한 요소를 담을 수 있는데.. 그 중 차트를 넣기 위한 코드를 정리합니다. 참고로 차트는 gwc 라이브러리 요소가 아닌 chart.js라는 별도의 외부 라이브러리를 사용합니다.

먼저 만들고자 하는 UI는 다음 영상과 같습니다.

먼저 DOM 구성은 다음과 같습니다.

JS 코드는 다음과 같습니다.

window.onload = () => {
    button.onclick = event => { 
        const html = `
            
`; const dlg = gwcConfirm(html, () => { gwcMessage("'예'라고 답하다.") }, () => { gwcMessage("'아니오'라고 답하다.", true) }, () => { gwcMessage("'취소'라고 답하다.")} ); const ctx = dlg.querySelector("canvas"); const config = { type: 'line', data: { labels: ['빨강', 'Blue', 'Yellow', '초록', 'Purple', '오렌지'], datasets: [ { label: '색상', data: [7, 8, 5, 3, 2, 6], backgroundColor: 'yellow', borderColor: 'yellow', borderWidth: 2 }, { label: 'Color', data: [6, 7, 6, 4, 3, 5], backgroundColor: 'red', borderColor: 'red', borderWidth: 2 } ] }, options: { maintainAspectRatio: false, } } const chart = new Chart(ctx, config); setInterval(() => { const datasets = config.data.datasets; for (let iDataset = 0; iDataset < datasets.length; iDataset++) { const data = datasets[iDataset].data; for (let iValue = 0; iValue < data.length; iValue++) { data[iValue] += Math.random() * 0.4 - 0.2; } } chart.update(); }, 10); }; };

코드가 상당히 긴데... 3~15 라인만 gwc에 대한 코드이고 나머지 전부는 차트 구성을 위한 코드입니다.

CSS 코드는 다음과 같습니다.

.center {
    display: flex;
    width: 100%;
    height: 100%;
    justify-content: center;
    align-items: center;
    gap: 3em;
}

.chart-layout {
    width: 600px;
    height: 400px;
}

gwcCreateModalDialog의 resizing 코드 예 (JS 코드 최소화)

gwcCreateModalDialog에서 크기 조절 시 UI가 적절하게 배치되도록 하기 위한 코드를 정리해 봅니다.

먼저 만들고자 하는 UI는 다음 영상과 같습니다.

먼저 JS 코드는 다음과 같습니다.

class GeocodingTool {
    constructor() {
        const dlg = gwcCreateModalDialog("지오코딩");

        dlg.content = `
            
`; dlg.width = "70em"; // 크기 조절 기능을 위해서는 반드시 크기를 지정해줘야 함 dlg.height = "50em"; // 크기 조절 기능을 위해서는 반드시 크기를 지정해줘야 함 dlg.resizablePanel.minWidth = 550; dlg.resizablePanel.minHeight = 300; dlg.resizablePanel.resizableRight = true; dlg.resizablePanel.resizableBottom = true; dlg.show(); GeoServiceWebComponentManager.instance.update(); } }

CSS 코드는 다음과 같습니다.

.vertical-linear-layout {
    display: flex;
    flex-direction: column;
    gap: 0.3em;
}

.horizontal-linear-layout {
    display: flex;
    gap: 0.3em;
    flex-direction: row;
    _padding: 0 1em;
}

.v-center {
    align-items: center;
}

.h-center {
    justify-content: center;
}

.geocoding-tool-dialog {
    padding: 0.5em;
    height: 100%;
}

.geocoding-tool-dialog .content {
    height: 100%;
}

.geocoding-tool-dialog gwc-grid {
    flex: 1;
}

.geocoding-tool-dialog .address-column {
    width: 250px;
}

.geocoding-tool-dialog .run {
    margin-left: auto;
}