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;
}

#GWC UI Library : Grid

웹 UI 라이브러리인 GWC에서 제공하는 Grid 컴포넌트에 대한 예제 코드입니다.

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

그리고 CSS 구성은 다음과 같구요.

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

#grid {
    width: 500px;
    height: 300px;
}

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

window.onload = () => {
    grid.columns = [
        { name: "NO" },
        { name: "이름" },
        { name: "나이" },
        { name: "주소" },
        { name: "회사" },
        { name: "기타" }
    ];

    grid.data = [
        { values: ["1", "김영희", "30", "경기도 양평군", "초록마을", "온화하며 삶에 대한 여운을 느낄줄 아는 사람"] },
        { values: ["2", "홍길동", "40", "전라남도 여수시", "혜민당", "실존 인물을 모델로하여 쓰여진 소설의 주인공"] },
        { values: ["3", "심청", "15", "제주도", "임당수", "아버지의 눈을 낫게하기 위해 희생을 하는 계획 있는 효녀"] },
        ....
    ];

    grid.fixFirstColumn = true;

    grid.addEventListener("columnclick", (event) => {
        const v = grid.getColumn(event.detail.index).name;
        gwcMessage(`컬럼명: ${v}`);
    });

    grid.addEventListener("dataclick", (event) => {
        const v = grid.getData(event.detail.row, event.detail.column);
        gwcMessage(`데이터: ${v}`);
    });
};

실행 결과는 다음과 같습니다.

다음은 크기 조절과 이동이 가능한 Card 컴포넌트와 함께 사용된 예제입니다.

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


    

그리고 CSS 구성은 다음과 같구요.

.center {
    display: flex;
    width: 100%;
    height: 100%;
    justify-content: center;
    align-items: center;
    _flex-direction: column;
    gap: 1em;
}

#grid {
    width: calc(100% - 6px);
    height: calc(100% - 6px);
    margin: 3px;
}

gwc-card {
    left: 100px;
    top: 100px;
    width: 500px;
    height: 300px;
}

js 코드에 반드시 다음 코드를 추가해 줘야 합니다.

GeoServiceWebComponentManager.instance.update();

CAD 도면을 기반으로 한 3차원 모델링 및 사용자 인터렉션

건물 내부에 대한 정확 정보는 해당 건물에 대한 설계 도면입니다. 설계 도면 파일은 아래와 같은 CAD 도면(예시)을 이용하는데요.

위와 같은 도면을 아래처럼 3차원 모델로 제작할 수 있습니다.

위와 같이 제작된 3차원 모델 데이터를 웹에서 시각화하고 사용자 인터렉션을 통해 공간 상에서 원하는 위치로 이동할 수 있습니다.