SK shieldus Rookies 16기 (클라우드 보안 기술 #06)

만두다섯개·2023년 12월 7일
0

SK 루키즈 16기

목록 보기
28/52

주요 정보

  • 교육 과정명 : 클라우드기반 스마트융합보안 과정 16기
  • 교육 회차 정보 : '23. 12. 07. 클라우드 보안 기술 #06

학습 내용 요약

(#이전회차) 웹 애플리케이션 환경 AWS 리소스로 구성

  • Flask 앱과 MySQL 사용방법(스키마 생성, 조회)
  • AWS EC2, RDS, MySQL 연동
  • React 앱 사용(웹 서버 실행 기초)
  • React 와 Flask 앱 사용, 그리고 CORS 오류
  • AWS 리소스(EC2, RDS)에 React, Flask 앱 구성
  • AWS 리소스(EC2, RDS, S3)에 React, Flask 앱 구성
  • AWS 리소스(EC2, RDS, S3)에 React, Flask 앱 구성
  1. AWS 리소스로 서버리스 웹 애플리케이션 구현
  • 서버리스 아키텍처 개요 및 특징
  • Lambda 함수 실습 3종(런타임 2종, S3 버킷을 사용해 썸네일 이미지 저장)
  • AWS 서버리스 웹 애플리케이션 구현
  • AWS 리소스 정리

1. 서버리스 아키텍처

1-1. 서버리스 아키텍처 개요

  • 로직 처리는 자바스크립트와 같은 스크립트로 처리한다.
  • 사용자가 웹 클라이언트에 접속하면, 웹 서버가 DB로부터 데이터를 가져와 사용자에게 제공한다.

1-2. AWS 서버리스

  • 표현 계층에서의 요청을 API Gateway, DB를 통해 lambda 함수를 호출하고, 람다 함수는 로직을 처리해 사용자에게 서비스를 제공한다.
  • 링크 : https://aws.amazon.com/ko/serverless/

    서버리스 기술은 자동 크기 조정, 기본 제공 고가용성 및 종량제 결제 모델을 제공하여 민첩성을 개선하고 비용을 최적화합니다. 또한 이러한 기술을 사용하면 용량 프로비저닝 및 패치 적용과 같은 인프라 관리 작업이 필요하지 않으므로 고객을 위한 코드를 작성하는 데 집중할 수 있습니다.

  • AWS Lambda란? AWS 제공하는 서버리스 컴퓨팅 FaaS 상품이다.
  • FaaS는 Function as a Server의 약자로 말 그대로 "함수를 서비스로 제공한다"라는 의미
  • 서버에 대한 고민 없이 앱 구축 및 실행 가능
  • 서버리스 아키텍처 도입의 장점 : 비용 절감, 대규모 조정, 간편하게 앱 구축

1-3. 서버리스 아키텍처의 원칙

  1. 컴퓨팅 서비스를 사용해 요구에 맞게 코드를 실행한다. (물리적 서버 없이)
  2. 단일 목적의 상태 없는 함수를 작성한다. (HTTP 요청 등)
  3. 푸시 기반, 이벤트 주도 파이프 라인을 설계한다.
  4. 강한 프론트엔드를 만들어야 한다. (H/W의 성능 발달, 등이 서버리스 아키텍처 출현의 한 요인이다.⇒ React, Angular, Vue, ... : 자바스크립트 프레임워크 들)
  5. 서드 파티 서비스를 받아들여야 한다. => 소셜 로그인

  • 사용자는 비디오를 업로드한다.
  • 사용자가 업로드하는 비디오 파일 형식이 각자 다르다.
  • 개발자는 개별 기능을 구현한다(서비리스 방식) -> 비디오 확장자에 따른 저장 방식 구현 등..
  • 위의 그림은 push-based 파이프라인 스타일 흐름도 이다. 이렇게 push-based 파이프라인 스티일 작동방식은 서버리스 아키텍처에서 잘 작동한다.

AWS Lambda란?

  • 서버를 프로비저닝, 서버 관리하지 않고도 코드를 실행할 수 있는 이벤트 기반 종량제 컴퓨팅 서비스

2. AWS Lambda 실습

2-1. AWS Lambda 실습_1 (Node.js 런타임)

  • Node.js 런타임을 사용하는 람다 함수를 생성해보자

  • AWS Lambda - 함수 생성 - 새로 작성

  • 아래와 같이 작성하고, 함수를 생성한다.

  • 생성한 람다 함수를 확인해보자

  • 코드 - index.mjs 에 람다 함수의 소스 코드를 확인할 수 있다.

1. 람다 함수 테스트

  • 람다 함수를 테스트해보자. 아래 절차대로 따라가면 된다.
  1. 람다 코드 수정 후 Depoly 버튼을 눌러 배포한다.
export const handler = async (event) => {
  console.log(event)
  // TODO implement
  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello from Lambda!'),
  };
  return response;
};
  1. 람다 함수 테스트
  • 배포된 람다 함수를 테스트하기 위해 Test 버튼의 오른쪽 옵션을 누른다.

  • Configure test event 를 선택한다.
  • 아래 그림처럼 테스트 이벤트 구성 창이 나온다.
  • 이벤트를 구성해보자.

  • 템플릿은 람다 함수에서 사용하는 서비스들의 자원의 이름을 알려준다. Hello world 로 설정한 후에 저장하자.

  • 생성된 테스트 이벤트가 체크된 것을 확인하고 Test 버튼을 누르자.

  1. 테스트 결과 확인
  • 코드에 새로운 탭이 생겼다. 내용을 확인하면 아래와 같다.
  1. Test Event Name : 테스트 이름
  2. Response : 람다 함수 응답 결과
  3. Function Logs : 람다 함수 실행 로그(시작 시간, 함수 실행 과정 중 출력 내용, 종료 시간, 실행 사용 리소스 요약)
  4. Request ID : 람다 함수 실행 식별자
  • 람다 함수는 CloudWatch에서도 결과를 확인 가능하다.

  • 만약 외부에서 람다 함수가 실행된다면 사용자는 이를 CloudWatch 콘솔에서 결과를 확인해야 한다.

  • 코드 - 모니터링 - CloudWatch Logs 보기에서 확인해보자

  • 람다 함수에 대한 3번의 테스트 로그가 남아있다.

2-2. AWS Lambda 실습_2 (파이썬 런타임)

  • 파이썬 런타임을 사용하는 람다 함수를 생성해보자
import json

def lambda_handler(event, context):
    # TODO implement
    print("홀리몰리과카몰리로보카폴리모노폴리")
    print("이 모든것은 제프 베이조스가 세상을 지배하기 위해 만든 매트리스 세계이다 ")
    print(event)
    print(context)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
  • 코드를 수정했으면, DEPOLY 후 아래와 같이 테스트 이벤트를 구성 후 저장한다

  • 테스트 버튼을 눌러 테스트하고, 결과를 확인해보자.

  • event , context 결과를 알 수 있다.

람다 함수 기초

  1. 핸들러 함수
  • 람다 함수의 시작점이다.

  • 위에서 생성한 두 람다함수의 코드 소스를 확인해보자.

  • 함수 생성 시, 지정한 런타임에 따라 소스코드 작성 언어를 선택한다.

2-3. AWS Lambda 실습_3 (S3 버킷을 사용해 썸네일 이미지 저장)

  • 이미지 썸네일을 자동으로 생성하는 람다 함수를 작성해보자.
  • 썸네일 생성 : 파이썬 PIL 모둘 사용. 이미지 프로세싱 모듈이다. 모듈은 실행 환경에 맞추어 컴파일 필요하다.
  • 람다 함수에서 어떻게 썸네일 생성 내용을 전달하는지 확인해보자.

2-3.1 썸네일 생성 람다함수

  • 람다 함수를 생성하자.

  • 파이썬 언어를 사용한다.

  • 람다 함수의 역할을 정의해보자.

  1. S3 버킷에 파일(객체)가 추가 될 때 발생 이벤트를 확인해 썸네일을 만든다.
  2. 생성한 썸네일을 썸네일 S3 버킷에 저장한다.
  • 람다 함수의 역할에서 S3 버킷으로 데이터를 저장해야 한다.
  • 테스트 이벤트 템플릿 중, s3-put 을 활용하자.
  • 테스트 이벤트 구성 시, 템플릿을 s3-put 으로 지정해 생성한다
  • s3-put 템플릿은 아래와 같다. 해당 템플릿으로부터 S3 버킷에 저장 시 람다 함수에서 사용할 값을 참조한다.
{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "us-east-1",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "EXAMPLE"
      },
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "EXAMPLE123456789",
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": {
          "name": "example-bucket",				⇐ 버킷 이름
          "ownerIdentity": {
            "principalId": "EXAMPLE"
          },
          "arn": "arn:aws:s3:::example-bucket"
        },
        "object": {
          "key": "test%2Fkey",파일(객체) 이름
          "size": 1024,
          "eTag": "0123456789abcdef0123456789abcdef",
          "sequencer": "0A1B2C3D4E5F678901"
        }
      }
    }
  ]
}
  • 소스코드를 작성(at VS Code)
