https://goodgid.github.io/Server-Side-Rendering-and-Client-Side-Rendering/




서버 사이드 렌더링(SSR)과 클라이언트 사이드 렌더링(CSR)

2018-10-26
goodGid

렌더링이란?

  • 어떠한 웹 페이지 접속시 그 페이지를 화면에 그려주는 것이다.

SSR

  • SSR : Server Side Rendering

  • 요청시마다 새로고침이 일어나며 서버에 새로운 페이지에 대한 요청을 하는 방식이다.


CSR & SPA

  • CSR : Client Side Rendering

  • SPA : Single Page Application

  • 모바일 시대가 도래하면서 모바일 환경에 최적화된 서비스가 필요해졌다.

  • 일반적인 컴퓨터에 비해 성능이 낮은 모바일에 최적화시키기 위해선 기존과는 다른 방법이 필요했다.

  • 그래서 나온 개념이 SPA(Single Page Application)이다.

  • SPA는 브라우저에 로드되고 난 뒤에 페이지 전체를 서버에 요청하는 것이 아니라
    최초 한번 페이지 전체를 로딩한 이후 부터는 데이터만 변경하여 사용할 수 있는 웹 애플리케이션을 의미한다.

  • 전통적인 웹 방식인 SSR은 SPA에 비해 성능이 뒤떨어졌다.

  • 그 이유는 요청 시 마다 서버로부터 리소스를 받아 해석하고 화면에 렌더링하는 방식이기 때문이다.

  • 이러한 점에 의해 SPA는 트래픽을 감소시키고 사용자에게 최적화된 환경을 제공할 수 있게 되었다.

  • 서버는 단지 JSON 파일만 보내주는 역할을 하며
    html을 그리는 역할은 클라이언트 측에서 자바스크립트가 수행하였다.
    그리고 이것이 클라이언트 사이드 렌더링(Client-side rendering)이다.


주의할 점

  • 전통적인 웹 페이지 방식 != SSR

  • SPA != CSR

  • 전통적인 웹 페이지 방식이 SSR 방식을 사용한 것이고
    SPA가 CSR 방식을 사용한 것이다.


SSR vs CSR

초기 View 로딩 속도

  • SSR의 경우 View를 서버에서 렌더링 하여 가져오기 때문에 첫 로딩이 매우 짧다.

  • 물론 JS파일을 모두 다운로드하고 적용하기 전까지는
    그 어떤 인터랙션에도 반응하지 않지만 사용자 입장에서는 로딩이 매우 빠르다고 느낄 수 있다.

  • 반면 CSR의 경우 서버에서 View를 렌더하지 않고
    HTML 다운 + JS파일 + 각종 리소스 다운을 받은 후 브라우져에서 렌더링을 하기 때문에
    SSR보다는 초기 View 로딩 속도는 오래걸린다.

  • 그렇지만 CSR의 경우 사용자의 행동에 따라 필요한 부분만 다시 읽어들이기 때문에
    서버 측에서 렌더링하여 전체 페이지를 다시 읽어들이는 것보다 빠른 인터랙션이 가능하다.

  • 하지만 문제도 존재한다.

  • CSR은 페이지를 읽어들이는 시간 + JS를 읽어들이는 시간 + 그리고 JS가 화면을 그리는 시간
    위 작업이 완료 후 콘텐츠가 사용자에게 보여진다.

  • 여기에 웹 서버에서 콘텐츠 데이터라도 가져와야 한다면 그 시간은 더욱 길어진다.

  • 즉 초기 구동 속도가 느리다는 단점이 존재하는 것이다.

  • 물론 초기 구동 속도를 제외하면 그 다음부터는 빠른 인터랙션의 성능을 보인다.


SEO 문제

  • SEO(검색 엔진 최적화)의 문제가 존재한다.

  • CSR방식으로 이루어진 사이트에서는 View를 생성하기위해 자바스크립트를 실행시켜야 한다.

  • 하지만 대부분의 웹 크롤러 봇들은 자바스크립트 파일을 실행시키지 못한다.

  • 때문에 HTML 에서만 콘텐츠를 수집하게 되고 CSR 페이지를 빈 페이지로 인식하게 된다.


