레이블이 [011. AWS]인 게시물을 표시합니다. 모든 게시물 표시
레이블이 [011. AWS]인 게시물을 표시합니다. 모든 게시물 표시

2020년 3월 22일 일요일

[AWS] AWS CloudFront에서만 S3 Bucket에서 파일을 가져갈 수 있도록 Bucket policy 작성하기

AWS CloudFront에서만 S3 Bucket에서 파일을 가져갈 수 있도록 Bucket policy 작성하기


AWS S3를 Origin으로 사용하는 CloudFront 배포를 만드는 경우가 있습니다. 예를 들면, S3에 저장된 파일들을 CDN으로 배포하려는 경우와 S3에서 정적 웹호스팅 기능을 사용하면서 SSL을 적용하기 위해서 CloudFront를 이용하는 경우가 있습니다.

위의 두 경우 모두 S3 Bucket에 저장한 파일을 Public Internet에 제공하기 위한 것이기 때문에, S3 Bucket의 정책을 퍼블릭하게 설정하게 됩니다. 하지만 CloudFront를 이용해서 S3 Bucket의 파일들을 Public Internet에 공개한다면 Bucket의 정책을 퍼블릭하게 설정하지 않고, CloudFront 배포에서만 접근하도록 설정하면 됩니다.

방법은 아주 간단합니다. S3 Bucket 정책의 Pricipal에 허용하려는 CloudFront 배포의 Origin Access Identity (OAI)를 명세하는 것입니다.


CloudFront 배포에서 Origin Access Identity (OAI)를 가져오기

OAI는 CloudFront에서 생성할 수 있습니다. CloudFront 배포의 'Origins and Origin Groups' 탭에서 Origin을 선택해서 Edit을 클릭하면 아래 이미지와 같은 화면을 볼 수 있습니다.

여기에서 'Origin Domain Name'을 클릭하면 Origin으로 사용 가능한 목록이 나오는데, 이 목록에서 연결할 S3 Bucket을 선택하면 아래에 'Restrict Bucket Access'항목이 나타납니다. 이 항목의 옵션을 'Yes'로 선택하면, 'Origin Access Identify'항목에서 OAI를 새로 생성하거나 기존의 값을 선택할 수 있습니다.

설정을 완료하고 'Edit'을 누르면 Origin 목록에서 Origin의 OAI를 확인할 수 있습니다.

S3 Bucket의 정책에 OAI 적용하기

OAI가 적용된 정책은 아래와 같습니다.
CloudFront에서 확인할 수 있는 OAI의 형태는 origin-access-identity/cloudfront/EH1HDMB1FH2TC와 같은 형태인데 여기에서 EH1HDMB1FH2TC만 복사해서 Bucket 정책의 {OAI}자리에 붙여 넣으면 됩니다.
그리고 {YOUR_BUCKET_NAME} 자리에는 Bucket 이름을 입력해주세요.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity {OAI}"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{YOUR_BUCKET_NAME}/*"
        }
    ]
}

설정이 끝나면, S3에 저장된 파일들은 S3 url로 접근하면 AccessDenied 에러가 발생하게 됩니다. 하지만 CloudFront로 연결한 URL로 접근하면 정상적으로 파일 접근이 되는 것을 확인 할 수 있습니다.

참고자료

2020년 3월 18일 수요일

AWS Amplify Console을 이용한 프론트엔드 배포자동화 시스템 구축하기

AWS Amplify Console을 이용한 프론트엔드 배포자동화 시스템 구축하기

이번 포스팅에서는 AWS의 Amplify Console 서비스에 대해서 정리해보려 합니다.
Amplify는 사실 3가지로 나눠집니다.
(1) Amplify 라이브러리: 클라우드 기능을 편리하게 사용할 수 있는 Javascript 라이브러리
(2) Amplify CLI: CLI 환경에서 클라우드 서비스를 생성, 관리 할 수 있는 tool
(3) Amplify Console: 정적 웹 호스팅을 위한 서버리스 지속적 배포 서비스
이 중에서 최근에 저는 Amplify Console에 대해서 알아보고 매력을 느껴서 블로그로 정리해두려합니다.


Amplify Console이란?

