NEMVV 3 웹서버 구동

3 분 소요

express의 기본 웹서버 틀을 약간 수정하여 구동해봅니다.

소스는 https://github.com/fkkmemi/nemvv.git에서 확인 할 수 있습니다.

서버 구동 사전 체크

./bin/www : 유효성 체크

#!/usr/bin/env node

const fs = require('fs');
const pkg = require('../package');
if(!fs.existsSync('./cfg/cfg.js')) {
  console.error('./cfg/cfg.js not exists');
  process.exit(1);
}
var cfg = require('../cfg/cfg');
var gb = require('../system/global.js');
let chk = gb.f.cfg.check(cfg);
if(chk !== 'OK') {
  console.error('./cfg/cfg.js file invalid ' + chk);
  process.exit(1);
}
/**
 * Module dependencies.
 */
var app = require('../app');
var debug = require('debug')(`${pkg.name}:server`);

기본적으로 cfg파일 유효성 체크를 했습니다.

var를 쓰는 이유는 최대한 express generated 된 코드는 건들지 않으려한 노력입니다.

서버 구동

./bin/www : 구동

if(cfg.web.http.use) {
  var http = require('http');
  var server = http.createServer(app).listen(cfg.web.http.port);
  server.on('error', onError);
  server.on('listening', onListening);
}

if(cfg.web.https.use) {
  var https = require('https');
  var o = {
    key: fs.readFileSync(cfg.web.https.key),
    cert: fs.readFileSync(cfg.web.https.cert),
    ca: [fs.readFileSync(cfg.web.https.ca)]
  }
  var servers = https.createServer(o, app).listen(cfg.web.https.port);
  servers.on('error', onError);
  servers.on('listening', onListenings);
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }
  var bind = `port ${cfg.web.http.port} or ${cfg.web.https.port}`

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('HTTP Listening on ' + bind);
}

/**
 * Event listener for HTTPS server "listening" event.
 */

function onListenings() {
  var addr = servers.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('HTTPS Listening on ' + bind);
}

http, https가 cfg파일대로 작동하는 것을 볼 수 있습니다.

별거 아닌 소스지만 혹시 ssl연결이 어려우신 분들이 참고하면 될 것 같습니다.

api, ssl등 전역처리

./app.js

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors = require('cors');
const cfg = require('./cfg/cfg');
const pg = require('./playGround');

if (!cfg) {
  console.error('./cfg/cfg.js file not exists');
  process.exit(1);
}

var app = express();

if(cfg.web.cors) {
  app.use(cors({
    exposedHeaders: ['WWW-Authenticate', 'Etag'],
  }));
}

app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json({ limit: '10mb' }));
app.use(bodyParser.urlencoded({ extended: false, limit: '10mb' }));
app.use(cookieParser());
app.use(function(req, res, next) {
  if (cfg.web.cors) return next();
  if (cfg.web.http.redirect && !req.secure) return res.redirect('https://' + req.headers.host + req.url);
  next();
});
app.use(express.static(path.join(__dirname, 'fe', 'dist')));
app.use(express.static(path.join(__dirname, 'public')));
app.set('jwt-secret', cfg.web.secret_key);
app.use('/api', require('./routes/api'));

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.send({ success: false, msg: err.message });
});

mongoose.connect(cfg.db.url, (err) => {
  if (err) return console.error(err);
  console.log('mongoose connected');
  pg.test.model();
});

module.exports = app;
  • cors 처리 cors는 다른위치에서 xhr 요청을 했을 경우 응답을 해줄 수 있게 해주는 것입니다. 문제는 app.use(cors())만 해주면 헤더는 가려진다는 것입니다. 헤더에 특별한 데이터를 실어보낼때는 위와 같이 원하는 필드를 넣으면 보여지게 됩니다. eg) exposedHeaders: [‘WWW-Authenticate’, ‘Etag’]

xhr은 일반적으로 쓰이는 ajax같이 문서 내에서 전달되는 요청입니다. 응답시 console.log(req.xhr)을 찍어보면 확인 할 수 있습니다.

  • ssl redirect 처리 res.redirect(‘https://’ + req.headers.host + req.url) http요청이 왔을때 https로 보냅니다.

서버를 https://xxx.com 로만 구성하면 좋지 않습니다. 그이유는 일반적으로 주소를 알려줄때 xxx.com이라고 알려줍니다. 브라우저마다 차이는 있지만 주소창에 xxx.com을 칠 경우 http://xxx.com으로 페이지가 없다고 뜰 수 있기 때문입니다. 그래서 http://xxx.com도 만들어 두고 https로 보내는 것이 좋다고 생각합니다.

댓글남기기