보안 문제

  • SSR에서는 사용자에 대한 정보를 서버 측에서 세션으로 관리를 했다.

  • 그러나 CSR일 경우 쿠키말고는 사용자에 대한 정보를 저장할 공간이 마땅치 않다.


정리

  • SSR의 경우 초기 로딩속도가 빠르고 SEO에 유리하지만
    View 변경시 서버에 계속 요청을 해야 하므로 서버에 부담이 크다.

  • CSR의 경우 초기 로딩속도는 느리지만
    초기 로딩 후에는 서버에 다시 요청할 필요없이 클라이언트 내에서 작업이 이루어지므로 매우 빠르다.
    하지만 SEO에 대한 문제가 있다.

  • 추가로 SSR과 CSR MVC 구조를 가볍게 눈에 익혀두자.


참고


Similar Posts



https://jungwoon.github.io/node.js/2017/08/01/ejs/

먼저 템플릿 사용이유를 알아봅시다.

템플릿 예시) 네이버
템플릿 예시) 다음

첫 번째 사진과 두 번째 사진을 보시면 공통적인 부분이 있는데요. 바로 이런 것이 바로 템플릿입니다. 사용자에 요청에 따라 응답하는 내용은 다르지만 제목, ui 가 같은 걸 알 수 있습니다.   만약 html으로 만든다면 사용자에 요청에 따라 매번 다른 html 파일로 응답해야 합니다. html을 정적이고 html템플릿은 동적이라고 알 수 있습니다.

  이 글은 ejs 템플릿을 나타냅니다. ejs는 html을 안다면 아주 쉽게 알 수 있습니다. 
우선 npm install express --save , npm install ejs --save 로 추가해야합니다.

node.js 에서 플랫폼 사용법
<!DOCTYPE html> <html> <head> <% include ../part/header %> </head> <body> example ejs <footer> <% include ../part/footer %> </footer> </body> </html>
include ../part/header
<meta charset="utf-8"> <title>ejs example</title>
include ../part/footer
<a href="http://blog.naver.com/rwans0397">ejs 예제</a>

우선 각파트들을 나누어서 실제 출력파일들에게 include합니다. 이렇게 include 한다면 모든 페이지마다 일일이 선언할 필요가 줄어듭니다. 

이번엔 node.js에서 출력하는 법을 알아봅시다.

express 사용시 npm install express --save 를 해야합니다.
var express = require('express'); var app = express(); app.set('view engine','ejs'); app.set('views','./views'); app.get('/',function(req,res){ res.render('view'); });

익스프레스를 실행한뒤 set 메서드로 사용할 파일들을 설정합니다. html템플릿파일을 사용하려면  4번째줄과 5번째줄은 필수적입니다.
 익스프레스는 html템플릿파일에 기본주소값을 ./views 으로 지원합니다. 플랫폼을 랜더할때는  ./views를 생략가능합니다.
'/'으로 접속하면 res.render('view'); 을 실행합니다. res는 응답한다라는 뜻이고  render는 플랫폼을 웹페이지에 표시합니다.

이번엔  어떻게 동적으로 하는지 알아봅시다. 

//app.js var express = require('express'); var app = express(); app.set('view engine','ejs'); app.set('views','./views_ejs'); app.get('/',function(req,res){ res.render('view',{data:'kim'}); }); app.get('/next',function(req,res){ res.render('view',{data:'lee'}); }); app.get('/next/:id',function(req,res){ res.render('view',{data:'park'}); }); app.listen(3000,function(){ console.log('hello ejs'); });
//view.ejs <!DOCTYPE html> <html> <head> <% include ../part/header.ejs %> </head> <body> example ejs <h1><%= data %></h1> <footer> <% include ../part/footer %> </footer> </body> </html>

동적인 html템플릿은 어떻게 하는걸까요? 그건바로 언어로 합니다. ejs에는 자바스크립트로 합니다. <% %>,<%= %> 이 두가지 태그안에 자바스크립트 코드를 넣어 사용합니다. <% %>태그는 일반적인 자바스크립트를코드를 사용할때 사용합니다.

<% if(data) %> <li> <%= data %> <li>