AWS Amplify Console에서는 Git 기반 워크플로를 통해 풀 스택 서버리스 웹 애플리케이션을 배포 및 호스팅합니다. 풀 스택 서버리스 앱은 GraphQL 또는 REST API, 파일 및 데이터 스토리지 같은 클라우드 리소스로 빌드된 백엔드와 React, Angular, Vue 또는 Gatsby 같은 단일 페이지 애플리케이션 프레임워크로 빌드된 프런트엔드로 구성되어 있습니다.
AWS Amplify Console 공식 웹사이트에 위와 같이 설명되어 있습니다. 설명대로 Amplify Console로는 프론트엔드 뿐만 아니라 백엔드까지 배포자동화 시스템을 구축할 수 있습니다.
배포자동화는 이미 잘 알려진 tool들이 있습니다. 젠킨스도 있고, AWS 내에도 CodeBuild, CodeDeploy, CodePipeline 같은 도구들이 많습니다.
이미 많은 tool들이 있음에도 Amplify Console은 왜 나왔는지를 생각해보면, 저는 그 이유가 빠르고 쉬운 배포자동화 시스템 구축에 있다고 봅니다.
아래에서 프론트엔드 프로젝트에 대해서 Amplify Console을 이용한 배포자동화 시스템을 구축해보면서, 얼마나 빠르고 쉬운지 소개하겠습니다.

Amplify Console을 이용한 프론트엔드 배포자동화 구축

이번 작업을 위해서 Next.js 프로젝트를 가져왔습니다. 사실 이번에 새로 공부해보려는건데, 어차피 공부하면서 배포도 해볼겸 Amplify Console로 해보려합니다.
Next.js를 완전 처음 셋팅한 그대로라고 보시면 됩니다.

(1) Amplify Console 접속

AWS Console에 접속해서 서비스 중에 Amplify에 들어가면 아래와 같은 화면이 나타납니다.(앱이 없을때 기준)

화면에서 'Deploy'영역에 있는 'GET STARTED'를 클릭합니다. 그러면, 앱 생성 절차를 시작하게 됩니다.

(2) Github 연결

앱 생성의 첫 단계는 소스코드 연결입니다. 아래 이미지처럼 다양한 옵션이 있습니다. 다양한 Git Repository를 선택할수도 있고, 샘플에서 선택하거나 CLI로 새로 만들수도 있습니다.
여러 옵션중에서 대부분 Git을 연결할 것이라 생각이되고, 저도 Github으로 연결하려합니다.

Github을 선택하고 'Continue'를 선택하면 Github 로그인 페이지로 이동할 것입니다. 여기서 로그인을 하면 아래 이미지와 같이 나타나고 'Authorize aws-amplify-console' 버튼을 눌러서 Amplify Console에서 사용자의 Github Repository에 접근할 수 있도록 권한을 줍니다.

(3) Git Repository 및 Branch 연결

권한을 승인하고 나면, 아래 이미지와 같이 Repositoy를 선택하는 페이지로 이동합니다.
리포지토리 선택 목록에는 제 Github 계정의 Repository들이 나타납니다.
Repository를 선택하면 바로 아래에 브랜치 선택 영역이 나타나고, 자동으로 배포하고 싶은 브랜치를 선택합니다. 다른 브랜치들도 앱생성을 완료한 이후에 더 추가 가능합니다!

(4) 빌드스펙 설정

다음으로 빌드 스펙을 설정합니다. 빌드 스펙에는 프로젝트를 어떤 명령어로 빌드하는지, 빌드 결과물은 어디에 저장되는지 지정합니다.

기본 설정되어 있는 빌드스펙은 Amplify Console에서 자동으로 프로젝트를 감지하여 작성된 것인데, 저는 아래와 같이 수정하였습니다.
빌드 설정도 나중에 수정가능 하니깐 처음부터 정확하게 입력할 필요는 없습니다.
빌드 스펙 작성이 완료되면 '다음' 버튼을 누릅니다.
version: 0.1
# 프론트엔드 프로젝트에 대한 빌드 설정 부분입니다.
frontend:
  # 빌드 단계별로 원하는 명령을 입력합니다.
  phases:
    # 빌드 전에 필요한 환경을 설치합니다.
    install:
      runtime-versions:
        nodejs: 12
    # 빌드 전에 수행할 명령을 입력합니다.
    preBuild:
      commands:
        - echo Buile Phase >> preBuild phase...
        - npm ci
    # 빌드를 수행할 명령을 입력합니다.
    build:
      commands:
        - npm run export
    # 빌드 후에 수행할 명령을 입력합니다.
    postBuild:
      commands:
        - echo Buile Phase >> Build completed on `date`
  # 빌드 결과물로 나온 아티팩트에 대한 정보를 제공합니다.
  artifacts:
    # 빌드 환경에서 빌드 출력 결과물이 생성되는 위치를 나타냅니다.
    # '**/*'는 모든 파일을 재귀적으로 나타냅니다.
    baseDirectory: out
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

