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 fix “this is undefined” in Vue.

Vue를 써보고 있는데, Vue 안에 method를 선언하고 this를 호출하니 undefined가 발생하였다.

export default {
  methods: {
    sayHello: () => {
    	this.val = 'hello';
    	console.log(this.val);
    }
  },
  data() {
	  return {
	  	val: ''
	  }
  }
}

#### 결과
this is undefined

원인을 찾아 보니 다음과 같은 내용을 확인했다.

If you try to access this from inside of an arrow function that’s on a Vue component, you’ll get an error because this doesn’t exist!

Vue 구성 요소에있는 화살표 함수 내부에서 this에 액세스하려고 하면 존재하지 않기 때문에 오류가 발생합니다!

Vue 구성 요소 안에서 this를 사용하려면 화살표 함수를 사용하지 말아야 한다는 내용이다. 다음과 같이 수정하면 잘 동작한다.

export default {
  methods: {
    sayHello() {
    	this.val = 'hello';
    	console.log(this.val);
    }
  },
  data() {
	  return {
	  	val: ''
	  }
  }
}

#### 결과
hello

화살표 함수는 익명 함수를 만들때 사용하며, 다음과 같은 이유로 사용됩니다.

  • 보다 짧고 응축된 구문
  • 향상된 가독성
  • this 주변상황에서 취해진다.

Vue의 method 내부에서 사용하는 것은 크게 문제가 없지만, method 자체를 화살표 함수로 선언할 경우 this를 사용할 수 없다.

# Vue 내부에서 화살표 함수 사용 예
data() {
  return {
    match: 'This is a message',
  };
},
computed: {
  filteredMessages(messages) {
    console.log(this); // Our Vue component
    
    const filteredMessages = messages.filter(
      // References our Vue Component
      (message) => message.includes(this.match)
    );
    
    return filteredMessages;
  }
}

참고 자료


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

댓글을 달아 주세요

80 port에 대하여 Root가 아닌 다른 계정으로 서비스 하기

보안 취약점으로 인해 서비스에 대한 기동을 root가 아닌 다른 계정으로 하라는 지침이 내려왔다.

하지만 1024 포트 이하에 대한 서비스 권한은 root만 가지고 있다. 기존에 했던 방법은 계정을 생성하고 root와 같은 그룹으로 묶어서 처리한 기억이 있다.

이번에 찾은 방법은 authbind라는 라이브러리를 이용 하는 방법이다.

예제는 pm2를 이용하였는데, 아마 생각은 다른 프로그램 역시 동작 할것이다.

우선 다음 명령어를 이용하여 authbind를 설치 하고 %user% 는 사용하려는 계정으로 바꿔서 진행하면 된다.

$> sudo apt-get install authbind
$> sudo touch /etc/authbind/byport/80
$> sudo chown %user% /etc/authbind/byport/80
$> sudo chmod 755 /etc/authbind/byport/80

그리고 변경해야 하는 내용은 사용하려는 서비스의 기동을 다음과 같이 하면 된다.

$> authbind --deep %명령어% 

일일이 치기 귀찮다면 다음과 같이 alias를 사용자 프로파일에 추가한다.

# ~/.bash 또는 ~/.zshrc
$> vi ~/.bash
# 가장 하단에 다음 내역 추가 
alias 명령어='authbind --deep 명령어'

# 프로파일 재반영
$> source ~/.bash

pm2를 예를 들면 다음과 같다.

# ~/.bash 또는 ~/.zshrc
$> vi ~/.bash
# 가장 하단에 다음 내역 추가 
alias pm2='authbind --deep pm2'

# 프로파일 재반영
$> source ~/.bash

pm2의 경우 update를 authbind를 이용하여 해야 한다.

$> authbind --deep pm2 update

추가적인 방법으로는 포트 포워딩을 이용하여 처리하는 방법도 있다.

참고자료


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

댓글을 달아 주세요