위 코드를 보시면 알수있드시 <%= %> 태그는 res.render('view',data);에서 보낸 변수를 사용할때 사용합니다.

ejs 템플릿 실행 결과
ejs 템플릿 실행 결과
ejs 템플릿 실행 결과

이렇게 템플릿은 한개의 템플릿으로 여러 페이지를 나타낼수있습니다. 템플릿은 데이터베이스와 같이 사용하는데요 데이터베이스에 값을 조회해서 템플릿으로 보내 다양한 내용을 나타낼수있습니다.

ejs 템플릿 더 알아보기






npm とは

  • Node Package Manager の略。
  • JavaScript 系のパッケージを管理するツール。
  • 必要とするパッケージをインストールする際、依存するパッケージもまとめてインストールしてくれる。
  • ライセンスは Artistic License。GPL に似ているが、改造版を再配布する際に名称変更が必要な点が異なる。
  • npm パッケージを集めたリポジトリ (npmjs.com) が運営され、40万ものパッケージが登録されている。

インストール

npm のインストール方法は Node.js のインストール を参照してください。

ヘルプ・バージョン

ヘルプを表示します。

$ npm help
$ npm --help
$ npm help コマンド
$ npm -h コマンド

npm のバージョンを表示します。

$ npm -v
$ npm --version
$ npm version

プロジェクトディレクトリを作成する

npm で管理するプロジェクトディレクトリを作成します。package.json ファイルが生成されます。

$ mkdir my-app
$ cd ./my-app
$ npm init
(略)
package name: (my-app) [Enter]
version: (1.0.0) [Enter]
description: [Enter]
entry point: (index.js) [Enter]
test command: [Enter]
git repository: [Enter]
keywords: [Enter]
author: [Enter]
license: (ISC) [Enter]
(略)
Is this ok? (yes) [Enter]
$ ls -l
-rw-rw-r--.  1 taro taro   298 Jan 18 00:05 package.json

パッケージインストール

カレントディレクトリ配下にインストールします。package.json ファイルが存在するディレクトリで実行します。

$ npm install パッケージ

install の代わりに省略形の i も指定可能です。

$ npm i パッケージ

バージョンを指定してインストールします。

$ npm install パッケージ@x.y.z

-g をつけるとグローバルインストールとなり、システムディレクトリにインストールされます。

$ npm install -g パッケージ
ローカルインストール
カレントディレクトリの node_modules 配下にインストールします。
グローバルインストール
システムディレクトリの node_modules 配下にインストールします。Node.js を yum でインストールしている場合は /usr/lib/node_modu、nodebrew でインストールしている場合は ~/nodebrew/node/バージョン/lib/node_modules 配下などにインストールされます。パッケージに依存するライブラリはローカルインストール、開発時に共通で利用するツールはグローバルインストールするケースも多い様です。

インストール後、package.json へのパッケージ情報追記を制御するには下記のオプションをつけます。

$ npm install パッケージ --no-save            // npm5~
$ npm install パッケージ --save
$ npm install パッケージ --save-optional
$ npm install パッケージ --save-dev
--no-save
package.json に書き込まない場合に指定します。npm4 までは package.json に書き込まないのがデフォルトでしたが、npm5 からは --save がデフォルトとなりました。
--save
依存パッケージの場合に指定します。package.json の dependencies に記録されます。このパッケージを誰かが npm install したときに依存パッケージとしてインストールされます。
--save-optional
依存はするけれど必須ではないパッケージの場合に指定します。package.json の optionalDependencies に記録されます。npm install でインストールされますが、インストールに失敗してもスルーされます。
--save-dev
テストツールなど、開発者が使用するパッケージの場合に指定します。package.json の devDependencies に記録されます。このパッケージを npm install しても、インストールされません。ただし、パッケージを Git から clone して npm install した場合は開発者とみなされ、インストールされます。

package.json に記述されたパッケージを再度インストールするには、package.json が存在するディレクトリで下記を実行します。

$ ls -l
-rw-rw-r--.  1 taro taro   265 Jan 18 01:41 package.json
$ npm install