import boto3 # 파이썬에서 Amazon Web Services(AWS)를 사용하기 위한 공식 SDK(소프트웨어 개발 키트)
import os
import sys, uuid ## 난수 생성모듈 / Universally Unique Identifier의 약자로, 고유 식별자를 생성하는 데 사용되는 모듈
from urllib.parse import unquote_plus
from PIL import Image
import PIL.Image

# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html
s3_client = boto3.client('s3') # S3 객체를 가져온다

def resize_image(image_path, resized_path):
    with Image.open(image_path) as image:
        image.thumbnail(tuple(n/2 for n in image.size))
        image.save(resized_path)

def lambda_handler(event, context):
    for record in event['Records']: # 람다 함수 테스트 시 사용하는 템플릿의 요소를 가져온다. 해당 템플릿의 이벤트 JSON  중 Records 를 가져온다
        bucket = record['s3']['bucket']['name']
        key = record['s3']['object']['key'] # test%2Fkey : test/key 값을 URL 인코딩 한 값
        tmpkey = key.replace('/', '') # path/file 형식을 pathfile 형식으로 변경한다.

        # S3 버킷으로부터 파일을 가져와 저장할 경로와 / 썸네일 이미지를 저장할 경로를 지정한다. 
        download_path = '/tmp/{}{}'.format(uuid.uuid1(),tmpkey) # /tmp/uuidpathfile
        upload_path = '/tmp/resized-{}'.format(tmpkey)

        #S3 버킷으로부터 파일을 다운로드
         # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3/client/download_file.html
        s3_client.download_file(bucket, key, download_path)

        # 다운로드한 파일의 크기를 반으로 축소한다 
        resize_image(download_path, upload_path)

        # 썸네일 이미지를 S3 버킷에 업로드
        # 다운로드버킷이름-resized 이름의 버킷에 원본 파일명과 동일한 파일명으로 업로드
         # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3/client/upload_file.html
        s3_client.upload_file(upload_path, '{}-resized'.format(bucket), key)
    
    
  • 소스코드를 람다함수 소스코드에 옮기고, 테스트한다. (테스트 이벤트 구성 - s3-put 템플릿 사용)

  • 람다 함수 실행 시, 소스코드에서 사용하는 PIL 모듈이 존재하지 않아 오류가 발생한다.
    ⇒ 파이썬 기본 라이브러리와 AWS SDK(여기에서는 boto3)를 제외한 외부 라이브러리는 직접 추가해 줘야 함

    => AWS 에서 PIL 모듈을 지원하지 안 하는걸까? 이걸 어떻게 해결할 수 있을까? 찾아보니 람다 함수 파일에 PIL(파이썬 이미지 라이브러리)를 재구현한 Pillow 모듈을 사용한다. 그러나 이 방식은 Pillow 모듈의 함수 사용을 소스코드에 적용해야 하고, 다른 모듈과의 의존성이 존재할 수 있지 않을까? => 람다 함수 런타임 버전과 사용 모듈 버전 호환 체크로 해결.

  • 따라서 람다 실행환경과 동일한 환경에서 PIL 모듈을 빌드 후 람다 계층(레이어)로 등록한다.

