

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Elastic Beanstalk에 Node.js Express 애플리케이션 배포
<a name="create_deploy_nodejs_express"></a>

이 단원에서는 Elastic Beanstalk 명령줄 인터페이스(EB CLI)를 사용하여 샘플 애플리케이션을 Elastic Beanstalk에 배포한 후, [Express](http://expressjs.com/) 프레임워크를 사용하도록 애플리케이션을 업데이트하는 절차를 살펴봅니다.

## 사전 조건
<a name="create_deploy_nodejs_express.prerequisites"></a>

이 튜토리얼의 사전 요구 사항은 다음과 같습니다:
+ Node.js 런타임
+ 기본 Node.js 패키지 관리자 소프트웨어인 npm
+ 익스프레스 커맨드 라인 생성기
+ Elastic Beanstalk 명령줄 인터페이스(EB CLI)

나열된 처음 세개 구성 요소의 설치 및 로컬 개발 환경 설정에 대한 자세한 내용은 [Elastic Beanstalk를 위한 Node.js 개발 환경 설정](nodejs-devenv.md)을 참조하십시오. 이 자습서에서는 참조된 주제에도 언급된 Node.js용 AWS SDK를 설치할 필요가 없습니다.

EB CLI 설치 및 구성에 대한 자세한 내용은 [설정 스크립트를 사용하여 EB CLI 설치(권장)](eb-cli3.md#eb-cli3-install) 및 [EB CLI 구성](eb-cli3-configuration.md) 단원을 참조하세요.

## Elastic Beanstalk 환경 생성
<a name="create_deploy_nodejs_express.eb_init-rds"></a>

**귀하의 애플리케이션 디렉터리**  
이 튜토리얼에서는 애플리케이션 소스`nodejs-example-express-rds` 번들용으로 호출되는 디렉터리를 사용합니다. 이 튜토리얼을 위한`nodejs-example-express-rds` 디렉토리를 만드세요.

```
~$ mkdir nodejs-example-express-rds
```

**참고**  
이 장의 각 튜토리얼에서는 애플리케이션 소스 번들용 자체 디렉토리를 사용합니다. 디렉터리 이름은 튜토리얼에서 사용하는 샘플 응용 프로그램의 이름과 일치합니다.

현재 작업 디렉터리를 `nodejs-example-express-rds`로 변경합니다.

```
~$ cd nodejs-example-express-rds
```

이제 Node.js 플랫폼과 샘플 애플리케이션을 실행하는 Elastic Beanstalk 환경을 설정합니다. Elastic Beanstalk 명령줄 인터페이스(EB CLI)를 사용할 것입니다.

**애플리케이션용 EB CLI 리포지토리를 구성하기 위해 Node.js 플랫폼을 실행하는 Elastic Beanstalk 환경을 생성합니다**

1. **[**eb init**](eb3-init.md)** 명령을 사용하여 리포지토리를 만듭니다.

   ```
   ~/nodejs-example-express-rds$ eb init --platform node.js --region <region>
   ```

   이 명령은 애플리케이션의 환경을 생성하기 위한 설정을 지정하는 `.elasticbeanstalk`라는 이름의 폴더에 구성 파일을 만들고 현재 폴더의 이름을 딴 Elastic Beanstalk 애플리케이션을 만듭니다.

1. **[**eb create**](eb3-create.md)** 명령을 사용하여 샘플 애플리케이션을 실행하는 환경을 생성합니다.

   ```
   ~/nodejs-example-express-rds$ eb create --sample nodejs-example-express-rds
   ```

   이 명령은 Node.js 플랫폼의 기본 설정과 다음 리소스를 사용하여 로드 밸런싱 수행 환경을 만듭니다.
   + **EC2 인스턴스(EC2 instance)** - 선택한 플랫폼에서 웹 앱을 실행하도록 구성된 Amazon Elastic Compute Cloud(Amazon EC2) 가상 머신입니다.

     특정 언어 버전, 프레임워크, 웹 컨테이너 또는 그 조합을 지원하도록 각 플랫폼마다 특정 소프트웨어, 구성 파일 및 스크립트 세트를 실행합니다. 대부분의 플랫폼에서는 웹 앱 앞에 위치해 웹 앱으로 요청을 전달하고, 정적 자산을 제공하고, 액세스 및 오류 로그를 생성하는 역방향 프록시로 Apache 또는 NGINX를 사용합니다.
   + **인스턴스 보안 그룹(Instance security group)** - 포트 80에서 인바운드 트래픽을 허용하도록 구성된 Amazon EC2 보안 그룹입니다. 이 리소스를 통해 로드 밸런서의 HTTP 트래픽이 웹 앱을 실행하는 EC2 인스턴스에 도달할 수 있습니다. 기본적으로 다른 포트에서는 트래픽이 허용되지 않습니다.
   + **로드 밸런서(Load balancer)** - 애플리케이션을 실행하는 인스턴스로 요청을 분산하도록 구성된 Elastic Load Balancing 로드 밸런서입니다. 또한 로드 밸런서가 있으면 인터넷에 인스턴스를 직접 노출할 필요가 없습니다.
   + **로드 밸런서 보안 그룹(Load balancer security group)** - 포트 80에서 인바운드 트래픽을 허용하도록 구성된 Amazon EC2 보안 그룹입니다. 이 리소스를 통해 인터넷의 HTTP 트래픽이 로드 밸런서에 도달할 수 있습니다. 기본적으로 다른 포트에서는 트래픽이 허용되지 않습니다.
   + **Auto Scaling 그룹(Auto Scaling group)** - 인스턴스가 종료되거나 사용할 수 없게 될 경우 인스턴스를 대체하도록 구성된 Auto Scaling 그룹입니다.
   + **Amazon S3 버킷(Amazon S3 bucket)** - Elastic Beanstalk 사용 시 생성된 소스 코드, 로그 및 기타 아티팩트의 스토리지 위치입니다.
   + **Amazon CloudWatch 경보(Amazon CloudWatch alarms)** - 환경의 인스턴스에 대한 로드를 모니터링하는 두 개의 CloudWatch 경보로, 로드가 너무 높거나 너무 낮은 경우 트리거됩니다. 경보가 트리거되면 이에 대한 응답으로 Auto Scaling 그룹이 확장 또는 축소됩니다.
   + **CloudFormation 스택** - Elastic Beanstalk는 CloudFormation 를 사용하여 환경에서 리소스를 시작하고 구성 변경 사항을 전파합니다. 리소스는 [CloudFormation 콘솔](https://console.aws.amazon.com/cloudformation)에서 볼 수 있는 템플릿에서 정의됩니다.
   + **도메인 이름(Domain name)** - **subdomain*.*region*.elasticbeanstalk.com* 형식으로 웹 앱으로 라우팅되는 도메인 이름입니다.
**도메인 보안**  
Elastic Beanstalk 애플리케이션의 보안을 강화하기 위해 *elasticbeanstalk.com* 도메인이 [공개 서픽스 목록(PSL)](https://publicsuffix.org/)에 등록되어 있습니다.  
Elastic Beanstalk 애플리케이션의 기본 도메인 이름에 민감한 쿠키를 설정해야 하는 경우 보안을 강화하기 위해 `__Host-` 접두사가 있는 쿠키를 사용하는 것이 좋습니다. 이렇게 쿠키를 설정하면 교차 사이트 요청 위조 시도(CSRF)로부터 도메인이 보호됩니다. 자세한 내용은 Mozilla 개발자 네트워크의 [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes) 페이지를 참조하세요.

1. 환경 생성이 완료되면 [**eb open**](eb3-open.md) 명령을 사용하여 기본 브라우저에서 환경의 URL을 엽니다.

   ```
   ~/nodejs-example-express-rds$ eb open
   ```

이제 샘플 애플리케이션을 사용하여 Node.js Elastic Beanstalk 환경을 생성했습니다. 자체 애플리케이션으로 업데이트할 수 있습니다. 다음으로 Express 프레임워크를 사용하도록 샘플 애플리케이션을 업데이트합니다.

## Express를 사용하도록 애플리케이션을 업데이트하려면
<a name="create_deploy_nodejs_express.update"></a>

샘플 애플리케이션이 있는 환경을 생성한 후 이를 자체 애플리케이션으로 업데이트할 수 있습니다. 이 절차에서는 먼저**express** 및**npm install** 명령을 실행하여 애플리케이션 디렉터리에 Express 프레임워크를 설정합니다. EB CLI를 사용하여 Elastic Beanstalk 환경에 업데이트된 애플리케이션을 배포합니다.

**Express를 사용하도록 애플리케이션을 업데이트하려면**

1. `express` 명령을 실행합니다. 이는 `package.json`, `app.js` 및 몇 개의 디렉터리를 생성합니다.

   ```
   ~/nodejs-example-express-rds$ express
   ```

   계속할지 여부를 묻는 메시지가 표시되면 **y**를 입력합니다.
**참고**  
**express**명령이 작동하지 않는 경우 이전 *사전 요구 사항* 섹션에 설명된 대로 Express 명령줄 생성기를 설치하지 않았기 때문일 수 있습니다. 또는**express** 명령을 실행하려면 로컬 시스템의 디렉터리 경로 설정을 설정해야 할 수 있습니다. 개발 환경 설정에 대한 자세한 단계는 *필수 조건* 섹션을 참조하십시오. 그러면 이 자습서를 계속 진행할 수 있습니다.

1. 로컬 종속 항목을 설정합니다.

   ```
   ~/nodejs-example-express-rds$ npm install
   ```

1. (선택) 웹 앱 서버가 시작되는지 확인합니다.

   ```
   ~/nodejs-example-express-rds$ npm start
   ```

   다음과 유사한 출력 화면이 표시되어야 합니다.

   ```
   > nodejs@0.0.0 start /home/local/user/node-express
   > node ./bin/www
   ```

   서버는 기본적으로 포트 3000에서 실행됩니다. 테스트하려면 다른 터미널에서 `curl http://localhost:3000`을 실행하거나 로컬 컴퓨터에서 브라우저를 열고 `http://localhost:3000`으로 이동하십시오.

   **Ctrl\$1C**를 눌러 서버를 중지합니다.

1. [**eb deploy**](eb3-deploy.md) 명령으로 Elastic Beanstalk 환경으로 변경된 애플리케이션을 배포합니다.

   ```
   ~/nodejs-example-express-rds$ eb deploy
   ```

1. 환경이 녹색이고 준비되면 URL을 새로 고쳐서 작동하는지 확인합니다. **Welcome to Express**라는 웹 페이지가 보일 것입니다.

다음으로 정적 파일을 제공하고 새 페이지를 추가하도록 Express 애플리케이션을 업데이트하겠습니다.

**정적 파일을 구성하고 Express 애플리케이션에 새 페이지를 추가하려면**

1. [`.ebextensions`](ebextensions.md) 폴더에 다음 콘텐츠가 포함된 두 번째 구성 파일을 추가합니다:

   **`nodejs-example-express-rds/.ebextensions/staticfiles.config`**

   ```
   option_settings:
       aws:elasticbeanstalk:environment:proxy:staticfiles:
           /stylesheets: public/stylesheets
   ```

   이 설정은 애플리케이션의 `public` 경로에서 `/public` 폴더에 있는 파일을 제공하도록 프록시 서버를 구성합니다. 프록시 서버에서 정적으로 파일을 제공하면 애플리케이션의 부하가 감소합니다. 자세한 내용은 이 장의 앞부분에 있는 [Stic 파일을](create_deploy_nodejs.container.md#nodejs-platform-console-staticfiles) 참조하십시오.

1. (선택 사항) 정적 매핑이 올바르게 구성되었는지 확인하려면 에서 정적 매핑 구성을 주석`nodejs-example-express-rds/app.js` 처리하십시오. 이렇게 하면 노드 애플리케이션에서 매핑이 제거됩니다.

   ```
   //  app.use(express.static(path.join(__dirname, 'public'))); 
   ```

   이전 단계의 파일에 있는 정적`staticfiles.config` 파일 매핑은 이 줄을 주석 처리한 후에도 여전히 스타일시트를 성공적으로 로드할 것입니다. 정적 파일 매핑이 익스프레스 응용 프로그램이 아닌 프록시 정적 파일 구성을 통해 로드되었는지 확인하려면 다음 값을 제거하십시오`option_settings:`. 정적 파일 구성과 노드 응용 프로그램 모두에서 스타일시트를 제거한 후에는 스타일시트를 로드할 수 없습니다.

   테스트가`staticfiles.config` 끝나면`nodejs-example-express-rds/app.js` 및 의 콘텐츠를 모두 재설정해야 합니다.

1. `nodejs-example-express-rds/routes/hike.js`를 추가합니다. 다음을 입력합니다.

   ```
   exports.index = function(req, res) {
    res.render('hike', {title: 'My Hiking Log'});
   };
   
   exports.add_hike = function(req, res) {
   };
   ```

1. 새로운 세 줄을 포함하도록 `nodejs-example-express-rds/app.js`를 업데이트합니다.

   먼저 다음 줄을 추가하여 이 경로에 `require`를 추가합니다.

   ```
   var hike = require('./routes/hike');
   ```

   파일은 다음 조각과 비슷해야 합니다.

   ```
   var express = require('express');
   var path = require('path');
   var hike = require('./routes/hike');
   ```

   그런 다음 `nodejs-example-express-rds/app.js`에 다음 두 줄을 추가하여 `var app = express();` 뒤에 놓습니다.

   ```
   app.get('/hikes', hike.index);
   app.post('/add_hike', hike.add_hike);
   ```

   파일은 다음 조각과 비슷해야 합니다.

   ```
   var app = express();
   app.get('/hikes', hike.index);
   app.post('/add_hike', hike.add_hike);
   ```

1. `nodejs-example-express-rds/views/index.jade`를 `nodejs-example-express-rds/views/hike.jade`에 복사합니다.

   ```
   ~/nodejs-example-express-rds$ cp views/index.jade views/hike.jade
   ```

1. [**eb deploy**](eb3-deploy.md)명령을 사용하여 변경 내용을 배포합니다.

   ```
   ~/nodejs-example-express-rds$ eb deploy
   ```

1. 몇 분 후 환경이 업데이트됩니다. 환경이 녹색이고 준비되면 브라우저를 새로 고치고 URL의 끝에 **hikes**를 추가하여(예: `http://node-express-env-syypntcz2q.elasticbeanstalk.com/hikes`) 작동하는지 확인합니다.

   **My Hiking Log**라는 제목의 웹 페이지가 보일 것입니다.

Express 프레임워크 를 사용하는 웹 애플리케이션을 생성합니다. 다음 섹션에서는 Amazon 관계형 데이터베이스 서비스(RDS) 를 사용하여 하이킹 로그를 저장하도록 애플리케이션을 수정하겠습니다.

## Amazon RDS를 사용할 수 있도록 애플리케이션을 업데이트합니다
<a name="create_deploy_nodejs_express.add_rds"></a>

다음 단계에서는 Amazon RDS for MySQL RDS를 사용하도록 애플리케이션을 업데이트합니다.

**MySQL용 RDS를 사용하도록 애플리케이션을 업데이트하려면**

1. Elastic Beanstalk 환경에 연결된 MySQL용 RDS 데이터베이스를 생성하려면 이 장 뒷부분에 포함된 [데이터베이스 추가](create-deploy-nodejs.rds.md) 항목의 지침을 따르십시오. 데이터베이스 인스턴스를 추가하는 데 약 10분이 걸립니다.

1.  `package.json`에서 종속성 섹션을 다음 내용으로 업데이트하십시오: 

   ```
   "dependencies": {
       "async": "^3.2.4",
       "express": "4.18.2",
       "jade": "1.11.0",
       "mysql": "2.18.1",
       "node-uuid": "^1.4.8",
       "body-parser": "^1.20.1",
       "method-override": "^3.0.0",
       "morgan": "^1.10.0",
       "errorhandler": "^1.5.1"
     }
   ```

1. **npm install**를 실행합니다.

   ```
   ~/nodejs-example-express-rds$ npm install
   ```

1. `app.js`업데이트하여 데이터베이스에 연결하고, 테이블을 생성하고, 단일 기본 하이킹 로그를 삽입하세요. 이 앱을 배포할 때마다 이전 hikes 테이블을 삭제하고 다시 생성합니다.

   ```
   /**
    * Module dependencies.
    */
   
    const express = require('express')
    , routes = require('./routes')
    , hike = require('./routes/hike')
    , http = require('http')
    , path = require('path')
    , mysql = require('mysql')
    , async = require('async')
    , bodyParser = require('body-parser')
    , methodOverride = require('method-override')
    , morgan = require('morgan')
    , errorhandler = require('errorhandler');
   
   const { connect } = require('http2');
   
   const app = express()
   
   app.set('views', __dirname + '/views')
   app.set('view engine', 'jade')
   app.use(methodOverride())
   app.use(bodyParser.json())
   app.use(bodyParser.urlencoded({ extended: true }))
   app.use(express.static(path.join(__dirname, 'public')))
   
   
   app.set('connection', mysql.createConnection({
   host: process.env.RDS_HOSTNAME,
   user: process.env.RDS_USERNAME,
   password: process.env.RDS_PASSWORD,
   port: process.env.RDS_PORT}));  
   
   function init() {
    app.get('/', routes.index);
    app.get('/hikes', hike.index);
    app.post('/add_hike', hike.add_hike);
   }
   
   const client = app.get('connection');
   async.series([
    function connect(callback) {
      client.connect(callback);
      console.log('Connected!');
    },
    function clear(callback) {
      client.query('DROP DATABASE IF EXISTS mynode_db', callback);
    },
    function create_db(callback) {
      client.query('CREATE DATABASE mynode_db', callback);
    },
    function use_db(callback) {
      client.query('USE mynode_db', callback);
    },
    function create_table(callback) {
       client.query('CREATE TABLE HIKES (' +
                           'ID VARCHAR(40), ' +
                           'HIKE_DATE DATE, ' +
                           'NAME VARCHAR(40), ' +
                           'DISTANCE VARCHAR(40), ' +
                           'LOCATION VARCHAR(40), ' +
                           'WEATHER VARCHAR(40), ' +
                           'PRIMARY KEY(ID))', callback);
    },
    function insert_default(callback) {
      const hike = {HIKE_DATE: new Date(), NAME: 'Hazard Stevens',
            LOCATION: 'Mt Rainier', DISTANCE: '4,027m vertical', WEATHER:'Bad', ID: '12345'};
      client.query('INSERT INTO HIKES set ?', hike, callback);
    }
   ], function (err, results) {
    if (err) {
      console.log('Exception initializing database.');
      throw err;
    } else {
      console.log('Database initialization complete.');
      init();
    }
   });
   
   module.exports = app
   ```

1. 다음 콘텐츠를 `routes/hike.js`에 추가합니다. 이렇게 하면 경로에서 새 하이킹 로그를 *HIKES* 데이터베이스에 삽입할 수 있습니다.

   ```
   const uuid = require('node-uuid');
   exports.index = function(req, res) {
     res.app.get('connection').query( 'SELECT * FROM HIKES', function(err,
   rows) {
       if (err) {
         res.send(err);
       } else {
         console.log(JSON.stringify(rows));
         res.render('hike', {title: 'My Hiking Log', hikes: rows});
     }});
   };
   exports.add_hike = function(req, res){
     const input = req.body.hike;
     const hike = { HIKE_DATE: new Date(), ID: uuid.v4(), NAME: input.NAME,
     LOCATION: input.LOCATION, DISTANCE: input.DISTANCE, WEATHER: input.WEATHER};
     console.log('Request to log hike:' + JSON.stringify(hike));
     req.app.get('connection').query('INSERT INTO HIKES set ?', hike, function(err) {
         if (err) {
           res.send(err);
         } else {
           res.redirect('/hikes');
         }
      });
   };
   ```

1. `routes/index.js`의 내용을 다음으로 바꿉니다:

   ```
   /*
    * GET home page.
    */
   
   exports.index = function(req, res){
     res.render('index', { title: 'Express' });
   };
   ```

1. 다음 jade 템플릿을 추가하여 하이킹 로그를`views/hike.jade` 추가하기 위한 사용자 인터페이스를 제공합니다.

   ```
   extends layout
   
   block content
     h1= title
     p Welcome to #{title}
   
     form(action="/add_hike", method="post")
       table(border="1")
         tr
           td Your Name
           td
             input(name="hike[NAME]", type="textbox")
         tr
           td Location
           td
             input(name="hike[LOCATION]", type="textbox")
         tr
           td Distance
           td
             input(name="hike[DISTANCE]", type="textbox")
         tr
           td Weather
           td
             input(name="hike[WEATHER]", type="radio", value="Good")
             | Good
             input(name="hike[WEATHER]", type="radio", value="Bad")
             | Bad
             input(name="hike[WEATHER]", type="radio", value="Seattle", checked)
             | Seattle
         tr
           td(colspan="2")
             input(type="submit", value="Record Hike")
   
     div
       h3 Hikes
       table(border="1")
         tr
           td Date
           td Name
           td Location
           td Distance
           td Weather
         each hike in hikes
           tr
             td #{hike.HIKE_DATE.toDateString()}
             td #{hike.NAME}
             td #{hike.LOCATION}
             td #{hike.DISTANCE}
             td #{hike.WEATHER}
   ```

1. [**eb deploy**](eb3-deploy.md)명령을 사용하여 변경 내용을 배포합니다.

   ```
   ~/nodejs-example-express-rds$ eb deploy
   ```

## 정리
<a name="create_deploy_nodejs_express.delete"></a>

Elastic Beanstalk 작업을 완료한 경우 환경을 종료할 수 있습니다.

**eb terminate** 명령을 사용하여 환경과 환경에 있는 모든 리소스를 종료합니다.

```
~/nodejs-example-express-rds$ eb terminate
The environment "nodejs-example-express-rds-env" and all associated instances will be terminated.
To confirm, type the environment name: nodejs-example-express-rds-env
INFO: terminateEnvironment is starting.
...
```