AWS
  • About
  • 수업준비
    • AWS 환경설정
  • 1주차 - EC2
    • 예습
    • 실습
    • AWS Skill Builder
    • 과제
  • 2주차 - ELB & Autoscaling
    • 예습
    • 실습
    • AWS Skill Builder
    • 과제
  • 3주차 - VPC
    • 예습
    • 실습
    • AWS Skill Builder
    • 과제
  • 4주차 - Database
    • 예습
    • 실습
    • AWS Skill Builder
    • 과제
  • 5주차 - Storage
    • 예습
    • 실습
    • AWS Skill Builder
    • 과제
  • 6주차 - IAM & Security
    • 예습
    • 실습
    • AWS Skill Builder
    • 과제
  • 7주차 - Monitoring & Ops
    • 예습
    • 실습
    • AWS Skill Builder
    • 과제
  • 8주차 - DevOps
    • 예습
    • 실습
    • 과제
  • EKS
    • 실습
    • 실습 (AWS Worshop Studio)
  • Serverless
    • 실습
  • FAQ
  • Archive
    • AWS CodeBuild로 애플리케이션 테스트 자동화 시스템 구축
    • AWS CodeDeploy로 애플리케이션 배포 자동화 시스템 구축
      • 배포 실패 수정 방법
Powered by GitBook
On this page
  • Introduction: Build a Serverless Web Application
  • Overview
  • Application Architecture
  • Modules
  • Module 1: Static Web Hosting with Continuous Deployment
  • Overview
  • Architecture Overview
  • Implementation
  • Module 2: User Management
  • Overview
  • Architecture Overview
  • Implementation
  • Module 3: Serverless Service Backend
  • Overview
  • Architecture Overview
  • Implementation
  • Module 4: Deploy a RESTful API
  • Overview
  • Architecture Overview
  • Implementation

Was this helpful?

  1. Serverless

실습

해당 실습은 AWS에서 제공하는 Build a Serverless Web Applcation의 내용을 기반으로 작성되었습니다. https://aws.amazon.com/getting-started/hands-on/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito/

PreviousServerlessNextFAQ

Last updated 3 years ago

Was this helpful?

Introduction: Build a Serverless Web Application

Overview

해당 실습에서는 사용자가 에서 유니콘 탑승을 요청할 수 있도록 하는 간단한 서버리스 웹 애플리케이션을 생성합니다. 애플리케이션은 사용자에게 원하는 픽업 위치를 표시하기 위한 HTML 기반 사용자 인터페이스(UI)를 제공하고 RESTful 기반의 백엔드 서비스와 연계해서 최적의 유니콘을 배정합니다. 응용 프로그램은 사용자가 승차를 요청하기 전에 회원 가입 및 로그인할 수 있는 기능을 제공합니다.

Application Architecture

해당 애플리케이션은 AWS Lambda , Amazon API Gateway , Amazon DynamoDB , Amazon Cognito 및 AWS Amplify를 이용해서 구축될 예정입니다. Amplify는 HTML, CSS, JavaScript 및 사용자 브라우저에 로드되는 이미지 파일을 포함한 정적 웹 리소스의 지속적인 배포(Continuous Deployment) 및 호스팅을 제공합니다. 브라우저에서 실행되는 JavaScript는 Lambda 및 API Gateway를 사용하여 구축된 퍼블릭 백엔드 API를 통해서 데이터를 송수신합니다. Amazon Cognito는 사용자 관리 및 백엔드 API와의 인증 기능을 제공합니다. 마지막으로 DynamoDB에 애플리케이션 데이터를 저장합니다.

Modules

이 워크샵은 4개의 모듈로 나뉩니다. 각 모듈은 아키텍처를 구현하고 작업을 확인하는 데 도움이 되는 빌드 및 단계별 지침에 대한 시나리오를 설명합니다.

  1. 정적 웹 사이트 호스팅: 내장된 지속적 배포를 통해 웹 애플리케이션에 대한 정적 리소스를 호스팅하도록 AWS Amplify 구성

  2. 사용자 관리: Amazon Cognito 사용자 풀을 생성하여 사용자 계정 관리

  3. 서버리스 백엔드 구축: 웹 애플리케이션에 대한 요청을 처리하기 위한 Lambda 함수 구축

  4. RESTful API 배포: Amazon API Gateway를 사용하여 이전 모듈에서 구축한 Lambda 함수를 RESTful API로 노출