Lambda 함수의 계층

  • 람다 함수에서 외부 라이브러리를 사용하기 위해서 람다 함수의 계층에 등록이 필요하다.
  • 등록 방식은 아래와 같다.
1. PIL 빌드를 생성한다.
2. PIL 빌드를 람다 함수 레이어에 추가한다.
  • PIL 모듈이 들어있는 파일의 압축폴더를 확인 가능하다.

3. 람다 계층에 PIL 라이브러리 등록
  • S3에 업로드한 라이브러리를 람다 계층에 등록한다.

  • Lambda 좌측 리스트에서 계층을 생성한다.
  • S3 버킷의 객체 URL 복사 및 호환 런타임 : 파이썬 3.9 으로 설정한다.
  • 생성한 람다 함수 - 계층 - Add a layer
  • 사용자 지정 계층을 선택하고, 이전에 생성한 람다 계층을 가져온다.

생성한 람다 함수 Depoly 및 Test

  • 생성한 람다 함수 Depoly 및 Test를 실행한다.

  • FORBIIDEN 오류가 발생한다. 람다 실행에 있어 권한이 필요하다.

  • S3 버킷에서 파일을 가져올 때 권한이 없어서 오류가 발생한다.

  • 람다 함수 역할에 S3 버킷을 읽고 쓰는 권한을 추가한다.

  • 생성한 람다로 들어간 후 구성 - 역할 이름으로 들어간다.

  • S3 FULL Access 를 주어준다

  • 이제 해당 람다 함수에는 권한 정책이 추가되었다.

  • 테스트를 위해 람다 레이어 버킷에 이미지를 하나 등록한다.

  • S3 버킷에 파일을 추가 후, 버킷 이름과 객체 이름(키)를 변경한다.

  • 그리고 새로운 테스트 이벤트를 생성해 Depoly 및 테스트한다.

  • 이번에는 파일 업로드 실패 오류가 발생했다.

  • 썸네일을 저장할 S3 버킷이 존재하지 않아 발생하는 오류이다.

  • 썸네일을 저장할 버킷을 생성한다.
  • S3 버킷 이름 : lambda-layer-bucket-015-resized (위 에러코드에서 나온 버킷 이름을 기재한다)
  • 다시 TEST 를 실행하고 결과를 확인해보자

  • 이상없이 결과가 나왔다.

  • 썸네일을 저장한 S3도 확인해보자

  • 원본 이미지와 썸네일의 크기가 약간 변경되어 저장된 것을 확인할 수 있다.

