Amazon ECS로 Swift 웹 어플리케이션 실행하기

원문: Running Swift Web Applications with Amazon ECS

Swift는 안전, 성능 및 소프트웨어 디자인 패턴에 대해 현대적으로 접근해 만들어진 범용 프로그래밍 언어입니다. Swift의 목표는 시스템 프로그래밍에서 데스크탑과 모바일 어플리케이션 프로그래밍, 클라우드 서비스까지 확장하는 최고의 언어가 되는 것입니다. 개발자로서 동일한 스택으로 어플리케이션을 구성할 수 있다는 가능성과 Swift의 장점을 클라이언트 및 서버단에서 활용할 수 있다는 사실에 흥분했습니다. 코드는 더욱 간결해지고 iOS 환경과 더 밀접하게 통합됩니다.

이 글에서 Swift를 이용해 웹 어플리케이션을 만들고 우분투 리눅스 이미지와 Amazon ECR을 사용해 Amazon ECS에 배포 하는 방법에 대해 설명합니다.

컨테이너 배포 개요

Swift는 우분투에서 사용할 수 있는 버전의 컴파일러를 제공합니다. 컴파일러 외에도 웹 서버, 컨테이너 전략 및 트레픽 최고치를 자동으로 확대하는 자동 클러스터 관리가 필요합니다.

다음은 서비스를 클라우드에 배포 할 때 내려야 할 결정들입니다:

  • HTTP server Swift를 지원하는 HTTP 서버를 선택하세요. Vapor가 가장 쉽습니다. Vapor는 iOS, MACOS 및 우분투에서 동작하는 Swift 3.0의 type-safe한 웹 프레임워크입니다. Swift 어플리케이션을 배포하는 것은 매우 간단하고 쉽습니다. Vapor는 새 Vapor 어플리케이션을 만들고, Xcode 프로젝트를 생성 및 빌드하는 것 뿐만 아니라 어플리케이션을 Heroku 또는 Docker에 배포 하는 것을 도와주는 CLI를 가지고 있습니다. 다른 Swift 웹 서버도 좋지만 이 글에서는 제가 시작하기에 쉽다고 생각한 Vapor를 사용하겠습니다.

Tip: Vapor 슬렉 그룹에 들어오세요, 매우 도움이 됩니다. 질문이 있다면 원하는 답변을 받을 수 있습니다.

  • Container model Docker는 배포된 어플리케이션을 소프트웨어 컨테이너 안에서 빌드, 실행, 테스트, 배포 할 수 있게 해주는 오픈 소스 기술입니다. Docker를 사용하면 개발을 위해 표준화된 단위로 소프트웨어를 패키징 할 수 있습니다. 여기에는 소프트웨어 실행에 필요한 모든 것이 포함됩니다: 코드, 런타임, 소프트웨어 툴, 시스템 라이브러리 등 Docker는 빠르고 안전하고 일관되게, 환경에 구애받지 않고 어플리케이션을 배포 할 수 있게 해줍니다.
    이 글에서는 Docker를 사용하지만 Heroku를 선호하는 경우 Vapor도 Heroku와 호환됩니다.
  • 이미지 저장소 Docker를 컨테이너 배포 단위로 선택한 후에는 규모에 맞춰 배포를 자동화 하기 위해 Docker 이미지를 저장소에 저장해야 합니다. Amazon ECR은 완벽하게 관리되는 Docker 레지스트리며 AWS IAM 정책을 사용해 저장소를 안전하게 보호할 수 있습니다.
  • 클러스터 관리 솔루션 Amazon ECS는 확장성이 뛰어나고 Docker 컨테이너를 지원하는 성능이 좋은 컨테이너 관리 서비스며 Amazon EC2 인스턴스의 관리 클러스터에서 어플리케이션을 쉽게 실행할 수 있게 해줍니다. ECS가 있으면 자체 클러스터 관리 인프라를 실치하고 운영하고 확장 할 필요가 없습니다.

