Amazon Web Services 한국 블로그

Startup Kit Serverless Workload 예제 프로그램 소개

“AWS를 시작하는 가장 쉬운 방법은 무엇입니까?”라는 질문을 흔히 받습니다. AWS Elastic Beanstalk 등을 이용해 시작하는 좋은 방법이 여러 가지 있지만, 서버리스 컴퓨팅 역시 좋은 대안으로 급부상하고 있습니다.

서버리스 컴퓨팅은 서버에 대해 신경 쓰지 않고도 어플리케이션 및 서비스를 구축하고 실행할 수 있도록 해줍니다. AWS Lambda 서비스는 AWS에서의 서버리스 컴퓨팅을 구성하는 가장 핵심 빌딩 블록입니다. 이 외에도 AWS는 서버리스 아키텍처를 지원하는 여러 가지 서비스를 제공합니다. 여기에는 Lambda와 함께 RESTful API를 생성 할 수 있는 Amazon API Gateway와 데이터베이스 클러스터 설정으로부터 자유로운 NoSQL 클라우드 데이터베이스 서비스인 Amazon DynamoDB가 포함됩니다.

다음 도표는 하나의 완전한 서버리스 아키텍처를 나타냅니다:

serverless-arch

다이어그램의 아래쪽 서비스 그룹은 RESTful API 서비스를 구현합니다. API Gateway는 API 요청 및 응답을 처리하여 비즈니스 논리를 구현하는 Lambda 함수에 매핑합니다. DynamoDB는 지속적인 계층입니다. 다이어그램의 맨 위에 있는 서비스 그룹은 프론트 엔드를 형성합니다. Amazon S3는 AngularJS 또는 React 앱과 같은 정적 웹 자산을 호스팅하며 프론트 엔드 서버를 실행할 필요가 없는 완전 관리형 서비스입니다. S3 앞단에는 전 세계 사용자들과 가까운 엣지 로케이션(edge location)에서 웹 콘텐츠를 효율적으로 전달하기 위한 콘텐츠 전달 네트워크(CDN)인 Amazon CloudFront가 있습니다.

최근까지 서버리스 어플리케이션을 구현할 때 고려해야 할 사항 중 하나는 효율적으로 배포하는 방법이었습니다. 이제는AWS의 고유 솔루션인 AWS SAM(Serverless Application Model)이 이 문제를 해결해 줍니다. AWS SAM을 사용하면 간단한 YAML 기반 설명 언어와 단 2 개의 AWS CLI 명령을 사용하여 서버리스 배포를 쉽게 관리할 수 있습니다. AWS를 시작하는데 있어 서버리스 아키텍처를 구축하는 것이 가장 쉬운 방법일 수 있습니다. 특히 인프라 관리에 익숙하지 않은 사용자에게는 더욱 그렇습니다.

이 글에서는 AWS Startup Kit을 소개합니다. Startup Kit은 AWS를 시작하는 방법에 대한 지침을 제공하며 스타트업에서 흔히 사용하는 기술을 도입한 워크로드의 예제를 포함합니다. “워크로드”는 고객에게 노출된 RESTful API, 분석을 위한 일괄 처리 작업 등과 같이 비즈니스 또는 운영 가치를 제공하는 AWS에서 실행되는 하나 이상의 관련 어플리케이션을 말합니다.

Startup Kit 구성 요소는 Startup Kit Serverless Workload입니다. Lambda Node.js 4.3 런타임을 사용하여 빌드되고 SAM과 함께 배포되는 TODO 어플리케이션의 샘플 RESTful API입니다. Github의 startup-kit-serverless-workload저장소에서 코드를 확인할 수 있습니다. AWS 계정을 아직 설정하지 않았다면 AWS 계정을 설정하고 AWS CLI를 설치해야 합니다(자세한 내용은 여기에서 확인하실 수 있습니다).

서버리스 아키텍처의 이점
서버리스 아키텍처를 사용하면AWS Well-Architected framework의 많은 이점을 얻을 수 있습니다. Well-Architected Framework에 대한 자세한 내용은 본 포스팅의 범위를 벗어나지만, 간략하게 프레임워크에 해당하는 5개의 요소가 아키텍처에 어떻게 적용되는지 살펴 보겠습니다. 다음 요약 차트에서 “HA”는 고가용성(High Availability)을 의미하며 “OS”는 운영 체제 (Operating System)이며 “IAM”은 AWS 서비스 및 자원에 대한 액세스를 안전하게 제어 할 수 있는 AWS Identity and Access Management service를 의미합니다.

