버전 비교

  • 이 줄이 추가되었습니다.
  • 이 줄이 삭제되었습니다.
  • 서식이 변경되었습니다.

...

실습이 종료되고 나면 리소스를 삭제해야 합니다. 해당 핸즈온은 CloudFormation 기반으로 진행됩니다. 배포 Stack을 삭제하고, 실습에 사용한 Cloud9과 같은 Stack을 삭제하면, 배포되어 있는 리소스도 함께 삭제가 됩니다. 반드시 상단에 게시된 리소스에 대해서 삭제가 이루어졌는지 확인 후 실습을 종료합니다. 만약 S3 버킷에 객체가 남아 있어서 삭제가 되지 않는 경우, 해당 S3 버킷을 직접 삭제하고 확인 합니다.

...


서버리스 웹

...

애플리케이션 구축 방법 소개

아래는 실습에 구축할 서버리스 웹 애플리케이션의 다이어그램입니다. 서버리스 서비스를 이용하기 때문에, 프로비저닝, 패치, 확장에 대해 고민할 필요가 없으며, 사용한 만큼만 비용을 지불합니다. 또한, 서버리스 서비스는 완전 관리형 서비스이기 때문에, 개발자는 애플리케이션 개발 자체에만 집중할 수 있습니다.

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNameServerlessPolly
simpleViewerfalse
width
diagramWidth1340
revision5

...


구성 영역별 소개

이 애플리케이션은 다섯 가지 영역으로 구분할 수 있습니다.

  1. 정적 웹페이지 구현 - StaticWebBucket

    1. 이 시나리오는 Amazon S3(Simple Storage Service)에서 호스팅되는 정적 웹 페이지를 기반으로 실행합니다.

  2. 새로운 뉴스를 등록 - PostNews

    1. MP3로 생성할 텍스트 정보는 Amazon API Gateway에 의해 노출된 RESTful API로 수신합니다.
    2. Amazon API Gateway는 MP3 파일 생성 프로세스를 초기화하는 전용 Lambda 함수인 "PostNews"를 설정합니다.
    3. "PostNews" Lambda 함수는 News에 대한 메타 정보를 "NewsTable" DynamoDB 테이블에 저장합니다.
    4. TTS 변환 프로세스를 비동기적으로 실행하기 위해 Amazon SNS의 Topic(NewsTopic)에 DynamoDB(NewsTable)에 등록한 새로운 id 값을 게시합니다.

  3. 텍스트를 MP3로 변환 - ConvertAudio

    1. Amazon SNS Topic에 의해서 트리거된 Lambda 함수인 "ConvertAudio"는 요청 텍스트를 오디오 파일로 변환합니다.
    2. "ConvertAudio" Lambda 함수는 Amazon Polly를 사용하여 텍스트를 지정된 언어의 음성을 이용하여 오디오 파일로 변환합니다.
    3. 생성된 오디오 파일인 MP3 파일은 전용 S3 버킷인 "PollyMp3Bucket"에 저장합니다.
    4. MP3는 S3 버킷에 대한 참조 URL 정보 및 해당 게시물 처리 상태에 대한 정보는 DynamoDB 테이블에 업데이트 합니다.

  4. 등록된 뉴스 정보 검색 - GetNews

    RESTful 웹 서비스는 Amazon API Gateway를 사용하여 배포합니다. Amazon API Gateway는 게시물에
    1. GET 메서드를 이용해서 뉴스에 대한 정보를 검색하는 방법을 제공합니다.
    이 방법은 게시물의 텍스트와 MP3 파일이 저장되는 S3 버킷에 대한 링크가 포함됩니다. 이 시나리오에서 이 웹 서비스는 Amazon S3에서 호스팅되는 정적 웹 페이지에서 호출됩니다.Amazon API Gateway는 뉴스를 검색하는 Lambda 함수인
    1. "GetNews
    "를 호출합니다."Get Post
    1. " Lambda 함수는 DynamoDB 테이블에서
    게시물에 대한 정보(Amazon S3에 대한 참조 URL을 포함)를 검색합니다
    1. 뉴스 텍스트에 대한 정보와 버킷에 업로드한 MP3 버킷 URL 정보를 제공합니다.

  5. 기존 뉴스 삭제 - DeleteNews

    1. RESTful
    API의
    1. API로 Delete 메서드를 이용하여 삭제를 요청합니다.
    API Gateway는 뉴스 데이터를 삭제하는 Lambda 함수인
    1. "DeleteNews"
    를 호출합니다
    1. Lambda 함수는 DynamoDB에 저장되어 있는 해당 News 항목과 관련되어 생성한 MP3를 삭제합니다.