ECS를 사용하면 자체 클러스터 인프라를 설치, 운영 확장 할 필요가 없기 때문에 컨테이너를 어플리케이션의 한 부분(분산 또는 기타)으로 채택하는것이 쉽습니다. ECS에서 Docker를 사용하면 장기간 실행되는 어플리케이션, 서비스 및 배치 프로세스를 유연하게 스케줄링 할 수 있습니다. ECS는 어플리케이션 가용성을 유지 관리하며 컨테이너를 확장 할 수 있게 해줍니다.

1

HTTP 서버(Vapor)에서 실행되는 Swift 웹 어플리케이션이 있고, 이 서버는 컨테이너(Docker)에 배포 되었으며, 이미지는 수평으로 확장할 수 있도록 자동 클러스터 관리(ECS)가 있는 보안 저장소 (ECR)에 저장되어 있습니다다.

AWS 계정 준비하기

  1. AWS 계정을 가지고 있지 않다면 http://aws.amazon.com에 접속해 화면의 명령을 따라 계정을 생성하세요.
  2. 네비게이션 바에 있는 지역 선택자를 사용해 Swift 웹 어플리케이션을 배포하고 싶은 AWS 지역을 선택하세요.
  3. 원하는 지역에서 보안 키를 만드세요.

둘러보기

다음은 Swift로 작성된 웹 어플리케이션을 설정하고 ECS에 배포하는데 필요한 단계들입니다:

  1. AWS CloudFormation template 인스턴스를 다운로드하고 실행하세요. CloudFormation template은 Swift, Vapor, Docker 및 AWS CLI를 설치합니다.
  2. SSH로 인스턴스에 접속하세요.
  3. vapor 예제 코드를 다운받으세요.
  4. 로컬에서 Vapor 웹 어플리케이션을 테스트하세요.
  5. 새로운 API를 포함해서 Vapor 예제 코드를 향상시키세요.
  6. 코드를 저장소에 푸쉬하세요.
  7. 코드를 도커 이미지로 만드세요.
  8. 이미지를 Amazon ECR에 푸쉬하세요.
  9. Swift 웹 어플리케이션을 Amazon ECS에 배포하세요.

세부 단계

  1. CloudFormation template을 다운로드하고 EC2 인스턴스를 작동시키세요. CloudFormation은 Swift와 Vapor, Docker 및 git을 설치하고 설정합니다. 인스턴스를 시작하려면 여기서 CloudFormation을 실행하세요.
  2. SSH로 인스턴스에 접속하세요:
    ssh –i ec2-user@<bastion host ip>
  3. vapor 예제 코드를 다운받으세요. 이 코드는 웹 어플리케이션에 사용중인 예제를 배포하는데 도움이됩니다:
    git clone https://github.com/awslabs/ecs-swift-sample-app.git
  4. Vapor 어플리케이션을 로컬에서 테스트하세요:
    1. Vapor 프로젝트 빌드:
      cd ~/ecs-swift-sample-app/example \
      vapor build
    2. Vapor 프로젝트 실행:
      vapor run serve --port=8080
    3. 서버 실행 확인(새 터미널 창에서):
      ssh -i ubuntu@ curl localhost:8080
  5. Vapor 코드를 향상시키세요:
    1. 샘플 어플리케이션에 새 route를 추가하는 가이드를 따라 하세요: https://Vapor.readme.io/docs/hello-world
    2. 웹 어플리케이션을 로컬에서 테스트하세요:
      bash vapor run serve --port=8080 curl http://localhost/hello.
  6. 변경사항을 커밋하고 깃허브 저장소에 푸쉬하세요:
    git add –all
    git commit –m
    git push
  7. 코드를 이용해 새 도커 이미지를 빌드하세요:
    docker build -t swift-on-ecs \
    --build-arg SWIFT_VERSION=DEVELOPMENT-SNAPSHOT-2016-06-06-a \
    --build-arg REPO_CLONE_URL=https://github.com/awslabs/ecs-swift-sample-app.git/ \
    ~/ ecs-swift-sample-app/example
  8. ECR에 업로드: ECR 저장소를 만들고 Amazon ECR 시작하기에 있는 단계를 따라 이미지를 푸쉬하세요.
  9. ECS 클러스터를 생성하고 Amazon ECS 시작하기에 있는 단계를 따라 작업을 실행하세요:
    1. 작업을 생성할 때 ECR 이미지에 전체 레지스트리/저장소:태그 이름을 사용해야 합니다. 예를 들면, aws_account_id.dkr.ecr.us-east-1.amazonaws.com/my-web-app:latest.
    2. 포트 포워딩을 8080으로 설정해야 합니다.
  10. 이제 컨테이너로 가서 public IP 주소를 확인하고 결과를 보기 위해 접속해 봅시다.
    1. 실행 중인 작업을 열고 URL을 확인합니다:
      2
    2. 브라우저에서 URL에 접속합니다:
      3