(5) 검토

검토단계에서는 이전에 설정한 내용들이 맞는지만 확인하고 맞으면, '저장 및 배포'를 누르면 끝입니다!
단순한 작업 몇번으로 배포자동화 시스템이 구축되는 것입니다!!



배포 확인

앱 생성이 완료 되면, 아래 이미지와 같이 브랜치별로 배포 정보가 표시됩니다.
왼쪽의 브라우저 이미지를 누르면 배포된 웹어플리케이션을 확인할 수 있는 링크가 열립니다.

이렇게 단순한 절차 몇번으로 배포자동화 시스템이 구축되었습니다!!
아주 빠르고 쉬운 방법이지 않나요? 젠킨스나 CodePipeline과 같은 tool들보다 훨씬 적은 설정으로 빠르게 배포가 된다고 생각합니다.


SPA를 Amplify Console에서 정적 웹호스팅 할 때의 주의점

Amplify Console은 정적웹호스팅을 지원하기 때문에, SPA에서 동적라우트가 있는 경우에 추가 설정을 해줘야합니다.
동적라우트는 SPA를 정적 리소스로 빌드했을 때 index.html과 같은 실제 파일로 떨어지는 것이 아니기 때문에, 동적 라우트 URL을 직접 브라우저에 입력해서 접속하게되면(또는 새탭으로 열기) 서버(e.g. Amplify Console)에서는 404에러(없는 파일)가 발생하게됩니다.
Amplify Console에서는 SPA를 올릴 경우에 ‘Rewrites and redirects’ 설정을 해줘야합니다. 아래 링크가 관련된 문서입니다.
https://docs.aws.amazon.com/amplify/latest/userguide/redirects.html#redirects-for-single-page-web-apps-spa내용을 정리하자면, 정적파일 이외의 Path는 SPA Route이기 때문에 실제로 파일이 존재하는 것이 아니라서 SPA의 Router 라이브러리가 URL을 확인하고 적절한 페이지를 표시하게 해야합니다. 그렇게 하기 위해서 Amplify Console의 Rewrites and redirects 설정에서 정적파일 이외의 Path로 요청이 들어오면 /index.html 파일을 전송하도록 지정해야합니다.


Source address: </^[^.]+$|\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>
Target address: /index.html
Type: 200(Rewrite)

Amplify Console의 특징

(1) 배포 과정 간소화

Amplify Console 자체가 배포자동화 서비스이기 때문에, 당연하게 배포 과정이 매우 간소화됩니다.
Amplify Console의 앱에 연결된 Repository의 Branch에 변경이 발생하면 자동으로 이를 감지하여, 빌드와 배포를 알아서 해줍니다.

(2) 즉시 배포

Amplify Console은 배포를 위해서 내부적으로는 S3와 CloudFront를 사용합니다. CloudFront를 사용해본 사람들은 보통 여기서 질문을 가집니다.
Origin의 파일이 변경되면, CloudFront의 캐시에 저장된 것을 Invalidation해줘야 Origin에서 변경된 파일을 가져오지 않는가?
Invalidation을 해주지 않으면 캐시에 저장된 파일이 만료되어 삭제될 때까지 새로운 Origin의 새로운 파일은 적용되지 않지 않나?
일반적인 CloudFront 배포라면 그렇겠지만, Amplify Console에서는 조금 다릅니다.
Amplify Console에서는 새로운 배포를 만들어서 S3에 저장하면서 버저닝을 합니다. 그리고 CloudFront에서는 가장 최신 버전의 파일을 S3에서 가져가서 CDN에 새로 저장합니다. 그렇기 때문에, 새로운 배포가 즉각적으로 반영될 수 있습니다.


(3) 고가용성

Amplify Console은 내부적으로 S3와 CloudFront를 이용하기 때문에 가용성이 높습니다. S3만으로도 99.99%의 가용성을 가지고 있는데, 이를 CloudFront에 배포되기 때문에 다수의 저장소에 저장되어 있는 셈입니다.

(4) 간편한 SSL 인증서 적용 및 Custom Domain 설정

보통 SSL 인증서를 적용시키려면 ACM에 가서 인증서를 생성하고 CloudFront에 따로 적용을 해줘야합니다. 그리고 Custom Domain도 Route53에서 생성해줘야합니다.
하지만, Amplify Console은 SSL 인증서 생성과 Custom Domain 생성 및 적용을 바로 할 수 있습니다. 아! 물론 도메인은 Route53에 등록되어 있어야하고, Amplify Console에서는 Domain에 Record set을 만들 수 있는 것입니다.
이 작업을 실제로 해보신다면, ACM과 Route53에서 각각 작업을 안 하고 Amplify Console에서 하는게 얼마나 간편한지 느낄 수 있습니다.