2-3.2 트리거 추가

  • 업로드 버킷에 파일이 추가되면, 람다 함수가 호출되도럭 트리거를 추가하자

  • S3 버킷에 대해 발생하는 모든 객체 발생 시(트리거 조건) 해당 람다 함수를 실행하겠다.

  • 아래의 확인문은 트리거로 인해 발생하는 재귀적 호출에 대해 인지하고 있겠다는 의미( 무한반복으로 인해 발생한 내용은 트리거 생성자의 책임)

  • 이제 생성한 트리거를 확인해보자

  • 새로 이미지를 S3 버킷(lambda-layer-bucket-015)에 올려보자

  • 이제 썸네일이 저장되는 버킷(lambda-layer-bucket-015-resized) 에서 확인해보자.

  • 썸네일이 저장되었고, 크기가 조금 줄어든 것을 확인 가능하다.

  • 이렇게 작동하는 것을 확인하기 위해 CloudWatch로 확인해보자.

  • 로그 스트림에 해당 로그를 확인 가능하다.

2-3.3 리소스 정리

  • 버킷 삭제 (lambda-layer-bucket-015, lambda-layer-bucket-015-resized)
  • 람다 함수 삭제 , 람다 계층 삭제
  • EC2 삭제
  • CloudWatch 로그 그룹 삭제 (발생한 모든 로그)
  • IAM - 생성한 역할 그룹 삭제