Module 1: Static Web Hosting with Continuous Deployment

Overview

이 모듈에서는 웹 애플리케이션의 정적 리소스(프론트엔드)를 S3로 호스팅하도록 AWS Amplify를 구성합니다. Amplify는 풀스택 웹 애플리케이션의 지속적인 배포 및 호스팅을 위한 git 기반 워크플로우를 제공합니다. 후속 모듈에서는 JavaScript를 사용하여 이러한 페이지에 동적 기능을 추가하여 AWS Lambda 및 Amazon API Gateway로 구축된 RESTful API를 호출합니다

Architecture Overview

해당 모듈의 아키텍처는 매우 간단합니다. AWS Amplify 콘솔에서 HTML, CSS, JavaScript, 이미지 및 기타 파일을 포함한 모든 정적 웹 콘텐츠를 관리되며 별도의 웹서버를 구축 하지 않고 AWS Amplify 콘솔에서 제공하는 URL을 통해서 사이트에 접근할 수 있습니다.

Implementation

Select a Region

1. 리전을 Asia Pacific (Seoul) - ap-northeast-2로 변경

2. AWS 관리 콘솔에서 Cloud9 서비스로 이동

3. 이미 생성되어 있는 serverless-lab Cloud9 인스턴스를 선택하고 Open IDE 를 클릭해서 인스턴스를 구동

4. IDE가 구동되는데 짧게는 몇 초, 길게는 수분까지 걸릴 수 있으며 구동이 완료되면 다음 화면이 표시됩니다.

Create a Git repository

1. AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 CodeCommit을 검색하거나 [Developer Tools] 카테고리에 있는 [CodeCommit] 를 선택

2. [Create repository] 클릭

3. Repository name에 wildrydes-site 를 입력하고 [Create] 클릭

4. 리포지토리를 복제하는 명령어를 클립보드로 복사 - [Copy] 클릭

5. Cloud9 인스턴스의 터미널로 이동해서 이전 단계에서 복사한 명령어를 붙여넣고 실행하거나 아래의 명령어 실행

git clone https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/wildrydes-site

정상으로 동작할 경우 아래와 같은 화면이 출력

lab-user:~/environment $ git clone https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/wildrydes-site
Cloning into 'wildrydes-site'...
warning: You appear to have cloned an empty repository.
lab-user:~/environment $ 

Populate the Git repository

1. S3에 저장된 정적 컨텐츠를 Cloud9 인스턴스에 복제한 리포지토리 디렉토리로 복사

cd ~/environment/wildrydes-site
aws s3 cp s3://youngwjung/labs/serverless/wildrydes-site . --recursive

2. 변경사항(정적 컨텐츠 추가)을 CodeCommit 리포지토리에 반영

git add .
git commit -m "add static files"
git push

정상으로 동작할 경우 아래와 같은 화면이 출력

