Express에서 post호출 시 request의 body에서 undefined가 발생한다.

다음과 같이 호출 했는데 결과가 undefined일 경우는 body-parser를 설정하지 않아서 이다.

# post 호출시, body에 {test:'hello"} 를 함께 전송

#router 소스
router.post('/', (req, res) => {
  console.log(req.body); undefined 발생
  res.redirect('/');
});

처리 방법은 body-parser를 express에서 사용하도록 설정 하면된다.

# body-parser 설치
$> npm install --save body-parser

#app.js 소스
const express = require('express');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser().json()); //bodyparser 사용 설정

이후 만나는 문제는 body의 크기가 크다는 오류를 만난 수 있다. 이때는 body의 크기를 옵션 설정하면 된다.

const bodyParser = require('body-parser');
app.use(bodyParser.json({limit: '50mb'})); //body 의 크기 설정
app.use(bodyParser.urlencoded({limit: '50mb', extended: true})); //url의 크기 설정

추가로 express 4.16부터는 body-parser를 포함 하고 있다.

const express = require('express')
const app = express();
app.use(express.json())
app.post('/', (req, res) => {
  console.log(req.body)
})

알아두자

참고 자료


Posted by lahuman

Node 모듈 설치시 오류시 해결 방법

node 버젼이 변경된 상태에서 npm install을 하면, 오류가 발생하는 경우가 있다.

이럴때 해결 방법은 정말 단순 하다.

해당 모듈을 삭제 하고 재설치 한다.

npm install
#oracle-db 모듈 오류발생

#oracle-db 모듈 삭제
npm uninstall oracle-db

#oracle-db 모듈 설치
npm install --save oracle-db

컴터 동작이 이상하면 재기동 하면 되듯이, 모듈도 재설치 하면된다.


Posted by lahuman

pm2 cluster mode 특징

NodeJS 2019.02.06 16:29

pm2 cluster mode에서는 session이나 websocket이 동작 하지 않는다.

pm2에서 제공하는 클러스터 모드는 코드의 수정 없이 CPU를 확장할 수 있다. Node.js 클러스터 모듈을 사용하여 확장 된 응용 프로그램의 하위 프로세스가 자동으로 서버 포트를 공유 하도록 하는 기능이다.

사용법은 다음과 같다.

# -i 옵션이 cluster 모드이며, max는 사용할 CPU 수를 입력 하면 된다.
# 0을 입력하면, 자동으로 모든 CPU 숫자만큼 클러스터가 생성된다.
pm2 start app.js -i max

또는 js/yaml/json 파일을 통해서 설정을 할 수 있다.

{
  "apps" : [{
    "script"    : "api.js",
    "instances" : "max",
    "exec_mode" : "cluster" 
  }]
}

Cluster Mode를 사용하면 가장 중요한게 stateless application이 된다는 것이다.

이 상태에서는 가중 중요한게 로컬 데이터 저장소를 프로세스에서 사용할수 없다는 것이다. 사용을 하고 싶으면, connect-redis과 같은 프로그램을 이용하면 된다.

Session이 동작하지 않아서 한참 해멧다.

참고자료


Posted by lahuman

Vuejs 배포시 route 동작 처리

vuejs에서 express로 배포하는 방식을 기존에 설명 했었다.

문제는 vuejs route에 주소를 직접 치고 들어가면 404 오류가 발생하였다.

express쪽에서 기본적인 요청은 vuejs의 route를 바라보게 하고 싶어서 검색을 해보니, Routes not working in production라는 글을 확인 하였다.

처리 방법은 express에 마지막 부분에 다음 코드를 추가 하면 된다. index.html은 vuejs를 배포한 위치이다.

app.get('*', (req, res) => {
  res.sendFile(`${__dirname}/public/index.html`);
});

vuejs도 잼나네!

참고 자료


Posted by lahuman

How To Use Winston to Log Node.js Applications

간단하게 설정만 작성하는 것으로 원본자료 How To Use Winston to Log Node.js Applications을 보세요.

var appRoot = require('app-root-path');
var winston = require('winston');

// define the custom settings for each transport (file, console)
var options = {
  file: {
    level: 'info',
    filename: `${appRoot}/logs/app.log`,
    handleExceptions: true,
    json: true,
    maxsize: 5242880, // 5MB
    maxFiles: 5,
    colorize: false,
  },
  console: {
    level: 'debug',
    handleExceptions: true,
    json: false,
    colorize: true,
  },
};

// instantiate a winston.createLogger with the settings defined above
var logger = winston.createLogger({
  transports: [
    new winston.transports.File(options.file),
    new winston.transports.Console(options.console)
  ],
  exitOnError: false, // do not exit on handled exceptions
});

// create a stream object with a 'write' function that will be used by `morgan`
logger.stream = {
  write: function(message, encoding) {
    // use the 'info' log level so the output will be picked up by both transports (file and console)
    logger.info(message);
  },
};

module.exports = logger;

요렇게 설정만 해놓아도 기본으로 사용이 가능하다.

추가로 알게된 App Root Path Module 도 꽤 유용해보인다.

app의 root path를 제공하여 다음과 같이 사용할 수 있다.

#1 
var appRoot = require('app-root-path');
var myModule = require(appRoot + '/lib/my-module.js');

#2
var reqlib = require('app-root-path').require;
var myModule = reqlib('/lib/my-module.js');

#3
// In app.js
global.reqlib = require('app-root-path').require;
 
// In lib/module/component/subcomponent.js
var myModule = reqlib('/lib/my-module.js');

#4
var myModulePath = require('app-root-path').resolve('/lib/my-module.js');

좋은게 많은데 몰라서 못쓴다.