3. AWS 서버리스 웹 애플리케이션 구현

  • 저번 시간에 웹 앱구조가 아래 사진처럼 존재한다.

  • End-User가 S3 버킷의 주소로 접근하면 아래 단계를 거친다.
  1. End-User가 S3 버킷에 접근
  2. S3 버킷은 End-User의 브라우저에서 EC2로의 데이터를 요청한다.
  3. EC2는 RDS로부터 데이터를 가져와 다시 End-User 브라우저에 전달한다.
  • 그러나, 개발자가 아닌 사용자는 베스천 호스트로 직접 접근(요청)할 필요가 없다.
  • 만약 이를 서버리스 아키텍처를 사용해 사용자가 베스천 호스트로 요청을 직접 보내고 받지 않게 할 수 있다.

  • 백엔드 API 기능을 람다 함수와 API Gateway로 구성해보자.

3-1. VPC, IGW, 서브넷, RDS 구현

  • 이전회차 AWS 리소스(EC2, RDS, S3)사용한다. (서브넷, IGW 포함)
  • EC2(베스천 호스트), RDS 인스턴스를 재실행한다.

3-2. Lambda 함수 생성

  • Flask 코드 함수인 empist()를 람다 함수를 사용해 구현하려고 한다.

3-2-1. PIL 모듈 람다 레이어 추가

로컬 개발환경(PC)에서 람다함수를 정의

  • CMD 창에서 설치된 파이썬 버전 : Python 3.12.0
  • aws 디렉터리에서 hello-lambda 디렉터리 생성 및 pymysql 다운로드
C:\aws> mkdir hello-lambda

C:\aws> cd hello-lambda

C:\aws\hello-lambda> pip install pymysql --target .
  • 설치가 완료되면 해당 위치에서 VS Code 를 실행시킨다
C:\aws\hello-lambda>code .
  • 파이썬 파일 생성 : lambda_function.py
import pymysql


def lambda_handler(event):     
    ret = []
    db = pymysql.connect(host='연결하고자하는RDS엔드포인트주소', user='root', db='sampledb', password='password', charset='utf8')
    curs = db.cursor()
    
    sql = "select * from emp"
    curs.execute(sql)
    
    rows = curs.fetchall()
    for e in rows:
        temp = {'empno':e[0],'name':e[1],'department':e[2],'phone':e[3] }
        ret.append(temp)
    
    db.commit()
    db.close()
    return ret
  • 람다 함수를 정의했다.
  • 해당 파일을 저장하고, 해당 파일을 압축한다.

    tar -acf ..\lambda_function.zip .

    1. 압축 대상 파일 위치 : 현재 경로의 상위 경로에 lambda_function.zip 이름으로 압축 파일 생성
    2. 압축 대상 : 현재 경로의 모든 것( . )을 압축
 tar -acf ..\lambda_function.zip .
  • 압축한 파일로 AWS 웹 콘솔에서 람다 함수를 생성한다
  • 람다 함수 이름 : LambdaFunctionWithRDS-015

  • 소스 코드 - 파일 업로드에서 생성한 zip 파일을 다시 업로드 한다.

  • 해당 함수를 아래와 같이 테스트해보자 (hello world 템플릿 사용)

  • 아규먼트 오류가 발생한다.
  • 이때, 람다 함수에서 바로 수정 불가능하다. 따라서 VS Code를 다시 수정 및 압축해서 다시 소스 코드로 사용해 보자.
import pymysql