lab-user:~/environment/wildrydes-site (master) $ git add .
lab-user:~/environment/wildrydes-site (master) $ git commit -m "add static files"
[master (root-commit) 0c18951] add static files
 Committer: EC2 Default User <ec2-user@ip-10-0-82-242.ap-northeast-2.compute.internal>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 91 files changed, 13680 insertions(+)
 create mode 100644 apply.html
 create mode 100644 css/bootstrap.min.css
 create mode 100644 css/bootstrap.min.css.map
 create mode 100644 css/font.css
 create mode 100644 css/index.css
 create mode 100644 css/main.css
 create mode 100644 css/mapbox-gl.css
 create mode 100644 css/message.css
 create mode 100644 css/normalize.css
 create mode 100644 css/ride.css
 create mode 100644 faq.html
 create mode 100644 favicon.ico
 create mode 100644 fonts/fairplex-wide-n4.woff
 create mode 100644 fonts/fairplex-wide-n7.woff
 create mode 100644 fonts/glyphicons-halflings-regular.eot
 create mode 100644 fonts/glyphicons-halflings-regular.svg
 create mode 100644 fonts/glyphicons-halflings-regular.ttf
 create mode 100644 fonts/glyphicons-halflings-regular.woff
 create mode 100644 fonts/glyphicons-halflings-regular.woff2
 create mode 100644 images/background.png
 create mode 100644 images/bbd3207c.png
 create mode 100644 images/bucephalus.png
 create mode 100644 images/loading.gif
 create mode 100644 images/logo.png
 create mode 100644 images/rocinante.png
 create mode 100644 images/shadowfox.png
 create mode 100644 images/spinning-gears.gif
 create mode 100644 images/star-pattern.png
 create mode 100644 images/unicorn-icon.png
 create mode 100644 images/unicorn-logo.png
 create mode 100644 images/unicorn-map-bg.png
 create mode 100644 images/unicorn-silhouette.png
 create mode 100644 images/wr-apply-header.png
 create mode 100644 images/wr-faq-header.jpg
 create mode 100644 images/wr-home-W.png
 create mode 100644 images/wr-home-Xiaomi.png
 create mode 100644 images/wr-home-about.jpg
 create mode 100644 images/wr-home-apple.png
 create mode 100644 images/wr-home-blackberry.png
 create mode 100644 images/wr-home-block-1.png
 create mode 100644 images/wr-home-block-2.png
 create mode 100644 images/wr-home-block-3.png
 create mode 100644 images/wr-home-block-4.png
 create mode 100644 images/wr-home-facebook.png
 create mode 100644 images/wr-home-google.png
 create mode 100644 images/wr-home-instagram.png
 create mode 100644 images/wr-home-kraken.png
 create mode 100644 images/wr-home-quote.jpg
 create mode 100644 images/wr-home-quote.png
 create mode 100644 images/wr-home-top.jpg
 create mode 100644 images/wr-home-twitter.png
 create mode 100644 images/wr-home-wechat.png
 create mode 100644 images/wr-home-weibo.png
 create mode 100644 images/wr-investors-1.png
 create mode 100644 images/wr-investors-2.png
 create mode 100644 images/wr-investors-3.png
 create mode 100644 images/wr-investors-4.png
 create mode 100644 images/wr-investors-5.png
 create mode 100644 images/wr-investors-awesome.png
 create mode 100644 images/wr-investors-header.png
 create mode 100644 images/wr-investors-pcp.png
 create mode 100644 images/wr-investors-thebarn.png
 create mode 100644 images/wr-logo-black.png
 create mode 100644 images/wr-logo-white.png
 create mode 100644 images/wr-unicorn-header.png
 create mode 100644 images/wr-unicorn-one.png
 create mode 100644 images/wr-unicorn-three.png
 create mode 100644 images/wr-unicorn-two.png
 create mode 100644 index.html
 create mode 100644 investors.html
 create mode 100644 js/cognito-auth.js
 create mode 100644 js/config.js
 create mode 100644 js/esri-map.js
 create mode 100644 js/main.js
 create mode 100644 js/ride.js
 create mode 100644 js/vendor.js
 create mode 100644 js/vendor/amazon-cognito-identity.min.js
 create mode 100644 js/vendor/aws-cognito-sdk.min.js
 create mode 100644 js/vendor/bootstrap.min.js
 create mode 100644 js/vendor/html5shiv.min.js
 create mode 100644 js/vendor/jquery-3.1.0.js
 create mode 100644 js/vendor/modernizr.js
 create mode 100644 js/vendor/moment.min.js
 create mode 100644 js/vendor/respond.min.js
 create mode 100644 js/vendor/unicorn-icon
 create mode 100644 register.html
 create mode 100644 ride.html
 create mode 100644 robots.txt
 create mode 100644 signin.html
 create mode 100644 unicorns.html
 create mode 100644 verify.html