API Gateway Lambda DynamoDB
보안 기본 설정값: HTTPS
호출의 대역폭 조절 가능
IAM 또는 무기명 토큰 인증을 사용하여 API 콜 보안
AWS 관리형 OS
Lambda 함수의 다른 AWS 리소스에 대한 액세스는 이에 할당된 IAM 역할로 제한
IAM은 DynamoDB 리소스에 대한 세분화된 액세스 제어 제공 DynamoDB호출은 AWS CloudTrail을 사용하여 추적 가능
신뢰성 AWS 관리형 HA와 확장성
별도로 지정하지 않는 한 API 콜은 제한 안됨
AWS 관리형 HA와 확장성
실패한 비동기 호출이 재시도 되고 데드 레터 큐(DLQ)에 저장
AWS 관리형 HA와 확장성
데이터는 AWS 리전에 세 번 복제
성능 효율 결과 캐시 활성화 가능
서버리스 리소스는 필요할 때만 소비.
서버리스 리소스는 필요할 때만 소비 서버리스 리소스는 필요할 때만 소비.
비용 최적화 API 호출을 라우팅하기 위해 역방향 프록시 플릿 실행 필요 없음 함수 수행 중에만 비용 발생; 미 작동시에 비용 없음 Cluster 관리 없음
하드웨어 용량 예측 필요 없음
운영 효율성 SAM과 자동화
API 버저닝과 배포의 쉬운 관리
기본 매트릭스 제공; 로깅 활성화
SAM과 자동화
람다 콘솔에 기본 매트릭스 제공
Lambda 콘솔에서 링크로 로그 액세스 혹은 Amazon CloudWatch 콘솔 직접 이동
SAM과 자동화
DynamoDB 콘솔에 기본 매트릭스 제공
DynamoDB 스트림으로 테이블  변화에 대한 트래킹 가능

위 표는 Well-Architected framework의 가장 기초 사항에만 해당됩니다. AWS에서 서버리스 아키텍처를 구축해 나가면서 아키텍처를 개선할 추가 고려 사항 및 방법에 대해서는 Well-Architected Framework 백서를 참조하십시오.

워크로드 도입을 위해 SAM사용하기
SAM은 서버리스 어플리케이션을 정의하기 위한 모델입니다. SAM을 사용하려면 템플릿 파일에서 YAML (또는 JSON)로 서버리스 자원을 설명하고 두 개의 AWS CLI 명령을 사용하여 코드를 패키징 및 배포하십시오. SAM 자체는 오픈 소스 프로젝트이며 GitHub에서 사용할 수 있습니다. SAM은 “함수”(Lambda사용), “API”(API Gateway 사용) 및 “SimpleTable”(DynamoDB 사용)의 세 가지 기본 서버리스 자원을 지원합니다.

또한, SAM은 함수(예 : API)의 이벤트 소스 및 함수의 환경 변수와 같은 속성을 지정할 수 있습니다. SAM 템플릿을 더 단순화하려면 API를 함수의 이벤트 소스로 지정하세요. 그렇게 하면 SAM에서 명시적으로 API 리소스를 선언할 필요가 없습니다. 아래의 SAM 템플릿은 함수 리소스를 지정하는 것이 얼마나 간단한지 보여줍니다. 첫 번째 함수 인 CreateFunction은 TODO 응용 프로그램의 DynamoDB 테이블에서 새 TODO 항목을 만들기 위해 API 호출을 구현합니다.

서버리스 어플리케이션의 나머지 부분에 대한 CreateFunction의 관계는 SAM 템플릿에 완전히 지정됩니다. 예를 들어, CreateFunction이 DynamoDB 테이블과 상호 작용하는 방법을 지정하기 위해 템플릿은 DynamoDB 쓰기 권한을 포함하는 IAM 정책 인 CreateFunction과 연관되며 DynamoDB 테이블을 참조하는 환경 변수도 지정합니다. API 이벤트는 CreateFunction을 호출하기 위해 지정됩니다. 이 이벤트는 경로 및 HTTP 메소드(이 경우 POST)로 설명됩니다. SAM 템플리트의 다른 기능은 모두 동일한 기본 패턴을 따릅니다

YAML
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: RESTful API for a TODO app, backed by a SimpleTable (DynamoDB) resource.

Resources:
  
  CreateFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.create
      Runtime: nodejs4.3
      Policies: AmazonDynamoDBFullAccess
      Environment:
        Variables:
          TABLE_NAME: !Ref Table
      Events:
        PostResource:
          Type: Api
          Properties:
            Path: /todo/new
            Method: post

  GetAllFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.getAll
      Runtime: nodejs4.3
      Policies: AmazonDynamoDBReadOnlyAccess
      Environment:
        Variables:
          TABLE_NAME: !Ref Table
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /todo/all
            Method: get

  # API functions related to active TODO items
  
  GetActiveFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.getActive
      Runtime: nodejs4.3
      Policies: AmazonDynamoDBReadOnlyAccess
      Environment:
        Variables:
          TABLE_NAME: !Ref Table
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /todo/active
            Method: get

  UpdateActiveFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.updateActive
      Runtime: nodejs4.3
      Policies: AmazonDynamoDBFullAccess
      Environment:
        Variables:
          TABLE_NAME: !Ref Table
      Events:
        PutResource:
          Type: Api
          Properties:
            Path: /todo/active
            Method: put

  # API functions related to completed TODO items
  
  GetCompleteFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.getComplete
      Runtime: nodejs4.3
      Policies: AmazonDynamoDBReadOnlyAccess
      Environment:
        Variables:
          TABLE_NAME: !Ref Table
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /todo/complete
            Method: get

  MarkCompleteFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.markComplete
      Runtime: nodejs4.3
      Policies: AmazonDynamoDBFullAccess
      Environment:
        Variables:
          TABLE_NAME: !Ref Table
      Events:
        PutResource:
          Type: Api
          Properties:
            Path: /todo/complete
            Method: put

  DeleteCompleteFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.deleteComplete
      Runtime: nodejs4.3
      Policies: AmazonDynamoDBFullAccess
      Environment:
        Variables:
          TABLE_NAME: !Ref Table
      Events:
        DeleteResource:
          Type: Api
          Properties:
            Path: /todo/complete
            Method: delete

  Table:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
         Name: todo_id
         Type: String
      ProvisionedThroughput:
         ReadCapacityUnits: 5
         WriteCapacityUnits: 5