def lambda_handler(event, context):     
    ret = []
    db = pymysql.connect(host='연결하고자하는RDS엔드포인트주소', user='root', db='sampledb', password='password', charset='utf8')
    curs = db.cursor()
    
    sql = "select * from emp"
    curs.execute(sql)
    
    rows = curs.fetchall()
    for e in rows:
        temp = {'empno':e[0],'name':e[1],'department':e[2],'phone':e[3] }
        ret.append(temp)
    
    db.commit()
    db.close()
    return ret
  • 기존에서는 lambda_handler(event)였다. 아래 사진처럼 변경한다. (파이썬에서는 아규먼트 2개 사용)

  • 다시 파일을 압축시켜 올려 다시 확인해보자.

  • 이번에는 람다 함수 실행 대기 시간 오류가 발생한다. 3초가 조금 넘자 람다 함수가 에러를 발생시킨 것이다. 해당 대기 시간을 늘려보자.

  • 람다 함수 - 구성 -일반 구성 - 편집 - 기존 : 3초 -> 1분 -> 테스트 재실행

  • 다시 에러코드가 나왔다. 해당 내용을 확인해보면, 람다 함수가 RDS와의 연결이 되지 않아 발생한 오류이다.

  • 람다 함수는 RDS와 같은 VPC에 속해 있다. 따라서 람다 함수의 VPC를 설정해준다.

  • 람다 함수 - VPC - 편집 - 아래와 같이 추가해준다.

  • 그러나 권한 오류가 발생한다

  • 람다 함수에 네트워크 인터페이스 생성 권한이 없어서 그런 것이다.

  • 새로운 창에서 람다 함수로 들어간다

  • 람다 함수에 해당 권한을 추가해주자.

  • 람다 함수에 구성 - 권한 - 실행 역할 이름 클릭

  • 권한 추가 - 정책 연결에서 AWSLambdaVPCAccessExecutionRole 추가한다.

  • 다시 람다 VPC 편집 창으로 돌아가 저장을 눌러주면 권한이 추가된다.

  • 이제 RDS에서 람다 함수를 연결 추가해주자.

  • RDS 프록시 기능을 해제 후 설정한다.

  • 다시 람다 함수를 테스트해보자

  • 정상적으로 데이터를 가져온다.

    왜 테스트를 하면 데이터를 응답으로 가져올까? EC2, RDS 와 연관지어 생각해보자

3-3. API 게이트웨이 생성

  • 이전에서는 람다 함수를 내부 (AWS 웹 콘솔)에서만 호출 가능했다.

  • API 게이트웨이를 생성해 외부 사용자가 람다 함수를 호출, 실행 할 수 있도록 설정해보자.

  • AWS 웹 콘솔에서 REST-API - REST API 생성

  • 생성된 REST API 에서 리소스 생성을 눌러 리소스를 추가한다.

  • 메서드를 추가한다

  • REST API 에서는 메서드 유형이 (GET, DELETE, PUT, 등이 존재) GET 으로 설정해 추가해준다.

  • 아래 그림에서 선택한(밑줄) 람다 함수가 아닌, 그 위의 람다 함수를 추가했다.

  • REST API에 리소스와 메소드도 지정한 것을 확인 가능하다

  • 테스트에 매개변수를 넣지 않고 확인해 보자.

  • 해당 테스트 결과를 자세히 확인해보자

  • 응답 본문 : 람다 함수의 응답

  • 응답 헤더 : 람다 함수의 응답 헤더

  • 로그 : REST API가 테스트를 수행하며 발생한 로그이다. 해당 로그에는 REST API와 람다 로그가 섞여있다.

3-3. API 배포

  • 이제 REST API 를 배포해보자.
  • 배포 버튼을 누르고, 스테이지를 선택하자.
  • 스테이지를 선택하라고 나온다. 여기서의 스테이지는 배포 목적을 기입하는 것이다. 새로운 스테이지를 생성하고, 프로덕션을 위한 배포 API 라고 배포 설명에 기입 후 배포하자.

  • 스테이지가 생성되었다.

  • API Gateway의 엔드포인트로 접근해보자.

  • 해당 엔드포인트에서 /emp 를 추가하면 이는 리소스를 의미한다.

  • 합쳐진 URL은 브라우저로부터 HTTP GET 방식으로 요청된다.

  • 해당 요청을 받은 API GateWay가 데이터를 가져와 보여준다.

  • 이제 API Gateway 주소를 호출하도록 리액트를 수정해보자