lab-user:~/environment/wildrydes-site (master) $ git push
Enumerating objects: 95, done.
Counting objects: 100% (95/95), done.
Delta compression using up to 2 threads.
Compressing objects: 100% (94/94), done.
Writing objects: 100% (95/95), 9.44 MiB | 16.58 MiB/s, done.
Total 95 (delta 2), reused 0 (delta 0)
To https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/wildrydes-site
 * [new branch]      master -> master
lab-user:~/environment/wildrydes-site (master) $ 

Enable Web Hosting with the AWS Amplify Console

1. AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 AWS Amplify를 검색하거나 [Front-end Web & Mobile] 카테고리에 있는 [AWS Amplify] 를 선택

2. 페이지 하단의 Amplify Hosting에서 [Get started] 클릭

3. 소스코드 제공자에 AWS CodeCommit를 선택하고 [Continue] 클릭

4. Repository = wildrydes-site, Branch = master, [Next] 클릭

5. 빌드 설정에서 Allow AWS Amplify to automatically deploy all files hosted in your project root directory 를 체크하고 [Next] 클릭

6. 리뷰 화면에서 [Save and deploy] 클릭

7. 애플리케이션 배포가 시작되고

배포가 완료되면 아래와 같은 화면이 표시

8. Amplify 콘솔에서 표시되는 URL 주소를 클릭해서 사이트로 접속이 되는지 확인

정상적으로 배포되었을 경우에 아래와 같은 페이지가 보여짐

Modify your site

1. Cloud9 인스턴스로 이동해서 wild-ryde-site/index.html 파일을 텍스트 에디터로 열기

2. 7번 라인에 있는 <title>Wild Rydes</title> 를 <title>Wild Rydes - Rydes of the Future!</title> 로 변경하고 저장

i.e.

<!doctype html>
<html class="no-js" lang="">
<head>
  <meta charset="utf-8">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Wild Rydes - Rydes of the Future!</title>

  <link rel="stylesheet" href="css/font.css">
  <link rel="stylesheet" href="css/main.css">

  <script src="js/vendor/modernizr.js"></script>
</head>

3. 변경사항(타이틀 변경)을 CodeCommit 리포지토리에 반영

cd ~/environment/wildrydes-site
git add index.html
git commit -m "update title"
git push

정상으로 동작할 경우 아래와 같은 화면이 출력

lab-user:~/environment/wildrydes-site (master) $ cd ~/environment/wildrydes-site
lab-user:~/environment/wildrydes-site (master) $ git add index.html
lab-user:~/environment/wildrydes-site (master) $ git commit -m "update title"
[master bfceb2f] update title
 Committer: EC2 Default User <ec2-user@ip-10-0-82-242.ap-northeast-2.compute.internal>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 file changed, 1 insertion(+), 1 deletion(-)
lab-user:~/environment/wildrydes-site (master) $ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 345 bytes | 345.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/wildrydes-site
   0c18951..bfceb2f  master -> master
lab-user:~/environment/wildrydes-site (master) $ 

4. Amplify 콘솔로 이동해서 변경분이 배포되고 있는지 확인

5. 사이트에 접속해서 타이틀이 변경되었는지 확인

Recap

해당 모듈에서는 Wild Rydes 비즈니스의 기반이 될 정적 웹사이트를 만들었습니다. AWS Amplify Console을 사용하면 지속적 통합 및 제공(CI/CD) 모델에 따라 정적 웹 사이트를 정말 쉽게 배포할 수 있습니다. 더 복잡한 Javascript 프레임워크 기반 응용 프로그램을 "구축"하는 기능이 있으며 브랜치 기반 배포, 사용자 지정 도메인 설정, 즉각 배포 및 암호 보호와 같은 기능이 있습니다.

Module 2: User Management

Overview

이 모듈에서는 사용자 계정을 관리를 위해 Amazon Cognito 사용자 풀을 생성합니다. 고객이 새 사용자로 등록하고, 이메일 주소를 검증하고, 사이트에 로그인할 수 있는 페이지도 배포할 예정입니다.

Architecture Overview