ただし、インストールされるバージョンは、package.json 記載されたものではなく、最新版がインストールされます。固定のバージョンをインストールするには、npm4 までは shrinkwrap を利用していましたが、npm5 以降では package-lock.json ファイルを使用します。

$ ls -l
-rw-rw-r--.  1 taro taro 14032 Jan 18 01:41 package-lock.json
-rw-rw-r--.  1 taro taro   265 Jan 18 01:41 package.json
$ npm install

また、npm install では、インストールしたバージョンは、--save オプションをつけても package.json ファイルに反映されません。インストールしたパッケージのバージョンを package.json ファイルに反映するには後述の npm-check-updates を利用します。

パッケージ情報

インストール済のパッケージの一覧を表示する

$ npm list
$ npm ls
$ npm la
$ npm ll

グローバルインストールされたパッケージの一覧を見る

$ npm list -g

第一階層のパッケージ(直接インストールしたパッケージ)のみを表示する。

$ npm list --depth=0

パッケージアップデート

インストール済みのものより新しいものがないか確認する。

$ npm outdated
$ npm outdated -g

パッケージをアップデートします。

$ npm update パッケージ
$ npm update パッケージ -g

パッケージ名を省略すると、package.json に記述されたすべてのパッケージをアップデートします。

$ npm update

一括アップデートには、npm-check-updates を使用することもあります。

$ npm install -g npm-check-updates     // ncu をインストールする
$ ncu                                  // アップデート情報を表示する
$ ncu -u                               // アップデート情報を package.json に書き込む
$ npm install                          // 更新された package.json に従いアップデートする
$ ncu パッケージ名                        // 特定のパッケージのみを調べる
$ ncu -x パッケージ名                     // 指定したパッケージを除外する
$ ncu '/^xyz-.*$/'                     // xyz- で始まるパッケージのみを調べる

パッケージアンインストール

アンインストールする

$ npm uninstall パッケージ
$ npm uninstall パッケージ -g

アンインストールの結果を package.json に記録します。

$ npm uninstall --save
$ npm uninstall --save-optional
$ npm uninstall --save-dev

uninstall の代わりに省略系の rm でも可能

$ npm rm パッケージ

パッケージ検索

キーワードに関連するパッケージを npm リポジトリから検索します。

$ npm search パッケージ

パッケージの詳細情報を表示します。

$ npm info パッケージ
$ npm view パッケージ
$ npm show パッケージ

パッケージのバージョンを表示します。

$ npm info パッケージ version  // 最新バージョンを表示
$ npm info パッケージ versions  // インストール可能なバージョン一欄を表示

タスク実行

タスクは package.json の scripts: に記述しておきます。

{
  "scripts": {
    "clean": "rimraf dist/*",
    "build": "npm run clean && tsc",
    "lint": "tslint ./src/**/*.ts --project tsconfig.json",
    "start": "pm2 start pm2config.yaml --env production",
    "test": "jest --coverage"
  }
}

タスクを実行するには run コマンドを使用します。

$ npm run build

引数なしで実行すると、タスクの一覧を表示します。

$ npm run

よく使用されるタスクには下記のものがあります。

$ npm run build   // プロジェクトをビルドします
$ npm run watch   // ファイルの更新を監視し、更新されたら自動ビルドします
$ npm run serve   // 評価用テストサーバを起動します

さらに、複数のタスクを自動実行するには、Grunt や Gulp などのタスクランナーを使用します。

ディレクトリ

ローカル、グローバルのルートディレクトリ、コマンドディレクトリを表示します。

$ npm root
$ npm root -g
$ npm bin
$ npm bin -g



パッケージ生成

該当プロジェクトのPackage化

$ npm pack

.npmignorebにファイルやディレクトリを追加すると記載のものは外してパック化する。



ショートカット

下記のショートカットを利用することができます。

コマンドショートカット
installi
uninstallrm r remove rm un unlink
listls
searchs se
--global-g
--save-S
--save-dev-D


PM2とは

PM2とは、Node.js製のWebアプリケーションを動かすための仕組みの一つです。例えば、Express4などで作成したアプリ(app.js)を動かしたい場合に普通だと、

$ node app.js

として起動しますが、PM2を用いると、

$ pm2 start app.js

