- 본 Hands-on lab은 AWS Seoul region 기준으로 작성되었습니다. Region을 Seoul (ap-northeast-2)로 변경 후 진행 부탁드립니다.
- AWS Credit 추가하기
- Lab 환경 구축
-
AWS Management Console 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 ssm를 검색하고 [Systems Manager] 를 선택
-
Systems Manager Dashboard 왼쪽 패널 Instances & Nodes 섹션 아래에 있는 [Session Manager] 선택
-
[Start Session] → Instance Name: react-app 선택 → [Start Session] 클릭
-
Root 환경으로 전환
sudo -i
-
Node.js App 설정 파일 열기
vi /home/ec2-user/react-ecommerce-node/config.js
-
DB_URL = <RDS_ENDPOINT> 로 변경 (RDS Console에서 확인 가능)
module.exports = { DB_URL: 'react-mysql.xxxxxxxx.ap-northeast-2.rds.amazonaws.com' };
-
Node.js 서버 시작
forever start /home/ec2-user/react-ecommerce-node/app.js
-
React App 설정 파일 열기
vi /home/ec2-user/react-ecommerce/src/config/config.js
-
API_SERVER =
http://<EC2_PUBLIC_IP>:5000
로 변경 (EC2 Console에서 확인 가능)const API_SERVER = 'http://123.123.123.123:5000'
-
React 빌드 생성
cd /home/ec2-user/react-ecommerce && yarn build
-
React 서버 시작
cd /home/ec2-user/react-ecommerce && /usr/local/bin/serve -s build --listen 80
-
- 이벤트에 대한 응답으로 코드를 실행하고 자동으로 기본 컴퓨팅 리소스를 관리하는 서버리스 컴퓨팅
- Java, Python, Node.js, C#, Go, Ruby
- 완전 관리형 서비스 (서버와 운영체제 유지 관리, Capacity Provisioning & Autoscaling, 로깅 및 모니터링, 보안패치 및 코드배포 등등)
- Event-driven compute: CloudWatch, S3, DynamoDB, SNS, etc
- HTTP request handler: API Gateway, Application Load Balancer
- API를 생성, 게시, 유지관리 및 모니터링 할수있는 완전관리형 서비스
- REST 및 WebSocket API 지원
- Integrated with IAM, Cognito, CloudFront, etc
- NoSQL Database
- Single-digit millisecond performance at any scale
- Support in-memory cache, global replication, point-in-time recovery
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 DynamoDB를 검색하거나 [Database] 밑에 있는 [DynamoDB] 를 선택
-
DynamoDB Dashboard에서 [Create table] 클릭후, Table name = event, Primary key = email, Use default settings = ✅, [Create] 클릭
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 SES를 검색하거나 [Customer Engagement] 밑에 있는 [Simple Email Service] 를 선택 → Asia Pacific (Sydney) 선택
-
SES Dashboard 왼쪽 패널에서 Email Addresses 를 선택 → [Verify a New Email Address] → 본인의 이메일 주소 입력 후 [Verify This Email Address] 클릭
-
메일박스에서 Amazon Web Services – Email Address Verification Request in region Asia Pacific (Sydney) 이메일 확인후 인증 링크 클릭
-
SES Console에서 인증받은 이메일의 Verification Status가 verified로 변경되었는지 확인
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 Lambda를 검색하거나 [Compute] 밑에 있는 [Lambda를] 를 선택
-
Lambda Dashboard에서 [Create function] 클릭후, Function name = event_handler, Runtime = Node.js 12.x, [Create function] 클릭
-
좌측 하단에 있는 [Execution role] 에서 View the event_handler-role-xxxx on the IAM console 를 선택
-
[Add inline policy] 선택 후,
Service = DynamoDB,
Actions = PutItem,
Resources = ✅ Specific → [Add ARN],
Region = ap-northeast-2, Table name = event → [Add],
[Add additional permissions] 클릭,
Service = X-ray,
Actions = ✅ Write,
Resources = ✅ All resources;
[Add additional permissions] 클릭,
Service = SES,
Actions = SendEmail,
Resources = ✅ All resources;
[Review policy] 클릭,
Name = event_handler,
[Create policy] 클릭\ -
Lambda Console로 돌아와서 우측 하단에 있는 [AWS X-Ray] 에서 ✅ Active tracing Specific → [Save] 클릭
-
아래 코드블록을 Lambda에 복사 후, [Save] 클릭
var AWS = require('aws-sdk') exports.handler = function(event, context, callback) { var dynamodb = new AWS.DynamoDB() var dynamodbParams = { Item: { 'email': { S: event.email }, 'name': { S: event.name }, 'mobile': { S: event.mobile } }, TableName: 'event' } dynamodb.putItem(dynamodbParams, function(err, data) { if (err) { console.log(err, err.stack) } else { var ses = new AWS.SES({region: 'ap-southeast-2'}) var sesParams = { Destination: { ToAddresses: [event['email']], }, Message: { Body: { Text: { Charset: 'UTF-8', Data: 'Registered', }, }, Subject: { Charset: 'UTF-8', Data: 'Thank you', }, }, Source: event['email'], } ses.sendEmail(sesParams, function(err, data) { if (err) { console.log(err, err.stack) } else { console.log(data) } }) } }) const response = { statusCode: 200, body: JSON.stringify('OK'), } callback(null, response) }
-
Lambda Console로 돌아가서 [Designer] 섹션에 있는 + Add trigger 클릭 → Dropdown 리스트에서 API Gateway 선택 → API = Create a new API, Security = Open → [Add] 클릭
-
Lambda Console의 [API Gateway] 섹션에서 event_handler-API 클릭
-
/event_handler 선택 → Actions → Create Method → POST 선택 → ✅ → Integration type = Lambda Function, Lambda Region = ap-northeast-2, Lambda Function = event_handler → [Save] 클릭
-
/event_handler 밑에 POST 선택 → Actions → Enable CORS → [Enable CORS and replace existing CORS headers] 클릭 → [Yes, replace existing values] 클릭
-
/event_handler 선택 → Actions → Deploy API → Deployment stage = default → [Deploy] 클릭
-
Stages → Default → /event_handler → POST → **[Invoke_URL]**를 클립보드에 복사
-
Session Manager를 통해서 EC2 인스턴스에 접속후,
-
React App 설정 파일 열기
vi /home/ec2-user/react-ecommerce/src/config/config.js
-
EVENT_REGISTER: <API_GATEWAY_INVOKE_URL>로 변경
EVENT_REGISTER: `https://xxxxx.execute-api.ap-northeast-2.amazonaws.com/default/event_handler`
-
React 빌드 생성
cd /home/ec2-user/react-ecommerce && yarn build
-
React 서버 시작
cd /home/ec2-user/react-ecommerce && /usr/local/bin/serve -s build --listen 80
-
-
웹사이트에 접속후 Event 페이지로 이동 후 폼 작성 및 제출 → DynamoDB 테이블에 Record 추가 됐는지 확인 & 이벤트 접수 메일 왔는지 확인
-
Lambda Dashboard에서 Layers 클릭 → [Create layer] → Name = nodejs-xray-sdk, 🔘 Upload a file from Amazon S3, Amazon S3 link URL =
https://saltware-aws-lab.s3.ap-northeast-2.amazonaws.com/msa/node-xray-sdk.zip
Compatible runtimes = Node.js 10.x, Node.js 12.x → [Create]-
Layer 파일 생성 방법
mkdir nodejs cd nodejs npm install aws-xray-sdk zip node-xray-sdk.zip ../nodejs -r
-
-
위에서 생성한 Lambda function으로 가서 Layers 선택 → [Add a layer] → Name = nodejs-xray-sdk, Version =1 → [Add] → Lambda function 저장
-
Lambda 소스 코드를 아래와 같이 수정하고 [Save]
var AWSXRay = require('aws-xray-sdk'); var AWS = AWSXRay.captureAWS(require('aws-sdk')); exports.handler = function(event, context, callback) { ... ...
-
웹사이트에 접속후 Event 페이지로 이동 후 폼 작성 및 제출
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 X-Ray를 검색하거나 [Developer Tools] 밑에 있는 [X-Ray] 를 선택
-
X-Ray Dashboard 에서 [Service Map] 선택후 서비스 Components 구성 확인
-
[Traces] → Trace list에서 Trace를 선택하고 Segment별 실행시간 확인
- HTML, CSS, Javascript 및 기타 정적(Image, text) 파일로 구성된 정적 사이트 호스팅
- Route53와 연계해서 Custom Domain으로 연결 가능
- Highly available & scalable Serverless Frontend 구성
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 S3를 검색하거나 [Storage] 바로 밑에 있는 [S3] 를 선택
-
S3 Dashboard에서 [Create bucket] 클릭후, Bucket name = [임의의 문자 및 숫자].saltware.io, Region = Asia Pacific (Seoul), [Create] 클릭
-
해당 Bucket 클릭 → [Properties] → [Static website hosting] → ✅ Use this bucket to host a website, Index document = index.html, Error document = index.html → [Save]
-
해당 Bucket 클릭 → [Permissions] → [Block public access] → [Edit] → uncheck Block all public access → [Save]
-
[Permissions] → [Bucket Policy] → 아래 Policy 블록을 Bucket policy editor에 붙여놓고 [Save]
{ "Version":"2012-10-17", "Statement":[ { "Sid":"AddPerm", "Effect":"Allow", "Principal": "*", "Action":["s3:GetObject"], "Resource":["arn:aws:s3:::<BUCKET_NAME>/*"] } ] }
- React 소스코드를 Github에 호스팅
- AWS CodePipeline을 이용해서 코드 변경시 배포 자동화 구성
- AWS Cloud9을 이용해서 개발환경 구성
-
해당 Git Repository를 Fork (GitHub 계정 필수)
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 CodePipeline를 검색하거나 [Developer Tools] 밑에 있는 [CodePipeline] 를 선택
-
[Create pipeline] → Pipeline name = msa-frontend, Service role = New service role → [Next] → Source provider = GitHub → [Connect to GitHub] → Repository = Step 1에서 Forking한 Repository, Branch = master → [Next] → Build provider = AWS CodeBuild → [Create project]
-
Project name = msa-frontend, Environment image = Managed Image, Operating system = Ubuntu, Runtime(s) = Standard, Image = aws/codebuild/standard:2.0, Service role = New service role, Build specifications = Insert build commands → [Switch to editor] → 아래 커맨드블록을 Build commands에 붙여놓고 [Continue to CodePipeline]
version: 0.2 phases: install: runtime-versions: nodejs: 10 commands: # Yarn installation - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - - echo "deb http://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list - apt-get -y update - apt-get install -y yarn # Installing react and serverless dependencies - yarn install build: commands: - yarn run build artifacts: files: - '**/*' base-directory: 'build'
-
[Next] → Deploy provider = AWS S3, Bucket = 바로 전에 생성한 S3 Bucket, ✅ Extract file before deploy → [Next] → [Create pipeline]
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 Cloud9를 검색하거나 [Developer Tools] 밑에 있는 [Cloud9] 를 선택 → Asia Pacific (Tokyo) 선택
-
[Create environment] → Name = dev → [Next step] → Environment type = ✅ Create a new instance for environment (EC2), Instance type = t2.micro (1 GiB RAM + 1 vCPU), Platform = Amazon Linux → [Next step] → [Create environment]
-
Forking한 Repository를 Cloud9으로 환경으로 Clone
git clone http://<REPOSITORY_URL>
-
React App 설정파일 수정 (API_SERVER, EVENT_REGISTER)
-
수정한 코드를 Commit & Push
git add . git commit -m "add API endpoints to config" git push
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 AppSync를 검색하거나 [Mobile] 밑에 있는 **[AWS AppSync]**를 선택
-
[Create API] → Import DynamoDB Table → [Start] → Table name = event, Create or use an existing role = ✅ New role → [Import]
-
Model Name = Event → [Add field], Name = name, Type = String, Required = ✅ → [Add field], Name = mobile, Type = String, Required = ✅ → [Create] → API Name = Event → [Create]
-
src/index.js 파일을 열고 AppSync Endpoint 정보를 입력, 관련정보는 **[Settings]**에서 확인
const client = new AWSAppSyncClient({ url: 'https://xxxxx.appsync-api.ap-northeast-2.amazonaws.com/graphql', region: 'ap-northeast-2', auth: { type: 'API_KEY', apiKey: 'xxxxxxxxxxxxxxxxxx', } })
-
src/components/event/event.component.jsx 파일을 열고 아래와 같이 35줄을 주석처리하고 36줄의 주석처리를 해제
// await events.register(name, email, mobile); this.props.onAdd(input);
-
수정한 코드를 Commit & Push
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 Lambda를 검색하거나 [Compute] 밑에 있는 [Lambda] 를 선택
-
Lambda Dashboard에서 [Create function] 클릭후, Function name = send_email, Runtime = Python 3.7, [Create function] 클릭
-
좌측 하단에 있는 [Execution role] 에서 View the send_email-role-xxxx on the IAM console 를 선택
-
[Attach policies] → DynamoDB 검색 → ✅ AWSLambdaInvocation-DynamoDB 선택 → [Attach policy]
-
Inline policy를 이용해서 해당 IAM Role에 SES SendEmail 권한 부여
-
아래 코드블록을 Lambda에 복사 후, [Save] 클릭
import json import boto3 def lambda_handler(event, context): #print("Received event: " + json.dumps(event, indent=2)) for record in event['Records']: if (record['eventName'] == 'INSERT'): email = record['dynamodb']['Keys']['email']['S'] client = boto3.client('ses', region_name='ap-southeast-2') sesResponse = client.send_email( Destination={ 'ToAddresses': [email], }, Message={ 'Body': { 'Text': { 'Charset': 'UTF-8', 'Data': 'Registered', }, }, 'Subject': { 'Charset': 'UTF-8', 'Data': 'Thank you', }, }, Source=email, ) print (sesResponse) print ("email sent") return 'OK'
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 DynamoDB를 검색하거나 [Database] 밑에 있는 [DynamoDB] 를 선택
-
DynamoDB Console에서 [Tables] → event 선택
-
Overview 탭 아래에 있는 Stream details 에서 [Manage Stream] 클릭 → ✅ New image → [Enable]
-
Trigger 탭 선택 → [Create trigger] → [Existing Lambda function] → Function = send_mail, Batch size = 1, Enable trigger = ✅ → [Create]
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 Cognito를 검색하거나 [Security, Identity, & Compliance] 밑에 있는 [Cognito] 를 선택
-
[Manage User Pools] → [Create a user pool] → Pool name = msa-app → [Review defaults]
-
[Choose username attributes..] → ✅ Email address or phone number → ✅ Allow email addresses → 왼쪽 패널에서 Review 선택 → [Create pool]
-
왼쪽 패널에서 App clients 선택 → [Add an app client] → App client name = msa-app, Generate client secret = 체크해제 → [Create app client]
-
좌측 상단에 있는 Federated Identities 선택 → Identity pool name = msa app → Authentication providers 탭 펼치기 → Cognito 탭 아래 User Pool ID , App client id 입력 → [Create Pool] → [Allow]
-
Cloud9에서 src/config/cognito.js 파일을 열고 Cognito Endpoint 정보를 입력,
export default { cognito: { REGION: "ap-northeast-2", USER_POOL_ID: "ap-northeast-2_xxxxx", APP_CLIENT_ID: "xxxxxxx", IDENTITY_POOL_ID: "ap-northeast-2:xxxx-xxxx-xxxxxxx" } };
-
Cloud9에서 src/components/sign-up/sign-up.component.jsx 파일을 열고 아래와 같이 38-54줄을 주석처리를 해제하고, 58줄 주석처리, 60줄 주석처리 해제
if(showVerification == false) { const currentUser = await Auth.signUp({ username: email, password: password }); this.setState({ displayName: displayName, email: email, password: password, confirmPassword: confirmPassword, verificationCode: verificationCode, showVerification: true }); return; } try { // const currentUser = await user.register(email, password); // console.log(verificationCode); const currentUser = await Auth.confirmSignUp(email, verificationCode)
-
수정한 코드를 Commit & Push
-
웹사이트에 접속 후, 신규 계정 생성 및 로그인 테스트 (Verification Code는 가입 이메일로 발송)
-
Cognito User Pool에 신규 유저가 생성됬는지 확인
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 ECR를 검색하거나 [Compute] 밑에 있는 [ECR] 를 선택
-
[Get Started] → Repository name = msa-node → [Create repository]
-
Cloud9 에서 Node.js backend repository 복제
cd ~/environment && git clone https://github.com/woowhoo/react-ecommerce-node.git
-
Cloud9에서 react-ecommerce-node/config.js 파일을 열고 DB_URL = <RDS_ENDPOINT> 로 변경 (RDS Console에서 확인 가능)
module.exports = { DB_URL: 'react-mysql.xxxxxxxx.ap-northeast-2.rds.amazonaws.com' };
-
복제한 Repository 루트 디렉토리에 Dockerfile 파일 생성후 아래 내용 복사
FROM node:10 # Create app directory WORKDIR /usr/src/app # Bundle app source COPY . . EXPOSE 5000 CMD [ "node", "app.js" ]
-
ECR Dashboard 에서 위에서 만든 Repository 선택 → 우측 상단에 있는 [View push commands] 클릭
-
Cloud9에서 복제한 Repository 루트 디렉토리로 이동후 위의 커맨드를 순서대로 실행
-
ECR Dashboard를 refresh하고 Docker 이미지가 추가 됬는지 확인
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 ECS를 검색하거나 [Compute] 밑에 있는 [ECS] 를 선택
-
좌측 패널에서 Task Definitions 클릭 → [Create new Task Definition] → FARGATE 선택 후 [Next step] → Take Definition Name = msa-node, Task memory (GB) = 1GB, Task CPU (vCPU) = 0.5 vCPU
-
[Add container] → Container name = msa-node, Image = <Image_URI> ECR에서 확인, Port mappings = 5000, → [Add] → [Create] → [View task definition]
-
좌측 패널에서 Clusters 클릭 → [Create Cluster] → Networking only 선택 후 [Next step] → Cluster Name = msa-node → [Create] → [View Cluster]
-
Services 탭 아래 [Create] 클릭 → Launch type = ✅ FARGATE, Task Definition = Family: msa-node | Revision: 1(latest), Service name = msa-node, Number of tasks = 1, [Next step]
-
Cluster VPC = msa-vpc(10.1.0.0/16), Subnets = 전부 선택, Security groups = [Edit] → ✅ Select existing security group, ✅ ec2-sg → [Save]
-
나머지 옵션들은 다 기본값으로 두고 [Next step]
-
Service Auto Scaling = Do not adjust the service’s desired count → [Next step] → [Create Service] → [View Service]
-
Last status가 RUNNING 인지 확인
-
Task ID 클릭 → Public IP를 클립보드에 복사
-
Cloud9 에서 React App 설정파일 수정 (API_SERVER)
const API_SERVER = 'http://<Public_IP>:5000'
-
수정한 코드를 Commit & Push
-
EC2 인스턴스를 정지하고 앱이 정상적으로 작동하는지 확인
- ECS - Cluster, Task Definition, ECR Repository
- Cognito - Domain, User Pool, Identity Pool
- Lambda - event_handler, send_mail
- AppSync
- DynamoDB
- Cloud9 - Tokyo Region
- CodePipeline
- CodeBuild
- GitHub Repository
- S3 Bucket
- API Gateway
- SES - Email Address (Sydney Region)
- IAM Role - appsync, AWSCodePipeline, codebuild, Cognito, event_handler, send_mail
- CloudWatch logs - codebuild, lambda, ecs
- CloudFormation Stack - msa-lab