사용자가 웹사이트를 처음으로 방문하면 가정 먼저 새계정을 등록합니다. 해당 워크숍에서는 실습 목적상 이메일 주소와 비밀번호로만 계정 생성을 진행할 예정이지만 실제로 애플리케이션 구축시에는 추가 속성을 요구하도록 Amazon Cognito를 구성할 수 있습니다.

사용자가 계정 생성 요청을 하면 Amazon Cognito에서 사용자가 제공한 이메밀 주소로 인증 코드가 포함된 이메일을 보냅니다. 이메일 주소 검증을 위해 사용자는 사이트로 돌아가 이메일 주소와 인증 코드를 입력합니다. 테스트 용도로 임의의 이메일 주소를 사용하려는 경우 Amazon Cognito 콘솔을 사용하여 이메일 계정을 검증 할수도 있습니다.

사용자가 확인된 계정(이메일 확인 프로세스 사용 또는 콘솔을 통한 수동 확인 사용)을 갖고 나면 로그인할 수 있습니다. 사용자가 로그인할 때 사용자 이름(또는 이메일)과 비밀번호를 입력합니다. 그런 다음 JavaScript 코드에서 Amazon Cognito와 통신하고 SRP(Secure Remote Password) 프로토콜을 사용하여 인증하고 JWT(JSON Web Tokens) 을 발급 받습니다. JWT에는 사용자 ID에 대한 정보가 포함되어 있으며 다음 모듈에서 Amazon API Gateway로 구축한 RESTful API에 대해 인증하는 데 사용됩니다.

Implementation

Create an Amazon Cognito User Pool

1. AWS 관리 콘솔에서 Cognito 서비스로 이동

2. [Manae User Pools] 클릭

3. [Create a User Pool] 클릭

4. Pool name에 WildRydes을 입력하고 [Review defaults] 클릭

5. [Create pool] 클릭

6. Pool Id를 메모장에 복사

Add an App to Your User Pool

1. 왼쪽 패널 General settings 섹션 아래에 있는 App clients 선택

2. [Add an app client] 선택

3. App client name에 WildRydesWebApp을 입력하고 Generate client secret 옵션을 선택 해제

4. 웹페이지 가장 아래로 스크롤하고 [Create app client] 클릭

5. App client id를 메모장에 복사

Update the Website Config

1. Cloud9 인스턴스로 이동해서 wild-ryde-site/js/config.js 파일을 텍스트 에디터로 열기

2. UserPoolId에 이전 단계에서 생성한 Pool Id를 userPoolClientId에 이전 단계에서 생성한 App cliet id를 입력하고, region에는 ap-northeast-2를 입력하고 파일을 저장

3. 변경사항(Cognito 설정)을 CodeCommit 리포지토리에 반영

cd ~/environment/wildrydes-site
git add .
git commit -m "add cognito config"
git push

4. Amplify 콘솔로 이동해서 변경분이 배포되고 있는지 확인

Validate your implememtation

1. 사이트에 접속해서 GIDDY UP! 클릭

2. 사용할 이메일 주소와 비밀번호를 입력하고 LET'S RYDE 클릭 - 비밀번호는 8글자 이상으로 대문자 1개, 숫자 1개, 특수문자 1개가 필수

3. 이메일로 전송된 인증 코드 확인

4. 이메일 검증 페이지에서 이메일주소와 인증코드를 입력하고 VERIFY 클릭

5. 다음과 같은 팝업메시지가 나오면 이메일 검증이 정상으로 완료

6. 등록한 이메일 주소와 비밀번호를 입력하고 SIGN IN 클릭

7. 로그인이 완료되면 /ride.html 페이지로 연결이 되고 아래와 같이 메시지가 표시됨

Module 3: Serverless Service Backend

Overview

이 모듈에서는 AWS Lambda 및 Amazon DynamoDB를 사용하여 웹 애플리케이션의 비지니스 로직을 처리할 백엔드 프로세스를 구축합니다. 첫 번째 모듈에서 배포한 프론트엔드 웹 모듈을 통해서 사용자는 본인이 원하는 위치로 유니콘을 호출 할 수 있습니다. 이러한 요청을 수행하려면 브라우저에서 실행되는 JavaScript가 클라우드에서 실행되는 백엔드 서비스를 호출해야 합니다.