のような形式でWebサービスを起動することができます。

node app.jsでの起動は非常にシンプルですが、以下のような問題点があります。

  • 基本的にはCPU1コアしか使えず、マルチコアに対応するのに手間がかかる
  • ログ出力や状態チェックなど自前で作る必要がある
  • その他、本番運用のための細かな手間がある

などなど。PM2を用いると、例えばCPUコア数を自動的に考慮して複数インスタンスを起動してくれるなど、便利な点が多いです。

同様の本番環境で使える起動ツールとしては、foreverなどがありますが、最近ではPM2が便利でよく使われている印象です。



今回のコードの置き場

以下におきましたので、必要あればご参照いただけたら幸いです。
https://github.com/yoheiMune/node-playground/tree/master/010-pm2

今回は、以下のようなExpress4で作成された簡単なアプリケーションを例に、話を進めます。

// app.js

const express = require('express');
app = express();

app.get('/', (req, res) => {
    res.send('Hello from index.');
});

app.listen(3000, () => {
    console.log('Express app starts, linstening port on 3000.')
});




PM2のインストール

npmから簡単にインストールすることが可能です。

# PM2をインストール
$ npm install -g pm2

インストール後に、以下のコマンドが認識されていればOKです。

$ pm2




PM2を使う

それではここから、pm2の基本的な使い方を見てみたいと思います。


起動する

起動するにはstartコマンドを利用します。