당신의 첫 번째 Swift 웹 어플리케이션이 지금 실행되고 있습니다.

이제, 서비스를 확장하기 위해 ECS with Auto Scaling를 사용할 수 있고 서비스를 모니터링 하기 위해 CloudWatch metrics 와 CloudWatch events를 사용할 수 있습니다.

결론

Swift의 장점을 활용하고 싶다면, Amazon ECS와 Amazon ECR을 활용해 Vapor를 웹 컨테이너로 사용하고 Swift 웹 어플리케이션을 대규모로 배포할 수 있으며 클러스터 관리를 Amazon ECS에 위임할 수 있습니다.

이 글을 넘어서 Swift를 가지고 할 수 있는 많은 흥미로운 것들이 있습니다. Swift를 더 배우시려면 추가적인 Swift 라이브러리들을 보시고 Swift 문서를 읽어보세요.

질문이나 제안이 있으시면 코멘트로 남겨주세요.

Webpack과 자바스크립트용 AWS SDK 를 사용해 어플리케이션을 만들고 번들하기 – 파트 2

※ 원문: https://aws.amazon.com/ko/blogs/developer/using-webpack-and-the-aws-sdk-for-javascript-to-create-and-bundle-an-application-part-2/

이전 글에서 webpack과 자바스크립트 AWS SDK를 사용해서 어플리케이션을 만들고 번들하는 방법에 대해서 소개했습니다.

이번 글에서는 필요한 AWS 서비스로만 번들 만들기, Node.js에서도 동작하는 번들 생성하기와 같은 다른 기능을 파헤쳐보겠습니다.

개별 서비스를 포함하기

webpack을 사용하는 것의 장점 중 하나는 webpack이 의존성을 분석하고 어플리케이션이 필요한 코드만을 포함할 수 있다는 것입니다. 이전 프로젝트에서 webpack이 2.38 MB짜리 번들을 생성했다는 것을 알아챘을 수도 있습니다. 왜냐 하면 webpack이 현재 s3.js에 있는 아래 구문을 기반으로 자바스크립트 AWS SDK 전체를 가져오기 때문입니다.

var AWS = require('aws-sdk');

require 구문을 아래와 같이 바꾸면 webpack이 Amazon S3 서비스만을 가져오게 할 수 있습니다:

var AWS = require('aws-sdk/clients/s3');

AWS.config를 사용해서 설정 가능한 모든 AWS SDK 옵션은 서비스를 초기화 할 때도 설정할 수 있습니다. 아래와 같은 구문으로 전역 설정을 하면 계속해서 모든 서비스에서 AWS 네임스페이스에 접근할 수 있습니다:

var AWS = require('aws-sdk/global');

다음은 이런 변화를 주면 s3.js파일이 어떻게 바뀌는지를 보여주는 예시입니다.

s3.js

// Amazon S3 서비스 클라이언트 가져오기
var S3 = require('aws-sdk/clients/s3');

// 보안 자격 증명과 지역 설정
var s3 = new S3({
    apiVersion: '2006-03-01',
    region: 'REGION', 
    credentials: {/* */}
  });

/**
 * 이 함수는 버킷에서 객체 목록을 검색합니다
 * 그 다음, 제공된 콜백을 전달받은 에러 혹은 데이터와 함께 실행합니다
 */
function listObjects(bucket, callback) {
  s3.listObjects({
    Bucket: bucket
  }, callback);
}