(5) 작업별 테스트 배포 환경의 분리

하나의 Git Repository를 다수의 작업자가 작업을 한다면, 각자의 작업을 분리된 환경에서 배포하여 테스트 할 필요가 있을 것입니다.
Amplify Console은 Brand별로 각기 다른 배포를 관리하고 각기 다른 URL이 할당됩니다.
또한, Preview 기능을 이용하면 지정한 Branch에 Pull Request가 생성되었을 때, 자동으로 해당 Pull Request에 대한 Preview 배포를 진행합니다. 그리고, Pull Request가 타겟 Branch에 Merge되면 Preview 배포도 자동으로 삭제됩니다.
이렇게 브랜치 별로 배포 환경을 분리하거나 Pull Request별로 배포 환경을 분리함으로써, 다수의 작업자가 자신의 작업물을 독립된 환경에서 테스트 할 수 있습니다.

(6) 서버리스

여기서 소개한 모든 특징이 서버리스라서 필요할 때, 필요한 만큼 과금된다는 장점이 있습니다.
배포자동화를 위해서 상시 운영되는 서버가 필요하지 않고, 빌드 시간만큼만 과금됩니다.
그리고 웹호스팅을 위해서도 상시 운영되는 서버가 필요하지 않고, 주로 제공된 저장용량과 트래픽에 대해서 과금됩니다.


저에게는 Amplify Console이 웹 프론트엔드 프로젝트에 대한 배포자동화 서비스 중에서 아주 간편하고 강력해서 너무 매력적입니다.
물론, Amplify Console이 배포자동화를 위한 모든 기능을 제공하고 있지 않기 때문에 더 많은 기능을 위해서는 다른 방법으로 직접 배포자동화 시스템을 구축해야할 수도 있지만, 그건 향후에 필요해 질때 하면 되고 처음에는 간단하게 시작해서 점점 발전시켜나가보려 합니다!


2019년 12월 7일 토요일

[AWS] AWS CodeBuild를 이용해서 프로젝트 빌드하기

[AWS] AWS CodeBuild를 이용해서 프로젝트 빌드하기

AWS CodeBuild 란?

AWS CodeBuild는 소스 코드를 컴파일하고 테스트를 실행하며 배포 준비가 완료된 소프트웨어 패키지를 생성하는 완전 관리형 지속 통합 서비스입니다.
ㅡ 'AWS CodeBuild 웹사이트' 내용 중,
설명에서도 알 수 있듯이 CodeBuild는 CD(Continuous Deployment, 지속적 통합)에 사용되는 서비스입니다.
일반적으로, 빌드를 로컬에서 수행하고 직접 서버에 배포할 수 있습니다. 하지만 이런 시간을 단축하기 위해서 단순히 프로젝트를 git에 push하는 것만으로 자동으로 빌드를 수행하도록 CodeBuild와 같은 Tool을 이용합니다.
CodeBuild 요금은 실제로 빌드한 시간 만큼만 지불하면 됩니다.

CodeBuild 작동 개요

CodeBuild는 아래 그림처럼, 소스 공급자에 소스가 업로드 되면 CodeBuild에서 알아서 가져다가 빌드를 진행합니다. 그리고 빌드가 완료되면 아티팩트(빌드 결과물)를 아티팩트 저장소에 저장합니다.
CodeBuild에서 지원하는 소스 공급자 리스트는 아래와 같습니다.
  • AWS CodeCommit
  • Amazon S3
  • Github
  • Github Enterprise
  • Bitbucket
그리고 아티팩트 저장소는 Amazon S3를 선택하거나 '선택하지 않을 수' 있습니다.
선택하지 않는 경우는, 빌드 후 절차에서 ECR에 저장하거나 단순 빌드 테스트하는 목적입니다.
이번 포스팅에서는 CodeBuild를 기초적으로 사용해보기 위해서 아래와 같이 소스 공급자를 Github으로 하고, 아티팩트 저장소를 Amazon S3로 해보겠습니다.

CodeBuild로 프로젝트 빌드하기

이번 포스팅에서 사용하는 소스코드는 Nuxt.js를 이용한 웹 프론트엔드 프로젝트입니다.
그래서, 빌드 환경이 Node.js 이며 버전은 12 입니다.
[2019.12.07 기준] 한국어 AWS 문서가 아직 최신 내용으로 업데이트가 되지 않았습니다. 한국어 문서에는 nodejs 지원 버전이 8와 10이 있는데, 영어로 보면 nodejs 지원 버전이 10, 12가 추가되어 있네요.