(환경변수를 삽입해 pm2가동하기는 http://valuefactory.tistory.com/258?category=765146 참고)

# pm2 start [スクリプトファイルパス]
$ pm2 start app.js
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
 App name  id  mode  pid    status  restart  uptime  cpu  mem        watching 
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
 app       0   fork  42728  online  0        0s      0%   15.3 MB    disabled 
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘

# --nameオプションをつけると、起動するアプリに名前をつけることができます。
# 今後の管理にも使うので、基本的には名前を明示的につけるのが良いです。
$ pm2 start app.js --name myapp
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
 App name  id  mode  pid    status  restart  uptime  cpu  mem        watching 
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
 myapp     0   fork  42882  online  0        0s      0%   13.4 MB    disabled 
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘



再起動する

デプロイなどでコードが変わる場合に、restartコマンドでサーバーを再起動して、変更を取り込むことができます。

# pm2 restart [アプリ名]
$ pm2 restart myapp
[PM2] Applying action restartProcessId on app [myapp](ids: 0)
[PM2] [myapp](0) 
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
 App name  id  mode  pid    status  restart  uptime  cpu  mem        watching 
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
 myapp     0   fork  43059  online  1        0s      0%   15.2 MB    disabled 
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘

ここでrestart1に増えているからも、再起動されたことがわかります。


停止する

停止するためにはstopコマンドを利用します。

# pm2 stop [アプリ名]
$ pm2 stop myapp
[PM2] Applying action stopProcessId on app [myapp](ids: 0)
[PM2] [myapp](0) 
┌──────────┬────┬──────┬─────┬─────────┬─────────┬────────┬─────┬────────┬──────────┐
 App name  id  mode  pid  status   restart  uptime  cpu  mem     watching 
├──────────┼────┼──────┼─────┼─────────┼─────────┼────────┼─────┼────────┼──────────┤
 myapp     0   fork  0    stopped  1        0       0%   0 B     disabled 
└──────────┴────┴──────┴─────┴─────────┴─────────┴────────┴─────┴────────┴──────────┘
 Use `pm2 show ` to get more details about an app



ログの確認

logsコマンドを用いることで、出力されているログを確認することができます。

# pm2 logs [アプリ名]
$ pm2 logs myapp
[TAILING] Tailing last 15 lines for [myapp] process (change the value with --lines option)
/Users/munesadayohei/.pm2/logs/myapp-error-0.log last 15 lines:
/Users/munesadayohei/.pm2/logs/myapp-out-0.log last 15 lines:
0|myapp    | Express app starts, linstening port on 3000.
0|myapp    | Express app starts, linstening port on 3000.



モニタリング

monitコマンドを使うと、起動しているアプリのモニタリング(ログの確認やプロセスの確認)を行うことができます。

$ pm2 monit

クラスタリングモードでの起動

最初に説明したpm2 start [スクリプトファイルパス]ではforkモードという状態で起動しますが、起動モードにはクラスターモードというものも存在します。フォークモードでは起動したアプリ自体がリクエストを受け取りますが、クラスターモードではpm2のマスターノードがリクエストを受け取り、それを起動中のインスタンスに割り振ります(いわゆるロードバランシングをしてくれます)。

この機能で、複数インスタンスを同時に立ち上げることで、マシンリソースを上限まで使うことができるようになります。具体的には、以下のように起動します。

# pm2 start [スクリプトファイル名] --name [名前] -i [起動数]
# -i をつけると、クラスターモードになり、起動数=0にすると、マシンのコア数でインスタンスを起動してくれる.
$ pm2 start app.js --name myapp -i 0
[PM2] Starting /Users/munesadayohei/git/node-playground/010-pm2/app.js in cluster_mode (0 instance)
[PM2] Done.
┌──────────┬────┬─────────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
 App name  id  mode     pid    status  restart  uptime  cpu  mem        watching 
├──────────┼────┼─────────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
 myapp     0   cluster  43861  online  0        0s      13%  26.5 MB    disabled 
 myapp     1   cluster  43862  online  0        0s      30%  27.2 MB    disabled 
 myapp     2   cluster  43863  online  0        0s      28%  26.8 MB    disabled 
 myapp     3   cluster  43864  online  0        0s      25%  26.9 MB    disabled 
└──────────┴────┴─────────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘

今回のマシンの場合、4コアあるので、4つのクラスターが起動しています。クラスターモードで複数インスタンスを立ち上げておけば、restartなどで再起動する場合にも、ダウンタイム0で再起動することができます。


設定ファイルを用いた起動指定

起動オプションで便利な振る舞いを指定できますが、一度にたくさんを指定するのは面倒です。起動オプションは設定ファイル(YamlまたはJSON形式)で定義することもできます。その設定ファイルをstartコマンドに渡すことで、便利なオプションを複数指定して起動することができます。

Yaml形式の場合

# ファイル名:pm2config.yml(ファイル名は自由です)

name: myapp                            # アプリ名
script: app.js                         # スクリプトファイルパス
exec_mode: "cluster"                   # 起動モード = cluster
instances: 0                           # 起動インスタンス数
log-date-format: "YYYY-MM-DD HH:mm Z"  # ログに日付を追加

JSONの場合

// ファイル名:pm2config.json(ファイル名は自由です)

{
    "name": "myapp",
    "script": "app.js",
    "exec_mode": "cluster",
    "instances": 0,
    "log-date-format": "YYYY-MM-DD HH:mm Z"
}

基本的には、Yamlの方がシンプルだしコメントも書けるので、Yaml定義が良いなぁと思います。

上記の設定ファイルを用いて起動するには、以下のように行います。

# Yamlファイルを指定して、起動する場合
$ pm2 start pm2config.yml

# JSONファイルを指定して、起動する場合
$ pm2 start pm2config.json




参考資料

今回は、以下の公式資料を利用しました。他にも色々とコマンドが紹介されているので、一読する価値は高いです。

http://pm2.keymetrics.io/docs/usage/quick-start/



最後に

PM2は非常に便利で、他にも色々な使い方をしているので、その辺もブログにアウトプットしていきたいなと思います。

最後になりますが本ブログでは、Linux・インフラ・開発環境・Python・フロントエンド・Go言語・Node.js・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSTwitterをフォローして頂けると幸いです ^ ^。

最後までご覧頂きましてありがとうございました!

foreverコマンドでNodeJSアプリを起動したままにする

この記事は最終更新日から1年以上が経過しています。

NodeJsアプリをデーモン化する

利点:"node app.js"をやらなくていい

npmでforeverを入れる

npm install -g forever

foreverコマンドの使い方

起動

forever start app.js

停止

forever stop app.js

再起動

forever restart app.js

foreverで実行しているリスト

forever list

こんなのが出る

info:    Forever processes running
data:        uid  command       script forever pid   id logfile                 uptime
data:    [0] ioGt /usr/bin/node app.js 39066   39068    /root/.forever/ioGt.log 0:0:0:13.174

ログ

forever logs

結果

info:    Logs for running Forever processes
data:        script logfile
data:    [0] app.js /root/.forever/ioGt.log

設定確認

forever config

結果

data:    {
data:      root: '/root/.forever',
data:      pidPath: '/root/.forever/pids',
data:      sockPath: '/root/.forever/sock',
data:      loglength: 100,
data:      logstream: false,
data:      columns: [
data:          'uid',
data:          'command',
data:          'script',
data:          'forever',
data:          'pid',
data:          'id',
data:          'logfile',
data:          'uptime'
data:      ]
data:    }

まとめ

foreverコマンドはstartしたらずっと動いてるので、便利。
便利だけど、ずっと動いてるので使い方忘れそう。
オプションもあるから、使えそうなら使ってみる。


Express에서 정적 파일 제공

이미지, CSS 파일 및 JavaScript 파일과 같은 정적 파일을 제공하려면 Express의 기본 제공 미들웨어 함수인 express.static을 사용하십시오.

정적 자산이 포함된 디렉토리의 이름을 express.static 미들웨어 함수에 전달하면 파일의 직접적인 제공을 시작할 수 있습니다. 예를 들면, 다음과 같은 코드를 이용하여 public이라는 이름의 디렉토리에 포함된 이미지, CSS 파일 및 JavaScript 파일을 제공하십시오.


app.use(express.static('public'));

이제 다음과 같이 public 디렉토리에 포함된 파일을 로드할 수 있습니다.


http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html

Express는 정적 디렉토리에 대해 상대적으로 파일을 검색하며, 따라서 정적 디렉토리의 이름은 URL의 일부가 아닙니다.

여러 개의 정적 자산 디렉토리를 이용하려면 다음과 같이 express.static 미들웨어 함수를 여러 번 호출하십시오.


app.use(express.static('public'));
app.use(express.static('files'));

Express는 express.static 미들웨어 함수를 이용해 정적 디렉토리를 설정한 순서대로 파일을 검색합니다.

express.static 함수를 통해 제공되는 파일에 대한 가상 경로 접두부(파일 시스템 내에 해당 경로가 실제로 존재하지 않는 경우)를 작성하려면, 아래에 표시된 것과 같이 정적 디렉토리에 대한 마운트 경로를 지정하십시오.


app.use('/static', express.static('public'));

이제 /static 경로 접두부를 통해 public 디렉토리에 포함된 파일을 로드할 수 있습니다.


http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html

그러나 express.static 함수에 제공되는 경로는 node 프로세스가 실행되는 디렉토리에 대해 상대적입니다. Express 앱을 다른 디렉토리에서 실행하는 경우에는 다음과 같이 제공하기 원하는 디렉토리의 절대 경로를 사용하는 것이 더 안전합니다.


app.use('/static', express.static(__dirname + '/public'));


Node.js (Express Framework) 앞단에 Nginx 사용하기

InspiredJW 2012.03.17 15:31
본글 출처 : 
http://inspiredjw.com/entry/Nodejs-Express-Framework-앞단에-Nginx-사용하기 [Inspired World]

Node.js의 창시자인 Ryan Dahl에 의하면


 "You just may be hacked when some yet-unknown buffer overflow is discovered. Not that that couldn't happen behind nginx, but somehow having a proxy in front makes me happy". 

"아직 발견되지 않은 버퍼 오버플로우 취약점에 의해서 해킹 당할 수 있습니다. 
Nginx를 앞단에 둠으로써 이런 취약점에 의해서 해킹을 완전히 막아주지는 않지만, 저는 Nginx을 Proxy서버로써 앞단에 두는 것이 좋다고 생각합니다."






좀 의역을 한 부분이 없잖아 있지만, 중요한 포인트는 Nginx를 앞단에 둠으로써 Express가 사용하는 실제 포트를 숨기고 Nginx의 80포트를 통해 Reverse Proxying 을 함으로써 저런 보안 이슈를 방지할수도 있고 Nginx의 우수한 기능 활용할 수 있습니다.

실제 Static File 과 같은 경우에는 Node.js 보다는 Nginx가 훨씬 성능이 뛰어나다고 합니다.




유의 하실 점은 Nginx 1.0.x버전은 HTTP 1.1을 아예 지원하지 않고 (TCP Module 사용 예외)

Nginx 1.1.x버전은 HTTP 1.1을 지원하지만 Websocket은 지원하지 않기 때문에 Socket.IO와 같은 모듈을 사용할 때 Websocket 방식으로 연결을 시도할 경우에는 Nginx를 거쳐서 연결을 시도하지 않고 직접 연결을 하거나 TCP Module을 사용해야 합니다.



그럼 Nginx 를 Reverse Proxy로 설정하는 방법을 알아볼까요?

Ubuntu 11.04 Natty에서 패키지 인스톨로러를 통해 Nginx를 설치한 경우로 설명하겠습니다.

 

1. ngnix 설치

참고로 Ubuntu에서 nginx 설치는 


sudo apt-get update
sudo apt-get install nginx

하시면 됩니다.



2. nginx 설정 파일 작성

먼저 , nginx 설정파일을 만들어 주어야 합니다. nginx설정파일을 아래의 디렉토리에 만들어주도록 합니다. [example]은 설정파일의 이름으로 확장자는 따로 적어주지 않습니다.






sudo nano /etc/nginx/sites-available/[example]

이렇게 사용하고 싶은 이름 (일반적으로 도메인 이름, 여기선 example) Nginx 설정 파일을 열고


server {
    listen 80;
    server_name example.com; #nginx와 도메인 주소를 연결해 주는 역할을 합니다. 외부에서 example.com으로 들어오는 도메인 주소에서 
요청이 들어오면 로컬에서 오픈되어 있는 아래의 " proxy_pass http://127.0.0.1:3000/; " 를 포워딩해줍니다.

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;

      proxy_pass http://127.0.0.1:3000/; # server_name example.com;로 들어온 요청을 nginx가 받아, 로컬에서 오픈되어 있는
"proxy_pass http://127.0.0.1:3000/;"를 포워딩해줍니다.
      proxy_redirect off;
    }

    gzip on;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_min_length  1000;
    gzip_disable     "MSIE [1-6]\."
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
 }