Architecture Overview

사용자가 유니콘을 요청할 때마다 호출되는 Lambda 함수를 구현합니다. 이 함수는 유니콘 무리중에서 하나의 유니콘을 선택하고 DynamoDB 테이블에 요청을 기록한 다음 발송되는 유니콘에 대한 세부 정보로 프론트엔드 애플리케이션에 응답합니다.

Lambda 함수는 Amazon API Gateway를 외부에 노출이 되고 브라우저에서 해당 API 엔드포인트를 호출합니다. 다음 모듈에서 프론트엔드와 백엔드의 연결을 구현하고 해당 모듈에서는 백엔드 API 구동에 대한 테스트만 진행합니다.

Implementation

Create an Amazon DynamoDB Table

1. AWS 관리 콘솔에서 Cognito 서비스로 이동

2. [Create Table] 클릭

3. Table name에 Rides을 입력하고 Partition key에는 RideId 입력하고 종류는 String으로 선택

4. Settings에 Default settings를 선택하고 [Create table] 클릭

Create a Lambda Function for Handling Requests

1. AWS 관리 콘솔에서 Lambda 서비스로 이동

2. [Create function] 클릭

3. 생성 옵션에는 Author from scratch를 선택, Function name에는 RequestUnicorn 을 입력, Runtime에는 Node.js 16.x를 선택하고 [Create function] 클릭

4. 코드에디터의 index.js에 있는 코드블록을 아래의 코드블록으로 교체하고 [Deploy] 클릭

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0

const randomBytes = require('crypto').randomBytes;

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

const ddb = new AWS.DynamoDB.DocumentClient();

const fleet = [
    {
        Name: 'Bucephalus',
        Color: 'Golden',
        Gender: 'Male',
    },
    {
        Name: 'Shadowfax',
        Color: 'White',
        Gender: 'Male',
    },
    {
        Name: 'Rocinante',
        Color: 'Yellow',
        Gender: 'Female',
    },
];

exports.handler = (event, context, callback) => {
    if (!event.requestContext.authorizer) {
      errorResponse('Authorization not configured', context.awsRequestId, callback);
      return;
    }

    const rideId = toUrlString(randomBytes(16));
    console.log('Received event (', rideId, '): ', event);

    // Because we're using a Cognito User Pools authorizer, all of the claims
    // included in the authentication token are provided in the request context.
    // This includes the username as well as other attributes.
    const username = event.requestContext.authorizer.claims['cognito:username'];

    // The body field of the event in a proxy integration is a raw string.
    // In order to extract meaningful values, we need to first parse this string
    // into an object. A more robust implementation might inspect the Content-Type
    // header first and use a different parsing strategy based on that value.
    const requestBody = JSON.parse(event.body);

    const pickupLocation = requestBody.PickupLocation;

    const unicorn = findUnicorn(pickupLocation);

    recordRide(rideId, username, unicorn).then(() => {
        // You can use the callback function to provide a return value from your Node.js
        // Lambda functions. The first parameter is used for failed invocations. The
        // second parameter specifies the result data of the invocation.

        // Because this Lambda function is called by an API Gateway proxy integration
        // the result object must use the following structure.
        callback(null, {
            statusCode: 201,
            body: JSON.stringify({
                RideId: rideId,
                Unicorn: unicorn,
                UnicornName: unicorn.Name,
                Eta: '30 seconds',
                Rider: username,
            }),
            headers: {
                'Access-Control-Allow-Origin': '*',
            },
        });
    }).catch((err) => {
        console.error(err);

        // If there is an error during processing, catch it and return
        // from the Lambda function successfully. Specify a 500 HTTP status
        // code and provide an error message in the body. This will provide a
        // more meaningful error response to the end client.
        errorResponse(err.message, context.awsRequestId, callback)
    });
};

// This is where you would implement logic to find the optimal unicorn for
// this ride (possibly invoking another Lambda function as a microservice.)
// For simplicity, we'll just pick a unicorn at random.
function findUnicorn(pickupLocation) {
    console.log('Finding unicorn for ', pickupLocation.Latitude, ', ', pickupLocation.Longitude);
    return fleet[Math.floor(Math.random() * fleet.length)];
}