// 함수 핸들러를 내보냅니다
module.exports = listObjects;

이제 npm run build 명령어를 실행하면 아래와 같은 결과를 보여줍니다.

    Version: webpack 1.13.2
    Time: 720ms
      Asset    Size  Chunks             Chunk Names
    bundle.js  797 kB     0  [emitted]  main
      [0] multi main 28 bytes {0} [built]
      [1] ./browser.js 653 bytes {0} [built]
      [2] ./s3.js 803 bytes {0} [built]
       + 155 hidden modules

이제 생성된 번들 용량이 2.38 MB 에서 797 KB로 떨어졌습니다.

최종 용량을 더 줄이기 위해 webpack에서 생성된 코드를 축소하도록 설정할 수 있습니다!

Node.js 번들 생성하기

webpack을 사용해서 설정에서 target: ‘node’ 를 지정하면 Node.js에서 작동하는 번들을 생성할 수 있습니다. 디스크 용량이 제한되어 있는 환경에서 Node.js 어플리케이션을 실행할 때 유용할 수 있습니다.

node.js 파일을 생성해서, Node.js 번들을 빌드하도록 프로젝트를 업데이트 해 봅시다. 이 파일은 browser.js 파일과 거의 동일합니다. 그러나 S3 객체를 DOM 나열하는 대신 콘솔에 출력합니다.

node.js

// listObjects 함수를 가져옵니다
var listObjects = require('./s3');
var bucket = 'BUCKET';
// 지정된 버킷에서 listObjects 를 호출합니다
listObjects(bucket, function(err, data) {
  if (err) {
    console.log(err);
  } else {
    console.log('S3 Objects in ' + bucket + ':');
    // 반환된 각각 객체의 키값을 출력합니다
    data.Contents.forEach(function(metadata) {
      console.log('Key: ' + metadata.Key);
    });
  }
});

다음, node.js를 진입점으로 사용하도록 webpack.config.js 파일을 업데이트하고 webpack이 Node.js 번들을 생성해야 하는 것을 알 수 있도록 target: “node” 라는 필드를 추가합니다.

webpack.config.js

// 파일 경로를 분석하기 위해 path를 포함합니다
var path = require('path');
module.exports = {
  // 어플리케이션의 진입점을 지정합니다.
  entry: [
    path.join(__dirname, 'node.js')
  ],
  // 번들된 코드를 포함하는 출력 파일을 지정합니다
  output: {
    path: __dirname,
    filename: 'bundle.js'
  },
  // Node.js 번들을 생성해야 하는 것을 알려줍니다
  target: "node",
  module: {
    /**
      * webpack에게 'json'파일 읽는 방법을 말해줍니다
      * 왜냐하면 기본적으로 webpack은
      * 자바스크립트 파일을 다루는 방법만 알기 때문입니다.
      * webpack이 'json' 파일이 포함되어있는 'require()' 구문을 만나면
      * json-loader를 사용하게 됩니다
      */
    loaders: [
      {
        test: /.json$/, 
        loaders: ['json']
      }
    ]
  }
}

새로운 번들을 생성하기 위해 npm run build 명령어를 실행하세요. 커맨드라인에 node bundle.js 명령어를 실행해서 이 코드를 테스트할 수 있습니다. 이렇게하면 콘솔에 S3 객체 리스트가 출력됩니다!

시도해 보세요!

자바스크립트용 AWS SDK v2.6.1 에서 새로 webpack을 지원하는 것에 대한 의견을 듣고 싶습니다! 시도해 보시고 피드백을 코멘트나 Github에 남겨주세요!

Webpack과 자바스크립트용 AWS SDK 를 사용해 어플리케이션을 만들고 번들하기 – 파트 1

원문 : Using webpack and the AWS SDK for JavaScript to Create and Bundle an Application – Part 1

우리는 자바스크립트용 AWS SDK 2.6.1 버전에서 webpack에 대한 지원을 추가했습니다. webpack과 SDK 같은 툴을 사용하면 모듈화된 코드를 작성할 수 있도록 자바스크립트 모듈을 번들할 수 있는 방법을 제공합니다.