실습

이 예제는 Cloud9이 존재하는 Singapore 리전에서 English 언어로 진행합니다.

실습은 다음과 같은 순서로 진행됩니다.

Lab1. Cloud 9을 이용한 웹 애플리케이션 구축 실습

실습 순서는 다음과 같이 Lab1과 Lab2로 구성되어져 있습니다.

Lab1. Cloud9을 이용한 서버리스 웹 애플리케이션 구축

Lab1은 Cloud9 IDE를 이용하여 서버리스 웹 애플리케이션을 구축하는 방법을 살펴봅니다. 이 실습은 Cloud9이 존재하는 Singapore 리전에서 English 언어로 진행합니다. 통합 개발 환경(IDE)은 싱가포르 리전을 사용하지만, 서비스 배포는 리전을 선택 할 수 있습니다.  이 실습에서는 배포 서비스의 확인을 간단히 하기 위해서 Singapore 리전을 그대로 사용하겠습니다.

  1. Cloud9 IDE 환경 생성

    1. AWS 콘솔 환경에서 Cloud9 서비스로 이동합니다.
      Image Added

    2. Create environment 버튼을 클릭하여 Cloud9 환경을 생성합니다.
      Image Added

    3. Cloud9 이름을 NewsWebApp 이라고 생성합니다. 설명(News Web Application using Serverless Service)은 옵션이기 때문에 넣지 않아도 됩니다. 
      Image Added

    4. Cloud9의 환경설정을 합니다. 개발환경은 EC2 인스턴스로 선택하고 인스턴스 타입은 t2.micro를 선택합니다. 프리티어로 사용할 수 있습니다. Cloud9 IDE를 30분간 사용하지 않으면, 자동으로 EC2 인스턴스가 Stop 되어 비용을 절감할 수 있는 옵션을 기본적으로 제공합니다.
      Image Added

    5. Cloud9 최종 점검을 합니다. 모든 검수가 완료되면 Create environment 버튼을 클릭합니다.
      Image Added

    6. Cloud9 IDE가 준비중인 것을 확인할 수 있습니다. 몇 분이 지나면 IDE가 활성화 됩니다.
      Image Added

    7. Cloud9에서 IDE에 대해서 환경 설정을 할 수 있습니다. 화면과 같이 서비스 배포를 위한 리전을 별도로 지정할 수 있습니다. 여기서는 Singapore 리전을 그대로 사용합니다.
      Image Added

    8. 개발 환경이 설치되고 서버리스 애플리케이션 개발을 할 준비가 완료되었습니다.
  2. Cloud9 IDE 환경 생성
  3. Application 및 "PostNews" Lambda 함수 생성

  4. SAM

    (template.yml)에 DynamoDB, SNS, S3(Web, Mp3) 리소스 추가하기

    기반 서버리스 리소스 추가

  5. "ConvertAudio" Lambda 함수 생성

  6. "GetNews" Lambda 함수 생성

  7. "DeleteNews" Lambda 함수 생성

  8. SAM에서의 Outputs 설정

  9. SAM에서의 CORS

    SAM의 Output

    설정

  10. 정적 웹 호스팅을 위한 파일 업로드하기

  11. 서비스 동작 테스트

  12. SAM을 CloudFormation 스택에 직접 반영하기

Lab2. Code* 서비스를 이용한 서버리스

...

CI/CD 배포 프로세스 구축

