var compression = require('compression')
var express = require('express')
var app = express()
app.use(compression())
--trace-sync-io
플래그를 사용하면 앱이 동기API를 호출하는 것을 확인할 수
있습니다.console.log()
와 console.error()
를 사용합니다. 하지만 이
함수들은 터미널 혹은 파일로 출력할 때 동기 함수들입니다. 그래서 배포할 때는
적합하지 않습니다.console.log()
보다는 debug를 사용하는 것이 좋습니다. 이 모듈은 DEBUG
환경 변수를 사용하고
앱이 비동기적으로 동작하도록 해줍니다.에외를 처리하지 않고 적적한 조치를 취하지 않으면 Express
앱은 다운되고
종료됩니다. 따라서 예외들을 적절히 처리해야합니다.
Node/Express는 두 가지 방식으로 에러를 처리합니다.
Node는 비동기 함수에서 첫 번째 인자로 에러를 반환하고 나머지 반환할 값들을
반환합니다. 만약 에러가 발생하지 않는다면 null을 첫 번째 인자로 반한합니다.
callback함수는 반드시 error-frist callback
컨벤션을 지켜야합니다.
Express에서는 next()
함수를 사용하여 에러를 전파하는 것이 best practice입니다.
에러처리에 대한 자세한 내용들은 다음을 참고하세요.
당신이하지 말아야 할 일 중 하나는 uncaughtException 이벤트를 수신하는 것입니다.
예외가 발생하면 예외가 이벤트 루프로 되돌아갑니다.
uncaughtException
을 event listener에 등록하는 것은 프로세스의 기본행동을
변경하게 됩니다. 그러면 프로세스는 예외가 발생해도 계속 실행하게 됩니다. 언듯
듣기에는 앱이 멈추는 것을 방지하기 떄문에 좋아 보이지만 예상치못한 에러가
발생했을 때 프로그램이 계속 실행되는 것은 굉장히 위험한 일입니다.
Try-catch는 동기 코드에서 예외를 catch하는 데 사용할 수있는 JavaScript 언어 구문입니다.
app.get('/search', function (req, res) {
// Simulating async operation
setImmediate(function () {
var jsonStr = req.query.params
try {
var jsonObj = JSON.parse(jsonStr)
res.send('Success')
} catch (e) {
res.status(400).send('Invalid JSON string')
}
})
})
하지만 Try-catch
는 동기코드에서만 동작합니다. Node
는 주로 비동기적으로
프로그램을 작성하므로 많은 예외를 처리하지 못합니다.
promise
들은 어떤 예외든 catch(next)
로 처리합니다.
app.get('/', function (req, res, next) {
// do some sync stuff
queryDb()
.then(function (data) {
// handle data
return makeCsv(data)
})
.then(function (csv) {
// handle csv
})
.catch(next)
})
app.use(function (err, req, res, next) {
// handle error
})
모든 동기, 비동기에러들이 에러미들웨어로 전파됩니다. 하지만 두가지 주의해야 할 것이 있습니다.
promise
를 맄턴해야합니다. 특정한 라이브러리가
promise
를 반환하지 않는다면 promise
로 변경해야합니다.const wrap = fn => (...args) => fn(...args).catch(args[2])
app.get('/', wrap(async (req, res, next) => {
let company = await getCompanyById(req.query.id)
let stream = getLogoStreamById(company.id)
stream.on('error', next).pipe(res)
}))
wrap()
함수는 reject된 promise들을 처리하고 next()
함수를 호출합니다.
NODE_ENV
환경변수는 어플리케이션이 동작하는 환경을 나타냅니다. 일반적으로
development
와 environment
가 있습니다.
성능을 올리는데 가장 간단한 것은 NODE_ENV
를 production
으로 설정하는
것입니다.
Express에서 NODE_ENV
를 production
으로 할 경우
Test indicate에서 테스트결과를 확인할 수 있습니다.
환경에 따라 다른 코드를 작성하고 싶다면 process.env.NODE_ENV
를 확인하여
작성할 수 있습니다.
production에서는 어플리케이션이 종료되는 것을 원치 않습니다. 만약 앱이 멈추면 앱은 재시작해야 합니다.
노드 애플리케이션은 처리되지 않은 예외가 있을 때 멈춥니다. 예외를 모두 처리하는 것이 더 중요하지만 만약 앱이 종료되었을 때 다시 시작하는 것이 필요합니다.
개발할 때는 CLI에서 서버를 실행시킵니다. 하지만 production에서 이렇게 하면 안됩니다. 앱이 멈추면 다시 시작할 떄 까지 서비스가 멈추게 됩니다. 앱이 멈추었을 때 다시 시작하도록 프로세스 매니저를 사용하는 것이 좋습니다. 프로세스 매니저는 애플리케이션들을 위한 컨테이너로 배포와 높은 가용성, 그리고 애플리케이션을 관리할 수 있도록 도와줍니다. 프로세스매니저는 단순히 앱을 재시작 하는 기능 뿐만 아니라 다음같은 기능들도 제공합니다.
가장 유명한 프로세스 매니저들은 다음과 같습니다.
서버가 재시작 될 때 애플리케이션 또한 재시작되어야 합니다. 시스템들은 여러가지 이유로 다운될 수 있기 때문에 서버가 재시작 될 때 애플리케이션도 또한 재시작 되어야 합니다. systemd와 Upstart가 가장많이 사용됩니다.
Systemd
는 리눅스 시스템의 서비스 매니저입니다. 대부분의 리눅스 배포판에서
기본으로 탑재되어 있습니다. systemd서비스 설정파일은 unit file
이고
.service
라는 이름으로 작성합니다.
[Unit]
Description=Awesome Express App
[Service]
Type=simple
ExecStart=/usr/local/bin/node /projects/myapp/index.js
WorkingDirectory=/projects/myapp
User=nobody
Group=nogroup
# Environment variables:
Environment=NODE_ENV=production
# Allow many incoming connections
LimitNOFILE=infinity
# Allow core dumps for debugging
LimitCORE=infinity
StandardInput=null
StandardOutput=syslog
StandardError=syslog
Restart=always
[Install]
WantedBy=multi-user.target
위의 예제는 직접적으로 node를 실행시킵니다.
쉽게 StringLoop PM
을 systemd service로 설치할 수 있는데 그러면 서버가 재시작
될 때 자등으로 StringLoop PM
을 실행할 것입니다.
StringLoop PM
을 systemd service로 설치하려면 다음과 같이 입력하면 됩니다.
$ sudo sl-pm-install --systemd
그리고 서비스를 재시작할 때는 다음과 같이 입력합니다.
$ sudo /usr/bin/systemctl start strong-pm
Upstart
는 만은 리눅스 배포판에서 사용가능한 시스템 도구 입니다. Express혹은
PM을 서비스로서 설정할 수 있고 Upstart
가 서버가 재시작 될 때 Express혹은 PM을
재시작 할 것입니다.
Upstart
서비스는 job설정파일로 정의되는데 .conf
로 끝나는 이름으로
작성됩니다. 밑의 예는 설정파일 예제입니다. myapp.conf
를 /etc/init/
에 만들고
다음과 같이 설정 할 수 있습니다.
# When to start the process
start on runlevel [2345]
# When to stop the process
stop on runlevel [016]
# Increase file descriptor limit to be able to handle more requests
limit nofile 50000 50000
# Use production mode
env NODE_ENV=production
# Run as www-data
setuid www-data
setgid www-data
# Run from inside the app dir
chdir /projects/myapp
# The process to start
exec /usr/local/bin/node /projects/myapp/index.js
# Restart the process if it is down
respawn
# Limit restart attempt to 10 times within 10 seconds
respawn limit 10 10
StrongLoop PM
을 Upstart
서비스로서 쉽게 설치할 수 있습니다. 서버가 재시작 될
때 자동으로 PM이 재시작 됩니다.
$ sudo sl-pm-install
설치 후 서비스를 실행시켜줍니다.
$ sudo /sbin/initctl start strong-pm
멀티코어 시스템에서 Node 애플리케이션의 프로세스들의 클러스터를 실행시켜 성능을 향상시킬 수있습니다. 클러스터는 앱의 인스턴스를 여러개 실행시켜 각 CPU core마다 하나의 인스턴스를 실행시켜 인스턴스의 부하를 줄일 수 있습니다.
자바스크립트로 직접 만들면서 배우는 - 자료구조와 알고리즘 강의 바로 가기
실습으로 마스터하는 OAuth 2.0: 기본부터 보안 위험까지 - OAuth 2.0 강의 바로 가기
기계인간 이종립, 소프트웨어 개발의 지혜 - Git 강의 바로 가기
코드숨에서 매주 스터디를 진행하고 있습니다. 메일을 등록하시면 새로운 스터디가 시작될 때 알려드릴게요!