본문 바로가기

프로그램 개발

node.js + express.js 로 만드는 Edge Server; 2. Request Handler + MongoDB

node.js + express.js 로 만드는 Edge Server

1. 시작하기

2. Request handler + MongoDB

5. Request Handler 만들기 - v1

  • common.js vs ECMAScript

node.js로 작업할 때 라이브러리 모듈을 사용하는 방법은 common.js방식인 require를 사용하는 방법과 ECMAScript방식인 import를 사용하는 2가지 방법이 있다. ECMAScript방식을 사용하기 위해서는 HTML에서는 script태그에 type을 module로 선언하면 되고,

<script type="module">

 

node.js서버 프로그램에서는 package.json파일에 type: module이라고 선언하면 된다.

{
	...
	type: module,
	...
}

express-generator가 만든 파일은 모두 common.js방식의 require를 사용하고 있기 때문에, ECMAScript방식으로 바꾸려면 /bin/www와 app.js파일을 바꿔주면 된다. 지금 만들려고 하는 프로그램은 작은 기능만을 사용하여 간단한 처리를 하는 프로그램이어서 현재는 common.js방식에 따라 만들 예정이다. 테스트가 끝나고 기능을 확장하기 전에는 SCMAScript와 typescript방식으로 바꿀 예정이다.

 

  • nodemon 설치하기

node.js와 express.js로 프로그램을 작성하면 기본적으로 프로그램이 변경되면 프로그램을 정지하고 다시 시작하지 않으면 변경사항이 반영되지 않는다. 이런 문제를 해결하기 위해 nodemon을 설치한다.

 

nodemon

Simple monitor script for use during development of a Node.js app.. Latest version: 2.0.22, last published: 19 days ago. Start using nodemon in your project by running `npm i nodemon`. There are 4450 other projects in the npm registry using nodemon.

www.npmjs.com

 

npm i nodemon --save-dev

--save-dev는 nodemon이 개발될 때에만 이용되고 운영환경에서는 사용하지 않는다는 옵션이다.

 

이제 nodemon을 설치했으니 package.json파일에서 script / start에 있는 node명령어를 nodemon으로 바꿔 nodemon이 실행을 관리하도록 만든다.

{
	...
	"scripts": {
		"start": "nodemon --watch api ./bin/www"
	},
    ...
}

중간의 --watch api는 nodemon이 모니터링할 폴더가 ./api라는 것을 알려준다. 만일 nodemon으로 실행했는 데에도 파일이 변경되었을 때 node.js프로그램이 restart 되지 않으면 node.js가 실행되고 있는 console에 rs를 입력하고 엔터키를 누르면 수동으로 restart 된다.

 

  • 이제 첫 번째 /sensor/get과 /sensor/save에 해당하는 request handler를 각각 express.js의 router에 등록한다.
var express = require('express');
var sensorRouter = express.Router();

sensorRouter.get('/sensor/get', function(req, res, next) {
    res.send('respond with a resource');
});

sensorRouter.post('/sensor/save', function(req, res, next) {
    res.send('respond with result');
})

module.exports = sensorRouter;

node. start명령으로 실행하고 curl명령을 사용해 테스트했을 때,

## 서버에서 (VSCode의 터미널에서 실행하면 된다.)
node start

## 테스트할 콘솔에서
curl -X GET http://localhost:3000/api/sensor/get
curl -H "content-type: application/json" -d "{}" -X POST http://localhost:3000/api/sensor/save

다음과 같은 결과를 얻을 수 있다. (git-bash에서 실행한 결과이다.)

 

6. MongoDB DAO 만들기

 

  • 먼저, mongodb.com에서 무료로 mongodb 서버를 만들거나,
 

MongoDB: The Developer Data Platform

Get your ideas to market faster with a developer data platform built on the leading modern database. MongoDB makes working with data easy.

www.mongodb.com

 

  • docker를 이용해서 MongoDB를 설치한다.
 

윈도우 개발 환경 시작하기; 6. Docker로 MongoDB 시작하기

윈도우 개발 환경 시작하기 목차 1. 우분투 리눅스 설치 2. Docker 설치 3. 설치속도 개선 후 node.js 설치 4. VScode 설치 5. Docker로 MySQL시작하기 6. Docker로 MongoDB 시작하기 1. MongoDB에 대해 현재 NoSQL DB (SQL

front-it.tistory.com

 

  • .env파일을 사용하기 위해 dotenv모듈을 설치한다.

이제 환경변수를 사용해서 mongodb에 연결할 connection URL을 만들고 .env파일에 저장한다. .env환경 파일을 만들어 계정정보를 저장하면 GitHub에 저장할때 .env파일만 .gitignore에 등록해서 정보를 숨길 수 있기 때문에 민감정보는 모두 .env파일에 등록하는 것이 편리하다. 이렇게 .env파일을 좀 더 편리하게 사용하기 위해서는 dotenv 모듈을 설치하면 된다.

npm install dotenv

 

  • .env파일에 mongodb URL을 등록한다.

프로젝트의 최상위 위치에 .env을 만들고 내 컴퓨터에 docker로 등록한 경우 아래 내용을 넣는다.

MONGODB_URI="mongodb://localhost:27017"

mongodb.com에 서버를 만든 경우

MONGODB_URI = "mongodb+srv://userid:password@cluster0.csexlvc.mongodb.net/?retryWrites=true&w=majority"

이런 형태의 URL을 등록할 것이다.

 

  • DAO (Data Access Object)를 만든다.
require('dotenv').config();
var mongodb = require('mongodb');

var MONGODB_URI = process.env.MONGODB_URI;

if (!MONGODB_URI) {
    throw new Error('MONGODB_URI is not defined.')
}

var dao = {
    getClient: async function() {
        var client = new mongodb.MongoClient(MONGODB_URI);
        return client;
    },

    getSensorValues: async function() {
        var client = await this.getClient();
        try {
            var db = client.db('hydroponix');
            var data = await db.collection('sensor_value').findOne();
            return data;
        } finally {
            await client.close();
        }
    },

    saveSensorValues: async function(data) {
        var client = await this.getClient();
        try {
            var db = client.db('hydroponix');
            data.time = new Date();
            var result = await db.collection('sensor_value').insertOne(data);
            return result;
        } finally {
            await client.close();
        }
    }
}

module.exports = dao;

5. Request Handler 만들기 - v2

var express = require('express');
const dao = require('./dao/sensorDao');

var sensorRouter = express.Router();

sensorRouter.get('/sensor/get', async function(req, res, next) {
    var data = await dao.getSensorValues();
    res.send(data);
});

sensorRouter.post('/sensor/save', async function(req, res, next) {
    var data = req.body;
    var result = await dao.saveSensorValues(data);
    if (result.acknowledged) {
        res.send('OK');
    } else {
        res.status(400).send('save failed.');
    }
})

module.exports = sensorRouter;

POST 방식의 경우 express서버가 지원하는 데이터 형식이

 

  • application/json
  • application/x-www-form-urlencoded
  • multipart/form-data

의 3가지 형식만을 지원하기 때문에 content-type을 application/json으로 지정해서 테스트하는 것이 좋다.

 

이제 다시 curl을 사용해서 테스트해 보면