시작하기 전에, AWS CLI를 설치하거나 이전에 설치한 버전을 업데이트하세요. 본 포스팅에 사용된 일부 명령은 이전 버전의 AWS CLI에 없을 수 있습니다. AWS CLI와 연결하는 IAM 사용자는 IAM 역할을 생성하는 기능을 포함하는 관리자 권한이 있어야 합니다. Startup Kit Serverless Workload 배포를 시작하려면 GitHub에서 코드의 zip 파일을 다운로드하거나 다음 명령을 사용하여 GitHub 리포지토리를 복제하세요.

git clone https://github.com/awslabs/startup-kit-serverless-workload.git

배포를 계획중인 AWS 리전에서 SAM이 배포 아티팩트(Artifacts)를 넣을 수 있는 기존 Amazon S3 버킷을 가지고 있는지 확인하거나 다음 AWS CLI 명령을 사용하여 새로운 버킷을 만듭니다:

aws s3 mb s3://<your-bucket-name>

다음으로, 간단히 두 개의 AWS CLI 명령을 실행하면 됩니다. 첫 번째 명령인 package의 경우 s3-bucket 인수를 S3 버킷의 이름으로 바꿉니다. 두 번째 명령인 deploy의 경우 template-file 인수를 출력 템플릿 파일의 전체 경로로 바꿉니다.

aws cloudformation package \
--template-file serverless.cfn.yml \
--output-template-file serverless-xfm.cfn.yml \
--s3-bucket <your-bucket-name>
aws cloudformation deploy 
--template-file <path-to-file/serverless-xfm.cfn.yml> \
--stack-name StartupKitServerless \
--capabilities CAPABILITY_IAM

Deploy 명령이 완료되었다고 표시되면, 작업 워크로드가 실행 중인 겁니다! 이 두 명령은 SAM으로 작업할 때 배포 워크 플로(work flow)의 핵심입니다. 예를 들어, 코드를 수정하고 변경 사항을 배포하려는 경우, 패키지를 실행하고 명령을 다시 배포하기 만하면 됩니다. 그런 다음, 워크로드를 테스트하려면 API의 호출 URL을 가져옵니다.다음 bash 코드를 복사하여 터미널에 붙여 넣어 다른 지역 (예 : us-east-1)의 AWS 지역 코드 “us-west-2″를 현재 지역으로 바꾼 다음, 반환하시면 됩니다:

x=`aws cloudformation list-stack-resources --stack-name StartupKitServerless | grep -A2 'AWS::ApiGateway::RestApi' | grep 'PhysicalResourceId' | awk '{print $2}' | tr -d '"' | tr -d ","`; echo "https://$x.execute-api.us-west-2.amazonaws.com/Stage/"

(호출 URL를 가져오는 다른 방법으로는 API Gateway console에서 StartupKitServerless를 선택하고, 왼쪽 탐색 창에서 스테이지를 선택한 다음, 스테이지 목록에서 스테이지를 선택하면, API의 호출 URL이 이제 오른쪽 상단에 나타납니다. 마지막 URL에 ‘/ Stage’를 포함하여 전체 URL을 복사하면 됩니다.) ‘Create API’를 사용하여 일부 TODO 항목을 추가하여 테스트를 시작하세요. 그러면 다음 명령을 사용하여 수행할 수 있습니다:

curl -X POST -H 'Content-Type: application/json' -d '{"todo_id": "1001", "active": true, "description": "What TODO next?"}' https://<invoke-URL-for-your-API>/todo/new

작성한 활성 TODO 항목을 가져 오려면 다음 명령을 실행하세요:

curl https://<invoke-URL-for-your-API>/todo/active

유사한 명령을 사용하여 다른 모든 API 호출을 테스트할 수 있습니다.

AWS SAM 및 서버리스 아키텍처를 사용하는 것은 AWS를 시작하는 가장 쉬운 방법 중 하나입니다. Startup Kit Serverless Workload에 관한 제안, 의견 또는 수정 사항이 있으면 GitHub에 요청해주세요. 앞으로 더 많은 Startup Kit으로 찾아 뵙겠습니다!

이 글은 Introducing the ‘Startup Kit Serverless Workload’의 한국어 번역으로 이창수 AWS 솔루션즈 아키텍트가 번역해 주셨습니다.