(1) 아티팩트 저장소로 사용할 Amazon S3 Bucket 생성

CodeBuild 프로젝트를 생성하기에 앞서서, 생성 과정에서 선택해줄, 아티팩트 저장소로 S3 Bucket을 생성해줍니다.

(2) buildspec.yml 작성

buildspec.yml 파일에는 빌드과정에서 필요한 정보를 입력합니다. 빌드 환경을 설정하거나 빌드 과정에서 수행할 명령어들을 입력하고, 빌드 결과물에 대한 정보를 입력합니다.
작성한 파일은 기본적으로 소스 프로젝트의 루트 디렉토리에 저장합니다.
buildspec.yml에 대한 자세한 설명은 아래 링크에서 확인하실 수 있습니다.
(링크: https://docs.aws.amazon.com/ko_kr/codebuild/latest/userguide/build-spec-ref.html )
아래 예시는 제가 이번 포스팅에서 사용할 buildspec.yml의 내용입니다.
# 버전은 현재, 0.2가 권장사항입니다.
version: 0.2

# 빌드 단계별로 원하는 명령을 입력합니다.
phases:
  # 빌드 전에 필요한 환경을 설치합니다.
  install:
    runtime-versions:
      nodejs: 12
  # 빌드 전에 수행할 명령을 입력합니다.
  pre_build:
    commands:
      - echo Buile Phase >> pre_build phase...
  # 빌드를 수행할 명령을 입력합니다.
  build:
    commands:
      - echo Buile Phase >> Build started on `date`
      - npm install
      - npm run generate
  # 빌드 후에 수행할 명령을 입력합니다.
  post_build:
    commands:
      - echo Buile Phase >> Build completed on `date`
# 빌드 결과물로 나온 아티팩트에 대한 정보를 제공합니다.
artifacts:
  # 빌드 환경에서 빌드 출력 결과물이 생성되는 위치를 나타냅니다.
  # '**/*'는 모든 파일을 재귀적으로 나타냅니다.
  files:
    - dist/**/*

(3) CodeBuild 프로젝트 생성

이제, AWS CodeBuild console에서 빌드 프로젝트를 생성합니다.
먼저, console에서 '빌드 프로젝트 생성'을 클릭합니다.
생성 페이지가 나타나면 아래의 사항들에 값을 입력해줍니다.
프로젝트 구성 섹션에서는 '프로젝트 이름'을 필수로 입력해주고, 선택적으로 '설명', '빌드 배지'를 설정합니다.
소스 섹션에는 모든 정보를 입력해줍니다. 저는 Github을 소스로 선택하였으며, Github과의 열결을 위하여 OAuth 방식을 사용하였습니다.
OAuth 방식으로 Github에 연결하려면 'Github에 연결' 버튼을 눌러서 새로 뜬 Github에 로그인 창에서 로그인을 해줘야합니다. 로그인을 하고 나면 'Authorize aws-codesuite' 버튼을 눌러서 AWS CodeBuild에서 Github에 접근할 수 있게 허용해줍니다.
Github과 연결하고 나면 소스 섹션이 아래와 같이 변합니다.
'내 Github 계정의 리포지토리'를 선택하면 'Github 리포지토리'를 눌렀을 때, 내 Github 리포지토리 목록이 나와서 선택할 수 있습니다.
목록에서 소스로 사용할 리포지토리를 선택해주세요.
그리고 '소스 버전' 항목에 저는 release를 입력했습니다. '소스 버전'에 입력하는 버전은 CodeBuild console에서 수동으로 빌드할 때 기본으로 사용할 소스의 버전입니다.
저는 release 브랜치에 PUSH 이벤트가 발생 했을 때 빌드가 실행되게 하기 위해서, '기본 소스 Webhook 이벤트' 섹션에서 이벤트 유형 중에 PUSH를 선택했습니다. 그리고서, '이러한 조건에서 빌드 시작'의 옵션 중에서 'HEAD_REF'에 'refs/heads/release'를 입력했습니다.
환경 섹션에서는 아래 이미지처럼만 설정해줍니다. 기본적인 설정이며, 각자에 맞는 환경이 필요하다면 상황에 맞게 빌드 환경을 설정하시면 됩니다.
Buildspec 섹션에서는 Buildspec을 어떻게 제공할지 설정하는데, 저는 아까 buildspec.yml을 작성하고 프로젝트 루트 디렉토리에 저장해놨습니다. 그래서 'buildspec 파일 사용'을 선택하고 넘어갑니다.
아티팩트 섹션에서는 빌드 결과물을 내보낼 저장소에 대한 정보를 입력합니다.
저는 Amazon S3에 결과물을 저장할 것이기 때문에 S3를 선택했고, '버킷 이름'은 클릭하면 버킷 리스트가 나타납니다.
다른 항목들은 필수는 아니기 때문에 저는 입력하지 않았습니다.
마지막으로 로그 섹션에서도 기본적으로 선택되어 있는 CloudWatch 로그를 선택하고 끝냅니다.
모든 설정이 완료되면 하단에 있는 '빌드 프로젝트 생성' 버튼을 누릅니다.

(4) 빌드

빌드 프로젝트가 생성되었으니, 빌드를 한번 해봅니다.
빌드 프로젝트 화면에서 '빌드 시작' 버튼을 누릅니다.
그러면, 빌드 구성을 조금 수정할 수 있는 페이지로 이동하는데, 변경하지 않거나 상황에 맞게 조금 변경하고 '빌드 시작'을 누르면 빌드가 시작됩니다.
빌드가 진행되면 상태가 '진행 중' 이었다가 완료되면 실패 또는 성공으로 나타납니다!!

'기본 소스 Webhook 이벤트' 섹션에 설정이 잘 되었다면, Git 이벤트를 발생시켰을 때도 동일하게 빌드가 진행되는 것을 확인할 수 있습니다.



2019년 2월 27일 수요일

[AWS] 프론트엔드 개발자가 혼자 웹어플리케이션 만들기. #4. AWS API Gateway, Lambda, DynamoDB를 이용한 REST API 구현

[AWS] 프론트엔드 개발자가 혼자 웹어플리케이션 만들기. #4. AWS API Gateway, Lambda, DynamoDB를 이용한 REST API 구현


  이번 포스팅에서는 AWS의 Serverless(서버리스) 서비스들을 이용해서 REST API를 만드는 방법을 정리해보려합니다.

  REST API라 하면, API를 호출할 수 있는 endpoint와, 호출과 함께 전달되는 데이터를 가공 및 처리할 수 있는 로직, 그리고 로직에 따라 데이터가 저장되거나 읽혀지는 데이터베이스가 기본 구성이 될 것입니다.
  이와 같은 기본 구성은 AWS Serverless 서비스들로 구현 가능합니다. endpoint를 생성 할 수 있는 API Gateway, 로직을 담당하는 Lambda, 데이터베이스는 DynamoDB가 담당합니다.


1. DynamoDB 테이블 생성

  먼저, 데이터를 저장하기 위한 데이터베이스로 DynamoDB 테이블을 생성합니다.
  DynamoDB는 AWS의 완전관리형 비관계형(NoSQL) 데이터베이스 서비스입니다. DynamoDB는 테이블 생성이 매우 간단하고, 인스턴스를 구동하는 방식이 아니기 때문에 RDS 처럼 인스턴스 스펙을 무엇으로 할지 고민할 필요가 없으며, 목표 처리량을 설정하기만 하면 나머지는 시스템에서 자동으로 처리합니다.

  DynamoDB는 Console에서 테이블만 생성하면 데이터베이스 구축 완성입니다. 우선, DynamoDB 대시보드에서 '테이블 만들기'를 클릭합니다.

(그림) DynamoDB 테이블 만들기


  첫 단계로 테이블 생성을 위한 정보를 입력하는데, '테이블 이름'을 입력하고 '기본키'에서 '파티션 키'의 이름과 타입만 입력해도 됩니다. 필요에 따라서 '정렬 키'를 추가할 수도 있습니다. '파티션 키'만 입력한다면, '파티션 키'만으로 저장된 항목 하나를 식별할 수 있어야합니다. 하지만 '정렬 키'를 추가한다면, '파티션 키'와 '정렬 키'의 쌍으로 저장된 항목 하나를 식별할 수 있습니다.
  입력 후에는 하단에 '생성' 버튼을 클릭합니다.

(그림) 테이블 생성을 위한 정보 입력


  이로써 테이블 생성이 끝났습니다. 테이블이 생성되면, 대시보드 좌측 리스트에 테이블이 나타나며, 테이블을 선택했을 때 우측에 나타나는 탭 중에서 '항목' 탭이 저장된 데이터를 볼 수 있는 탭입니다.

(그림) 테이블 생성 완료


2. Lambda Function 생성

  데이터베이스가 준비되었다면, 해당 데이터베이스에 데이터를 Create, Read, Update, Delete 할 수 있는 로직을 수행할 Lambda Function(함수)를 생성할 차례입니다.

  Lambda 대시보드에서 '함수 생성' 버튼을 클릭해서 Lambda Function 생성 절차를 시작합니다.

(그림) Lambda Function 생성 시작

  Lambda Function을 만드는 옵션은 총 3가지가 있습니다. 첫번째는 코드를 처음부터 새롭게 작성하는 '새로 작성' 옵션, 두번째는 AWS에서 미리 작성해둔 템플릿을 기반으로 코드를 작성하는 '블루프린트' 옵션, 세번째는 AWS 사용자들이 만들고 공유한 템플릿을 기반으로 코드를 작성하는 '서버리스 애플리케이션 리포지토리' 옵션입니다. 세번째 옵션은 최근에 새로 추가되었습니다.
  이번 포스팅에서는 '새로 작성'을 선택하겠습니다. 그런 다음, Function 생성을 위한 기본 정보를 입력합니다. Function의 이름을 입력하고 런타임을 선택하고 역할(Role)을 선택합니다. 이때의 역할은 현재 생성할 Function이 가지는 권한입니다. 만일 이 Function이 DynamoDB에 접근해야한다면 역할에 DynamoDB에 접근할 수 있는 정책(Policy)이 포함되어 있어야합니다.
  정보가 다 입력되면 하단에 '함수 생성'을 클릭합니다

(그림) Lambda Function 생성을 위한 정보 입력


  '함수 생성'을 누르고나면 Function의 코드를 작성할 수 있는 페이지가 나옵니다. 그곳에 원하는 동작을 하는 코드를 작성하면 됩니다. 아래 코드는 런타임이 Node.js 6 일때, DynamoDB에 기본적으로 CRUD하는 코드 예시입니다. 코드의 주석에서 중요 코드를 설명하겠습니다.

'use strict';

// DynamoDB에 접근할 수 있는 객체 생성
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();

// API Gateway를 이용해서 Lambda Function을 호출할 때,
// Query String이나 Request Body의 데이터는 handler 함수의 event 매개변수로 전달되어옵니다.
exports.handler = (event, context, callback) => {

  // handler 함수의 callback 매개변수를 이용해서 Lambda에서 API Gateway로 Response를 전달할 수 있습니다.
  const done = (err, res) => callback(null, {
    statusCode: err ? '400' : '200',
    body: err ? err.message : JSON.stringify(res),
    headers: {
      'Content-Type': 'application/json',
    },
  });

  // event 객체에는 API Gateway로 호출받은 HTTP Reqeust가 어떤 method인지 저장되어 있습니다.
  // 아래 코드는 HTTP method에 따라 DynamoDB에 CRUD하는 작업을 수행하는 부분입니다.
  switch (event.httpMethod) {
    case 'DELETE':
      dynamo.deleteItem(JSON.parse(event.body), done);
      break;
    case 'GET':
      dynamo.scan({ TableName: event.queryStringParameters.TableName }, done);
      break;
    case 'POST':
      dynamo.putItem(JSON.parse(event.body), done);
      break;
    case 'PUT':
      dynamo.updateItem(JSON.parse(event.body), done);
      break;
    default:
      done(new Error(`Unsupported method "${event.httpMethod}"`));
  }
};


  DynamoDB의 라이브러리에 대한 내용은 링크에서 확인가능합니다. Node.js용 DynamoDB SDK 확인은 여기에서 가능합니다. SDK 문서를 보면서 원하는 동작을 찾아가시면 됩니다.

  코드를 다 작성하고 '저장'을 누르면 Lambda도 준비가 끝났습니다.


3. API Gateway 생성

  이번에는 위에서 작성한 Lambda Function을 호출할 수 있는 endpoint를 만들기 위해서 API Gateway에서 API를 생성하는 방법을 정리합니다. API Gateway로 API를 생성하면 https를 지원하는 URL 형식의 endpoint를 받을 수 있습니다. 그래서 이 endpoint를 axios 같은 http request 라이브러리에서 사용할 수 있습니다.

  API Gateway 대시보드에 들어가서 'API 작성'을 클릭하여 API 생성 절차를 시작합니다.

(그림) 'API 작성' 클릭


  API 생성의 첫 단계는 생성할 API의 정보를 입력하는 것입니다. 새 API를 만들기 위해서는 'API 이름'만 필수로 입력하면 됩니다.
  '엔드 포인트 유형'은 링크를 참고해서 서비스에 맞게 적절히 선택하시면 됩니다. 여기서는 기본값인 '지역'을 선택하겠습니다.

(그림) API 생성을 위한 정보 입력


  API가 생성이되면 아래 그림처럼 '리소스' 영역에 Root Path ('/')가 나타납니다. 아래 그림의 /file 이나 /test는 제가 연습삼아 미리 추가한 것이고, 최초 API 생성 후에는 Root Path만 있습니다. 이 Root Path 하위에 여러 리소스들을 생성해서 여러 REST API URL을 만들어냅니다.
  새로운 하위 Path를 만들기 위해서는 Root Path를 선택한 상태에서 '작업' > '리소스 생성'을 선택합니다.
(그림) '리소스 생성' 선택


  리소스 생성하기 위해서는 '리소스 이름'만 입력하면 됩니다. '리소스 경로'는 리소스 이름을 따라 자동으로 입력되므로 새로 입력할 필요는 없습니다. CORS 활성화는 여기서 체크하지 않아도 됩니다. 어차피 나중에 메서드들을 생성하고 새로 활성화해줘야 하기 때문입니다.

(그림) '리소스 이름' 입력


  리소스를 생성하면 새로운 하위 path가 생성된 것입니다. 이제 이 path가 지원하는 http method를 생성해야합니다. 그러기 위해서 생성한 리소스를 선택한 상태에서 '작업' > '메서드 생성'을 선택합니다.

(그림) '메서드 생성' 선택


  생성할 메서드를 선택하고 체크 버튼을 클릭하면, 메서드 생성을 위한 정보를 입력하는 페이지로 이동합니다. 여기서는 위에서 만든 Lambda Function을 호출하기 위해서 '통합 유형''Lambda 함수'로 선택합니다. 그리고 'Lambda 프록시 통합 사용'을 체크하고 Lambda Function을 생성한 리전을 선택하고 생성한 Lambda Function을 선택합니다. 'Lambda 함수' 입력칸에는 텍스트를 입력할 수 있는데 첫글자를 입력하고나면 드랍다운이 나타나서 선택할 수 있습니다.

(그림) 생성할 메서드 선택

(그림) 생성할 메서드로 호출할 Lambda 함수 선택


  메서드 정보를 저장할 때, 권한에 대한 확인창이 나타나는데, '확인'을 눌러주면 됩니다.

(그림) Lambda Function 호출을 위한 권한 추가


  새로운 리소스와 메서드를 생성했다면, 'CORS 활성화'를 해주어야합니다. 그래야 브라우저에서 다른 도메인 간의 호출이 가능해집니다. CORS 활성화 페이지에서는 별도의 설정이 필요한 상황이 아니라면 바로 'CORS 활성화 및 기존의 CORS 헤더 대체' 버튼을 클릭합니다.

(그림) 'CORS 활성화'

(그림) 대체 버튼 클릭

(그림) 재확인 창에서 다시 버큰 클릭


  사실 가장 많이 실수 하는 부분이 이 부분일것 같습니다. API를 생성하고 온갖 설정을 했지만, 현재는 실제 사용할 수 없습니다. 설정이 끝난 API는 'API 배포'를 해야만 실제로 사용할 수 있습니다. 배포를 위해서는 '작업' > 'API 배포'를 선택합니다.

(그림) 'API 배포' 선택


   API 배포는 스테이지(Stage)를 지정해서 배포할 수 있습니다. 스테이지를 이용하면, 개발단계의 API와 운영단계의 API의 호출 URL을 구분할 수 있습니다. 예를 들어서 방금 전에 만든 API를 실제 운영단계에서 사용하기 전에 테스트를 해보고 싶다면, dev 또는 test라는 스테이지에 배포하고 이 스테이지의 호출 URL을 이용해서 미리 테스트 한 다음에 운영단계의 스테이지에 배포합니다.
  아래 그림은 새로운 스테이지를 만드는 화면입니다. '스테이지 이름'만 입력하면 API 배포가 가능하지만, 현재 배포하는 내용이 무엇인지 설명을 쓰는것이 API 관리에는 도움이 됩니다.


(그림) API 배포 


  API를 배포하고나면, 이 API를 호출할 수 있는 호출 URL가 주어집니다. 이 호출 URL과 생성한 리소스의 하위 path를 이용하여 http request를 요청할 수 있습니다. 예를 들어서 호출 URL이 'https://api.test.com/prod' 이고 리소스의 하위 path가 '/content' 라면, http request를 'https://api/test.com/prod/content'로 요청할 수 있습니다.

(그림) 스테이지마다 각각 주어지는 호출 URL



  이로써, API Gateway, Lambda, DynamoDB가 결합된 REST API를 완성했습니다.