function recordRide(rideId, username, unicorn) {
    return ddb.put({
        TableName: 'Rides',
        Item: {
            RideId: rideId,
            User: username,
            Unicorn: unicorn,
            UnicornName: unicorn.Name,
            RequestTime: new Date().toISOString(),
        },
    }).promise();
}

function toUrlString(buffer) {
    return buffer.toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}

function errorResponse(errorMessage, awsRequestId, callback) {
  callback(null, {
    statusCode: 500,
    body: JSON.stringify({
      Error: errorMessage,
      Reference: awsRequestId,
    }),
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  });
}

5. [Configuration] → [Permission] → Execution role 에서 RequestUnicorn-role-xxxx 를 선택

6. [Permissions] 섹션 오른쪽에 있는 [Add Permissions ] → [Attach policies] 클릭

7. 검색창에 DynamoDB를 입력하고 엔터

8. AmazonDynamoDBFullAccess를 선택하고 [Attach policies] 클릭

Validate Your Implementation

1. 람다 화면으로 돌아와서 [Code] → [Test] → [Configure test event] 선택

2. Test event action에 Create new event를 선택하고 Event name에 TestRequestEvent 를 입력

3. Event JSON에 아래의 JSON 블록을 복사해서 붙여넣고 [Save] 클릭

{
    "path": "/ride",
    "httpMethod": "POST",
    "headers": {
        "Accept": "*/*",
        "Authorization": "eyJraWQiOiJLTzRVMWZs",
        "content-type": "application/json; charset=UTF-8"
    },
    "queryStringParameters": null,
    "pathParameters": null,
    "requestContext": {
        "authorizer": {
            "claims": {
                "cognito:username": "the_username"
            }
        }
    },
    "body": "{\"PickupLocation\":{\"Latitude\":47.6174755835663,\"Longitude\":-122.28837066650185}}"
}

4. 코드 에디터에서 [Test] 클릭

5. 아래와 같은 응답이 오면 Lambda 함수가 정상적으로 동작

{
  "statusCode": 201,
  "body": "{\"RideId\":\"VlNw-rUvQJHrh6AguNOUfQ\",\"Unicorn\":{\"Name\":\"Shadowfax\",\"Color\":\"White\",\"Gender\":\"Male\"},\"UnicornName\":\"Shadowfax\",\"Eta\":\"30 seconds\",\"Rider\":\"the_username\"}",
  "headers": {
    "Access-Control-Allow-Origin": "*"
  }
}

Module 4: Deploy a RESTful API

Overview

해당 모듈에서는 Amazon API Gateway를 사용하여 이전 모듈에서 구축한 Lambda 함수를 RESTful API로 노출합니다. 이 API는 퍼블릭 인터넷을 통해서 접근이 가능하지만 이전 모듈에서 생성한 Amazon Cognito 사용자 풀을 통해서 인증 및 인가를 받은 사용자만 접근할수 있습니다. 해당 구성을 통해서 브라우저에서 실행되는 JavaScript로 API를 호출해서 정적으로 호스팅되는 웹 사이트를 동적 웹 응용 프로그램으로 전환할 수 있습니다.

Architecture Overview

위의 다이어그램은 해당 모듈에서 구축할 API Gateway 구성 요소를 이전에 구축한 기존 구성 요소와 연동하는 방법을 보여줍니다. 회색으로 표시된 항목은 이전 단계에서 이미 구현한 부분입니다.

첫 번째 모듈에서 배포한 정적 웹 사이트에는 이미 해당 모듈에서 구성할 API와 연동하기 위해서 구성된 페이지가 있습니다. /ride.html 페이지에는 유니콘 탑승 요청하기 위한 간단한 지도 기반 인터페이스가 있습니다. /signin.html 페이지를 사용하여 인증한 후 사용자는 지도의 한 지점을 클릭한 다음 오른쪽 상단 모서리에 있는 "Request Unicorn" 버튼을 클릭해서 배차를 요청하여 픽업 위치를 선택할 수 있습니다.