import { useEffect, useState } from 'react';
import './App.css';
import axios from 'axios';

function App() {
  // 상태변수를 정의
  const [emps, setEmp] = useState([]);  
  
  // 화면이 최초로 출력되었을 때(=마운트될 때) 동작을 정의 
  useEffect(() => {
        // axios.get('http://localhost:80/emp01')
    // 플라스크 서버가 동작하고 있는 EC2 인스턴스의 퍼블릭 주소로 변경
    axios.get('https://elzsq6rd82.execute-api.ap-southeast-1.amazonaws.com/prod/emp')
    .then(res => {
      console.log(res);   // 응답 내용을 콘솔에 출력
      setEmp(res.data);   // 응답 내용 중 data 항목을 상태변수 emps에 설정
    })
    .catch(err => console.log(err));
  }, []);

  return (
    <table>
      <tr>
        <th>사번</th>
        <th>이름</th>
        <th>부서</th>
        <th>전화번호</th>
      </tr>
        { // 상태변수의 내용을 화면에 출력
          emps.map(emp => 
            <tr>
              <td>{emp.empno}</td>
              <td>{emp.name}</td>
              <td>{emp.department}</td>
              <td>{emp.phone}</td>
            </tr>            
          )
        }        
    </table>
  );
}

export default App;

  • 이제 PC에서 리액트 개발 서버를 실행해 실행 결과를 확인해보자.
#리액트 파이썬 코드 있는 곳으로 이동. (C:\aws\hello-react\src 나는 이곳에 있었다.) 해당 위치로 CMD 이동
 C:\aws\hello-react>python -m venv venv # 가상 환경 설정
 C:\aws\hello-react>cd \venv\Scripts>npm start
 C:\aws\hello-react\venv\Scripts>activate # 가상 터미널 실행
(venv) C:\aws\hello-react\venv\Scripts>npm start

  • CORS 오류가 발생해 데이터를 가져오지 못한다.

  • API Gateway 에서 CORS 관련 설정을 해서 해결해보자.

  • API Gateway - API - 리소스 - > /emp 에서 CORS 활성화한다.

  • 이때, 스테이지에서 CORS 활성화가 아니다!!!!

  • 접근 제어 허용 메소드에서 GET 이 발생하면, 오리진이 ( * )으로부터 온 데이터의 CORS를 활성화 시켜준다.

  • 해당 메소드에 대해 다시 배포해준다.

  • 새로고침 하면 이제 데이터가 나온다.

  • 이렇게 구현이 된것이다

3-4. S3 버킷 정적 웹 호스팅 추가

  • 리액트 코드를 이제 로컬이 아닌 S3로 옮겨보자.

  • 리액트 코드 빌드

C:\aws\hello-react> npm run build
  • 빌드된 리액트 코드를 S3 버킷에 업로드한다.

  • 업로드한 객체(빌드 결과)에 퍼블릭 엑세스 권한을 부여한다.

3-5. 서버리스 아키텍처 완성

  • 이제 S3 버킷의 정적 웹 사이트 호스팅 주소로 접속해보자

  • 접속 가능하다!
  • (2번째 해봤을때, API Gateway 까지는 잘 나왔으나, S3버킷에 리액트 앱을 올려 정적 호스팅 시 데이터가 나오지 않음)
  • 해결 방법 : 기존 리액트 앱 바인드 파일 삭제 후 다시 바인드. 그리고 S3 버킷에 드래그 인 클릭으로 넣는다 (14개 들어갔음)

리소스 정리

  • EC2 종료
  • 버킷 삭제
  • API Gateway 삭제
  • IAM 역할 삭제

  • RDS 삭제
  • RDS에서 사용한 프록시도 삭제한다 (프록시가 삭제가 되지 않는다면 VPC가 삭제되지 않는다)

  • VPC 삭제
profile
磨斧爲針

0개의 댓글