이렇게 입력 해주고 CTRL + X 를 눌러 빠져나오고 Y를 눌러 파일을 저장합니다.




다음에는 /etc/nginx/sites-available에 만든 nginx설정 파일을 /etc/nginx/sites-enabled/ 직하로 옮겨주는 작업을 합니다.


cd /etc/nginx/sites-enabled/ 
ln -s /etc/nginx/sites-available/example example

이렇게 해주게 되면 방금 만든 Nginx 설정파일이 적용됩니다. 설정을 변경한 이후에는 Nginx를 반드시 재시작 해줘야 변경한 것이 적용이 되므로


sudo /etc/init.d/nginx restart
혹은sudo service nginx reload

를 쉘에서 실행하여 재시작을 합니다.




혹시 아직 만든 Node.js 앱이 없다면

테스트용으로


var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(3000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');

//express 모듈을 사용하고 있다면, app.listen(3000,'127.0.0.1', function(){ });


위와 같이 입력하고 이름을 app.js로 저장합니다.

쉘에서 

node app.js


이렇게 테스트 앱을 실행해주면



http://localhost:3000으로는 직접 연결해서 Hello World 를 볼 수도 있고

nginx설정 파일에서 적어준 server_name example.com;
http://example.com로도 같은 Hello World를 볼 수 있습니다.


실제 Production 에서는 방화벽에서 3000포트를 허용하지 않고 80포트만 Inbound 해주면 Nginx 를 통해서만 앱에 접근할 수 있게 됩니다.




'frameworks > NodeJs' 카테고리의 다른 글

nodejs 로그인 로직  (0) 2019.03.12
npm 명령어  (0) 2019.01.08
PM2로 Nodejs어플을 서비스 가동시키기  (0) 2018.06.15
forever로 Nodejs어플을 서비스 가동시키기  (0) 2018.06.15
Express에서 정적 파일 제공  (0) 2018.03.21

+ Recent posts