이 글은 webpack과 자바스크립트용 AWS SDK를 사용해서 버킷에 있는 Amazon S3 객체 목록를 보여주는 간단한 어플리케이션을 만들고 번들하는 방법을 설명합니다.

왜 webpack을 사용해야 할까?

webpack과 같은 툴은 어플리케이션 코드를 분석하고 import와 require 구문을 찾아 어플리케이션이 필요로하는 모든 에셋들을 가지는 번들을 생성합니다.

webpack은 기본적으로 자바스크립트 파일을 다루지만 JSON이나 CSS, 이미지 파일같이 다른 종류도 다루도록 설정할 수 있습니다! 이렇게하면 웹페이지를 통해 에셋을 쉽게 전달하도록 어플리케이션의 에셋을 잘 패키징할 수 있습니다.

webpack을 사용하면 필요한 서비스로 이루어진 번들을 만들고 Node.js에서도 작동하는 번들을 만들수 있습니다.

선행 조건

이 글을 따라가기 위해서 node.js와 npm이 설치되어 있어야 합니다 (npm은 node.js와 함께 설치됩니다). 이 툴들이 설치되어 있다면 새로운 디렉토리를 만들고 npm install x 명령어를 사용해 이 프로젝트에 필요한 의존성 파일들을 다운로드 합니다. x에는 아래와 같은 단어가 들어갑니다.

  • aws-sdk: AWS SDK
  • webpack: webpack CLI 와 자바스크립트 모듈
  • json-loader: webpack에게 JSON파일 읽는 방법을 알려주는 플러그인

어플리케이션 세팅하기

프로젝트를 저장하는 디렉토리를 생성하는 것으로 시작합니다. 프로젝트 이름은 aws-webpack으로 짓겠습니다.

어플리케이션은 아래에 있는 세개의 파일을 가집니다:

  • s3.js는 버킷을 문자열로 받아들이는 함수와 콜백 함수를 내보내고 객체 목록을 콜백 함수에 반환합니다.
  • browser.js는 s3.js 모듈을 포함하고 listObjects 함수를 호출하며 결과를 보여줍니다.
  • index.html은 webpack이 생성한 자바스크립트 번들을 참조합니다.

아래와 같이 프로젝트의 루트 디렉토리에 이 파일들을 생성합니다:

s3.js
중요: 보안 자격증명 설정은 스스로 하셔야 합니다.

// AWS SDK를 포함합니다
var AWS = require('aws-sdk');

// 지역(region)과 자격증명(credentials)을 설정 하세요,
// 이것은 서비스 클라이언트로 직접 이동할 수 있습니다
AWS.config.update({region: 'REGION', credentials: {/* */}});

var s3 = new AWS.S3({apiVersion: '2006-03-01'});

/**
 * 이 함수는 버킷에서 객체 목록을 검색합니다
 * 그 다음, 제공된 콜백을 전달받은 에러 혹은 데이터와 함께 실행합니다
 */
function listObjects(bucket, callback) {
  s3.listObjects({
    Bucket: bucket
  }, callback);
}

// 함수 핸들러를 내보냅니다
module.exports = listObjects;

browser.js

// listObjects 함수를 포함합니다
var listObjects = require('./s3');
var bucket = 'BUCKET';
// 특정한 버킷에서 listObjects 를 호출합니다
listObjects(bucket, function(err, data) {
  if (err) {
    alert(err);
  } else {
    var listElement = document.getElementById('list');
    var content = 'S3 Objects in ' + bucket + ':n';
    // 반환된 객체의 키 값을 출력합니다
    content +=  data.Contents.map(function(metadata) {
      return 'Key: ' + metadata.Key;
    }).join('n');
    listElement.innerText = content;
  }
});

지금, Amazon S3에 요청을 담당하는 자바스크립트 파일이 하나, 웹페이지에 S3 객체 목록을 추가하는 자바스크립트 파일이 하나, 하나의 div 태그와 script 태그를 가지고 있는 HTML파일이 있습니다. 웹페이지에서 데이터를 출력주기 전 마지막 순서로 webpack을 사용해서 script 태그를 참조하는 bundle.js 파일을 생성합니다.