해당 모듈은 API의 클라우드 구성 요소를 구축하는데 필요한 단계에 중점을 둘 것이지만 해당 API를 호출하는 브라우저 코드가 작동하는 방식에 관심이 있다면 웹사이트의 ride.js 파일을 통해서 확인할 수 있습니다. 이 경우 애플리케이션은 jQuery의 ajax() 함수를 사용하여 API를 호출합니다.

Implementation

Create a New REST API

1. AWS 관리 콘솔에서 API Gateway 서비스로 이동

2. Choose an API type에서 REST API 카드에 있는 [Build] 를 클릭

3. Protocol에 REST, 생성옵션에 New API를 선택하고 API name에 WildRydes 를 입력하고 Endpoint Type에 Edge optimized를 선택하고 [Create API] 클릭

4. 생성된 API 설정화면 왼쪽 패널에서 [Authorizers] 선택하고 [+ Create New Authorizer] 클릭

5. Name에 WildRydes를 입력, Type에 Cognito를 선택, Cognito User Pool에서 지역은 ap-northeast-2로 그대로 두고 목록에서 WildRydes를 선택, Token Source에 Authorization을 입력하고 [Create] 클릭

6. 웹브라우저에서 배포한 사이트의 /ride.html 경로로 접속 - 로그인 화면이 보일 경우에는 이전 계정생성 단계에서 사용한 이메일과 비밀번호를 입력해서 로그인

7. 브라우저의 개발자 도구를 통해서 Authentication 토큰 값을 복사

8. 위에서 생성한 Authorizer 구성에서 [Test]를 클릭

9. Authorization Token에 웹페이지에서 확인한 토큰 값을 입력하고 [Test] 클릭

10. 응답코드가 200이고 Claims에 로그인한 사용자의 상세내용이 표시되면 정상

Create a new resource and method

1. API 설정화면 왼쪽 패널에서 [Resources] → [Actions] → [Create Resource] 선택

2. Resource Name에 ride를 입력하면 Resource Path에 ride가 자동으로 입력되고 Enable API Gateway CORS를 활성화하고 [Create Resource] 클릭

3. 위에서 생성한 /ride 리소스를 선택 → [Actions] → [Create Method] 선택

4. 새로운 드롭다운 목록이 활성화되면

POST를 선택하고

체크 모양의 아이콘을 클릭

5. Integration type에 Lambda Function을 선택, Use Lambda Proxy integration을 활성화, Lambda Region에 ap-northeast-2를 선택(기본값), Lambda Function에 RequestUnicorn 을 입력하고 [Save] 클릭

6. API Gateway에 Lambda 함수를 호출하는 권한 부여를 확인한는 팝업메시지가 뜨면 [OK]를 선택

7. [Method Request]를 선택

Authorization 옆에 있는 연필 모양의 아이콘을 선택

드롭다운 목록에서 WildRydes Cognito user pool authorizer를 선택

체크 모양의 아이콘을 클릭

Deploy Your API

1. [Actions] → [Deploy API] 선택

2. Deployment stage에 [New Stage]를 선택, Stage name에 prod를 입력하고 [Deploy] 클릭

3. Invoke URL을 메모장에 복사

Update the Website Config

1. Cloud9 인스턴스로 이동해서 wild-ryde-site/js/config.js 파일을 텍스트 에디터로 열기

2. invokeUrl에 이전 단계에서 생성한 API 엔드포인트를 입력하고 파일을 저장

3. 변경사항(API 엔드포인트 설정)을 CodeCommit 리포지토리에 반영

cd ~/environment/wildrydes-site
git add .
git commit -m "add backend api config"
git push

4. Amplify 콘솔로 이동해서 변경분이 배포되고 있는지 확인

Validate your implementation

1. 웹브라우저에서 배포한 사이트의 /ride.html 경로로 접속 - 로그인 화면이 보일 경우에는 이전 계정생성 단계에서 사용한 이메일과 비밀번호를 입력해서 로그인

2. 맵에서 원하는 픽업 위치를 선택하고 [Set pickup] 클릭

Wild Rydes