...

  1. 소스 리포지토리를 위해서 CodeCommit 생성

  2. CodeBuiild를 위한  buildspec.yaml 파일 생성

  3. CodePipeline 구축하기

  4. 소스 리포티토리에 코드 체크인하기

  5. 배포 결과 확인 (S3 정적 웹 페이지는 다루지 않습니다.)

  6. API를 이용해서 결과 확인

  7. Canary 배포를 위한 설정하기

  8. CloudFormation에서 CodeDeploy 할 수 있도록 IAM 정책 설정 적용

  9. 코드를 변경하여 배포하고 CodeDeploy 중에 API를 호출하여 적용되는지 확인하기

  10. 기존 배포 버전으로 롤백하기

...

Lab3.

...

Cloud9 IDE 환경 생성

...

X-ray를 이용한 서버리스 서비스 모니터링 및 디버깅 (9월 예정)

Lab4. LocalStack을 이용한 로컬 테스트 환경 구축 및 테스트 (미정)

Lab5. ElasticSearch를 이용한 검색 서비스 구축 (미정)

...


Application 및 "PostNews" Lambda 함수 생성

  1. 새로운 애플리케이션 및 람다 함수 생성합니다. Cloud9 IDE 우측 네비게이션의 AWS Resources 탭을 클릭하고, Lambda 아이콘을 클릭하면 새로운 함수를 생성할 수 있습니다.
  2. Application name에는 WebApp을 Function name에는 PostNews를 입력하고 Next 버튼을 클릭합니다.
  3. Runtime은 Python 2.7을 선택하고, Blueprint는 hello-world-python을 선택하고 Next 버튼을 클릭합니다.
  4. 가나다
  5. 가나다
  6. 가나다
  7. 가나다
  8. 가나다

    코드 블럭
    languagepy
    themeRDark
    titlePostNews
    linenumberstrue
    # -*- coding: utf-8 -*-
    from __future__ import print_function
    
    import boto3
    import os
    import json
    import uuid
    import datetime
    
    def lambda_handler(event, context):
        if "body" in event:
            event = json.loads(event['body'])
        print (event)
        
        recordId = str(uuid.uuid4())
        voice = event["voice"]
        originText = event["text"]
        timbre = event["timbre"]
        pitch = event["pitch"]
        updateDate = datetime.datetime.now().strftime("%Y%m%d")
        print('Generating new DynamoDB record, with ID: ' + recordId)
    
        # Create the item in DynamoDB table
        dynamodb = boto3.resource('dynamodb')
        table = dynamodb.Table(os.environ['DB_TABLE_NAME'])
        table.put_item(
            Item={
                'id' : recordId,
                'originText': originText,
                'postDate': int(updateDate),
                'pollyVoice' : voice,
                'pollyStatus' : "PROCESSING",
                'pollyTimbre': timbre,
                'pollyPitch': pitch
            }
        )
        
        # Sending notification about new post to SNS
        client = boto3.client('sns')
        client.publish(
            TopicArn = os.environ['SNS_TOPIC'],
            Message = recordId
        )
        
        response = {
            'statusCode': 200,
            'body': json.dumps({'recordId': recordId}),
            'headers': {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'
            }
        }
        
        return response


  9. 가나다
  10. 가나다

    코드 블럭
    languageyml
    themeRDark
    titlePostNewsTemplate_01
    linenumberstrue
    AWSTemplateFormatVersion: '2010-09-09'
    Transform: 'AWS::Serverless-2016-10-31'
    Description: >-
      Building Serverless development environment and CI/CD process for DevOps based
      on Cloud9
    
    Globals:
      Function:
        Runtime: python2.7
        Handler: lambda_function.lambda_handler
        MemorySize: 128
        Timeout: 60
    
    Resources:
      PostNews:
        Type: 'AWS::Serverless::Function'
        Properties:
          CodeUri: PostNews
          Description: Post news text to convert from text to speech
          Events:
            PostNewsApi:
              Type: Api
              Properties:
                Path: /news
                Method: POST
          Policies:
            - Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action:
                    - 'logs:PutLogEvents'
                    - 'logs:CreateLogStream'
                    - 'dynamodb:PutItem'
                    - 'sns:Publish'
                  Resource: '*'
    


  11. 배포하기