webpack 설정하기

일반 자바스크립트 파일을 사용해서 webpack의 설정 옵션을 지정합니다. 기본적으로 webpack은 프로젝트의 루트 디렉토리에 있는 webpack.config.js 을 찾습니다. webpack.config.js 파일을 만들어 봅시다.

webpack.config.js

// 파일 경로를 분석하기 위해 path를 포함합니다
var path = require('path');
module.exports = {
  // 어플리케이션의 진입점을 지정합니다.
  entry: [
    path.join(__dirname, 'browser.js')
  ],
  // 번들된 코드를 포함하는 출력 파일을 지정합니다
  output: {
    path: __dirname,
    filename: 'bundle.js'
  },
  module: {
    /**
      * webpack에게 'json'파일 읽는 방법을 말해줍니다
      * 왜냐하면 기본적으로 webpack은
      * 자바스크립트 파일을 다루는 방법만 알기 때문입니다.
      * webpack이 'json' 파일이 포함되어있는 'require()' 구문을 만나면
      * json-loader를 사용하게 됩니다
      */
    loaders: [
      {
        test: /.json$/, 
        loaders: ['json']
      }
    ]
  }
}

webpack.config.js에서 진입점을 browser.js로 지정했습니다. 진입점이란 포함된 모듈 탐색을 시작하는 파일입니다. 그리고 출력을 bundle.js로 정의했습니다. 이 번들은 어플리케이션을 실행하기 위해 필요한 모든 자바스크립트를 포함합니다. s3.js가 browser.js에 포함되어있기 때문에 webpack은 이미 s3.js를 포함하는 것을 알고있습니다. 따라서 s3.js를 진입점으로 지정할 필요가 없습니다. 또한, aws-sdk가 s3.js에 포함되어 있기 때문에 aws-sdk를 포함해야 하는 것도 알고있습니다.

webpack에게 포함된 JSON 파일을 다루는 방법을 말해주는 로더를 지정했음을 주목하세요, 이 경우에 이전에 설치한 json-loader를 사용합니다. 기본적으로 webpack은 자바스크립트 파일만 지원하지만 로더를 사용해서 다른 종류의 파일을 포함하는 지원 또한 추가할 수 있습니다. AWS SDK는 JSON 파일을 엄청나게 사용하기 때문에 이런 추가적인 설정이 없으면 webpack이 번들을 생성할 때 에러를 던집니다.

webpack 실행하기

어플리케이션을 빌드할 준비가 거의 다 됐습니다! package.json에서 scripts 객체에 “build”: “webpack” 를 추가하세요.

{
  "name": "aws-webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "build": "webpack"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "aws-sdk": "^2.6.1"
  },
  "devDependencies": {
    "json-loader": "^0.5.4",
    "webpack": "^1.13.2"
  }
}

이제 커맨드라인에서 npm run build 명령어를 실행하면 webpack이 프로젝트 파일의 루트 디렉토리에 bundle.js 파일을 생성합니다. webpack이 알려주는 결과가 아래와 같아야 합니다:

    Version: webpack 1.13.2
    Time: 1442ms
      Asset     Size  Chunks             Chunk Names
    bundle.js  2.38 MB     0  [emitted]  main
      [0] multi main 28 bytes {0} [built]
      [1] ./browser.js 653 bytes {0} [built]
      [2] ./s3.js 760 bytes {0} [built]
       + 343 hidden modules

이제 브라우저에서 index.html파일을 열 수 있고 예시에 있는 것과 같은 출력을 볼 수 있습니다.

시도해 보세요!

다음 글에서는 webpack과 자바스크립트용 AWS SDK를 사용하는 것의 다른 기능을 살펴보겠습니다.

자바스크립트용 AWS SDK v2.6.1 에서 새로 webpack을 지원하는 것에 대한 의견을 듣고 싶습니다! 시도해 보시고 피드백을 코멘트나 Github에 남겨주세요!