공부 많이 좀 해야겠다. 요즘 게을러져서 공부도 안하고 그냥 날로 먹을라고 한다.

참고 자료


Posted by lahuman

이번에 함께 일하시는 분의 코드를 리펙토링하며 의견을 나누었다.

이번에 함께 일하는 분의 코드 리펙토링을 진행 하였다.

유지보수 가능한 코딩의 기술 자바편의 내용을 기준으로 리펙토링을 하였다.

하나의 메소드를 15라인을 넘지 않도록 하고 결과를 확인하니, 너무 세분화 하여 쪼갠 느낌이다.

하나의 메소드는 하나의 역활만 하도록 하고, 중복된 코드가 없도로 했다.

const __DEFAULT_SELECTBOX_STR = "선택해주세요";
const __ORDER_SELECT_BOX = ['cls-l', 'cls-m', 'cls-s', 'cls-d'];

const removeAllOptions = (isRemove, target) => {
    if(isRemove){
        target.find('option').remove();
        target.append(new Option(__DEFAULT_SELECTBOX_STR, ""));
    }
}

const resetSubSelectBoxOption = (target_id) => {
    let target_obj;
    let isResetSelectBox = false;
    __ORDER_SELECT_BOX.forEach(v => {
        target_obj = $("#"+v);
        if(v === target_id){
            isResetSelectBox = true;
        }
        removeAllOptions(isResetSelectBox, target_obj);
    });
}

const setClassification = (target, val, level) => {
    callClassification({'upper_prd_cls_cd' : val, 'cls_lvl_no' : level}, (res)=>{
        res.forEach(element => {
            target.append(new Option(element.PRD_CLS_NM, element.PRD_CLS_CD));
        });
    }); 
}

const setSubSelectBoxOption = ($target, val, level) => {
    resetSubSelectBoxOption($target.attr("id"));
    if (val === "") return;
    setClassification($target, val, level);
}

const setInitValue4SelectBox = (target, i) => {
    removeAllOptions(true, target);
    if (i === 0){
        setClassification(target, "", 1);
    }
}

const bindEventOnSelectBox = (target, i) => {
    if (i !== (__ORDER_SELECT_BOX.length-1)) {
        target.change(function() {
            setSubSelectBoxOption($("#"+__ORDER_SELECT_BOX[i+1]), $(this).val(), (i+2));
        });
    }
}

const initSelectBox = () => {
    __ORDER_SELECT_BOX.forEach((o, i) => {
        let target = $("#"+o);
        setInitValue4SelectBox(target, i);
        bindEventOnSelectBox(target, i);
    });  
    
}

$(document).ready(function() {
    initSelectBox();  
});

전체 diff로 원본 소스와 리펙토링된 소스 비교

이후 처리로 ESLINT와 TDD를 샘플링 해볼 예정이다.

한걸음 한걸음씩


Posted by lahuman

ORA-21561 OID generation failed

어제까지 문제가 없었는데 갑지가 node에서 Oracle 연결시 다음과 같이 오류가 발생 하였다.

> node ./bin/www
ORA-21561: OID generation failed

검색을 해보니 호스트네임의 문제라고 한다.

다음과 같이 해주면 처리가 된다.

echo "127.0.0.1 $(hostname)" | sudo tee -a /etc/hosts

그러면 /etc/hosts에 한줄이 추가 되고 재기동 하면 접속에 성공했다는 메시지를 확인할 수 있다.

> node ./bin/www
Connection was successful!

하루에 하나 이상은 배우는 구나!

참고자료


Posted by lahuman

node.js에서 버젼 변경 하기

오늘 특정 프로젝트를 받아서 빌드를 진행하는데 오류가 발생하였다.

$> npm install
.... 모듈 오류 발생 ...

원인은 node 버젼이 내 PC에 설치된 것은 11.x 이고 해당 모듈은 8.x 에서만 동작하였다.

버젼 변경을 어찌 해야하는지 고민하는 차에 함께 일하시는 분이 n 이라는 모듈을 이용하면 된다고 알려 주셨다.

# 설치 
$>sudo  npm install -g n

# Node 버전 중 설치된 버전 확인
$> n ls  

# Node 버전 설치  
$> n <version>  
# ex> n 8.13

# 최신 LTS Node 버전 설치
$> n latest  

# 제거할 Node 설정
$ n rm <version ...>  
#ex> n rm 8.9.1 8.9.2

# 현재 버전을 제외한 모든 버전 제거
$ n prune  

참고 주소


Posted by lahuman

node.js에서 global로 선언하는 2가지 방법

node.js를 이용하여 개발을 진항하는 중, static 변수 또는 전체 전역 클래스로 사용해야 하는 경우가 발생하였다.

node.js 사용한지 3주 밖에 안되어서 여러 가지를 검색 하였으나, 어떤 방식이 가장 좋은지 몰라 옆에서 일하시는 분에게 여쭤보았다.

두가지 방법을 알려주셨는데 다음과 같다.

  • global을 이용하는 방식

이 방법은 가장 간단하다 다음과 같이 어디서든 global에 추가를 해주면 된다.

//app.js
// global.변수명 = 사용하려는 변수명
let running = false;
global.running = running;


//test.js
//이후 다른 js에서 다음과 같이 사용 하면된다.
console.log(running);
running = false;
console.log(running);

해당 js 파일에 선언한 것과 같이 사용 할 수 있다.

  • require 를 이용하는 방식

이 방법은 node.js에서 require를 이용하여 call을 할 경우 cache 되는 것을 이용한다.

# test.js
module.exports = {running: true}

# app.js
let test = require('test.js');
test.running = false;
console.log(test.running);

노드가 재미 난다!

참고자료


Posted by lahuman