...

  1. 가나다

    코드 블럭
    languageyml
    themeRDark
    titlePostNewsTemplate_02
    linenumberstrue
    AWSTemplateFormatVersion: '2010-09-09'
    Transform: 'AWS::Serverless-2016-10-31'
    Description: >-
      Building Serverless development environment and CI/CD process for DevOps based
      on Cloud9
    
    Globals:
      Function:
        Runtime: python2.7
        Handler: lambda_function.lambda_handler
        MemorySize: 128
        Timeout: 60
        Environment:
          Variables:
            DB_TABLE_NAME:
              Ref: NewsTable
            SNS_TOPIC:
              Ref: NewsTopic
            BUCKET_NAME:
              Ref: PollyMp3Bucket
    
    Resources:
    
      NewsTable:
        Type: 'AWS::Serverless::SimpleTable'
        Properties:
          PrimaryKey:
            Name: id
            Type: String
          ProvisionedThroughput:
            ReadCapacityUnits: 5
            WriteCapacityUnits: 5
    
      NewsTopic:
        Type: 'AWS::SNS::Topic'
        Properties:
          DisplayName: NewsTopic
    
      PollyMp3Bucket:
        Type: 'AWS::S3::Bucket'
    
      StaticWebBucket:
        Type: 'AWS::S3::Bucket'
        Properties:
          AccessControl: PublicRead
          WebsiteConfiguration:
            IndexDocument: index.html
            ErrorDocument: error.html
    
      PostNews:
        Type: 'AWS::Serverless::Function'
        Properties:
          CodeUri: PostNews
          Description: Post news text to convert from text to speech
          Events:
            PostNewsApi:
              Type: Api
              Properties:
                Path: /news
                Method: POST
          Policies:
            - Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action:
                    - 'logs:PutLogEvents'
                    - 'logs:CreateLogStream'
                    - 'dynamodb:PutItem'
                    - 'sns:Publish'
                  Resource: '*'


  2. 가나다

  3. 가나다


"ConvertAudio" Lambda 함수 생성

  1. 가나다
  2. 가나다
  3. 가나다
  4. 가나다
  5. 가나다
  6. 가나다
  7. 가나다

"GetNews" Lambda 함수 생성

  1. 가나다
  2. 가나다
  3. 가나다


"DeleteNews" Lambda 함수 생성

  1. 가나다
  2. 가나다
  3. 가나다

S3 정적 컨텐츠 업로드

  1. 가나다
  2. 정적 웹 호스팅 파일 다운로드 받기

    코드 블럭
    languagebash
    themeRDark
    linenumberstrue
    wget https://s3.ap-northeast-2.amazonaws.com/polly.awsdemokr.com/301_static_web.zip


  3. 축 풀고 폴더 이동

    코드 블럭
    languagebash
    themeRDark
    linenumberstrue
    unzip 301_static_web.zip
    cd 301_static_web


  4. Cloud9에서 scripts.js 파일 열어서 CloudFormation Stack에 배포된 Output의 APIEndpointURL 값을 소스코드에 반영 (WebsiteURL이 아니므로 주의)

    코드 블럭
    languagejs
    themeRDark
    linenumberstrue
    var API_ENDPOINT = "https://xxxxxxxxxx.execute-api.ap-southeast-1.amazonaws.com/Prod/news/";
    if (API_ENDPOINT === "")
    {
            alert("scripts.js 파일의 상단에 API Gateway에 배포한 URL을 등록하고 실행하세요.");
    }


  5. 정적 웹 포스팅하고자 하는 S3 버킷에 public-read 권한으로 파일을 업로드 (CloudFormation Stack에 배포된 Output의 S3WebBucket 값을 아래에 대체)

    코드 블럭
    languagebash
    themeRDark
    linenumberstrue
    aws s3 sync . s3://cloud9-webapp-staticwebbucket-xxxxxxxxxxxx --acl public-read


  6. 웹 브라우저로 정적 웹 페이지에 접속 (CloudFormation Stack에 배포된 Output의 WebsiteURL 값을 웹 브라우저 주소창에 입력)
    1. https://cloud9-webapp-staticwebbucket-xxxxxxxxxxxx.s3.amazonaws.com

...