Amazon Web Services 한국 블로그

[AWS Heroes 특집] Serverless Application Repository을 통한 서버리스 앱 구축하기

AWS 서버리스 히어로인 Aleksandar Simovic 의 기고입니다. Aleksandar는 Science Exchange의 수석 소프트웨어 엔지니어로, Manning Publications에서 출판한 “Serverless Applications with Node.js”를 Slobodan Stojanovic 와 공동으로 집필했으며 서버리스의 비즈니스 및 기술적 측면에 대한 글도 매체에 기고합니다.

여러분 중 다수는 사용자 로그인이나 권한 부여 서비스를 처음부터 구축한 경험이 수십 번은 있을 것입니다. 결제를 처리하는 다른 여러 서비스와 PDF를 내보내는 또 다른 서비스도 수차례에 걸쳐 구축하셨을 것입니다. 모든 엔지니어들은 이 작업을 중복으로 수행합니다. AWS Serverless Application Repository를 사용하면 고객에게 중요한 기능을 제공하는 비즈니스 논리를 더 빠르게 개발하는 데 더 많은 시간과 에너지를 쏟을 수 있습니다.

AWS Serverless Application Repository란?

AWS Serverless Application Repository는 개발자가 공통의 서버리스 구성 요소를 팀과 조직에 배포하고 게시하고 공유하는 데 필요한 기능을 제공합니다. 이 서비스의 퍼블릭 라이브러리에는 커뮤니티에서 구축한 오픈 소스 서버리스 구성 요소가 포함됩니다. 이러한 구성 요소는 사용자 지정 가능한 파라미터 및 미리 정의된 라이선스를 통해 즉시 검색 및 배포가 가능합니다. 이 서버리스 구성 요소는 AWS 리소스를 템플릿으로 만드는 데 사용되는 IaC(Infrastructure as Code) YAML 언어인 AWS Serverless Application Model(AWS SAM)을 사용하여 구축되고 게시됩니다.

정식 서비스에 활용하는 방법

저는 고객이 제품을 선택하고 결제할 수 있는 애플리케이션을 구축하려고 했습니다. 상당한 수고를 들여야 할 것 같은 이 작업은 AWS Serverless Application Repository를 사용하면서 예상보다 짧은 시간 안에 완료되었습니다.

간단히 말해 제가 구축한 항목은 다음과 같습니다.

  • Stripe Checkout SDK에 자동으로 연결되는 [Buy] 버튼이 있는 제품 페이지. 고객이 [Buy]를 선택하면 Stripe Checkout 결제 양식이 페이지에 표시됩니다.
  • Stripe의 콜백을 수락하고, 고객에게 요금을 부과하고, 거래 성공 알림을 전송하는 API 엔드포인트가 포함된 Stripe 결제 서비스.

이 게시물을 위해 제품 세부 정보를 표시하고 Stripe Checkout JavaScript가 포함되는 미리 구축된 샘플 정적 페이지를 만들었습니다.

미리 구축된 페이지에서도 결제 서비스를 통합할 수 있습니다. 그러나 다른 많은 개발자가 한 번 이상 구축한 결제 애플리케이션이 있는데 동일한 기능을 구축하는 데 시간을 낭비할 필요는 없습니다. 여기서 AWS Serverless Application Repository를 사용하면 이 작업이 편리해집니다.

구성 요소를 찾아서 배포해보기

먼저, AWS Serverless Application Repository 퍼블릭 라이브러리에서 기존 구성 요소를 검색합니다. “stripe”를 입력하고 사용자 지정 IAM 역할 또는 리소스 정책을 생성한 애플리케이션을 표시하도록 선택합니다. 결과는 다음과 같습니다.

api-lambda-stripe-charge라는 제목의 애플리케이션을 선택하고 구성 요소의 세부 정보 페이지에서 [Deploy]를 선택합니다.

구성 요소를 배포하기 전에 구성 요소가 안전하고 프로덕션 환경에서 사용 가능한지 여부를 검사합니다.

구성 요소 평가하기

AWS Serverless Application Repository 구성 요소를 평가할 때 권장되는 접근 방식은 4단계 프로세스입니다.

  1. 구성 요소 권한을 확인합니다.
  2. 구성 요소 구현을 검사합니다.
  3. 구성 요소를 제한된 환경에서 배포하고 실행합니다.
  4. 프로덕션 환경에서 사용하기 전에 구성 요소의 동작 및 비용을 모니터링합니다.

이러한 프로세스는 AWS Serverless Application Repository의 빠른 전송이라는 이점을 무색하게 만드는 것처럼 보일지 모르지만 실제로는 각 구성 요소를 한 번만 확인하면 됩니다. 그런 다음에는 회사 전체에서 구성 요소를 손쉽게 재사용하고 공유할 수 있습니다.

Stripe 구성 요소를 추가하는 동안 이 접근 방식을 적용하는 방법은 다음과 같습니다.

1. 구성 요소 권한 확인

구성 요소에는 퍼블릭과 프라이빗의 두 가지 유형이 있습니다. 퍼블릭 구성 요소는 오픈 소스이지만 프라이빗 구성 요소는 오픈 소스가 아닐 수 있습니다. 이 사례에서 Stripe 구성 요소는 퍼블릭입니다. 코드를 검토하여 보안을 침해할 수 있는 불필요한 권한이 부여되지 않는지 확인합니다.

이 사례에서 Stripe 구성 요소는 GitHub에 있습니다. 구성 요소 페이지에서 template.yaml 파일을 엽니다. 여기에 AWS Lambda 함수는 하나 뿐이므로 Policies 속성을 찾아서 사용되는 정책을 검토합니다.

  CreateStripeCharge:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs8.10
      Timeout: 10
      Policies:
        - SNSCrudPolicy:
          TopicName: !GetAtt SNSTopic.TopicName
        - Statement:
          Effect: Allow
          Action:
            - ssm:GetParameters
          Resource: !Sub
arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${SSMParameterPrefix}/*

이 구성 요소는 AWS SAM 정책 템플릿과 사용자 지정 템플릿을 사용합니다. 이러한 미리 정의된 정책 템플릿은 AWS 보안 팀이 확인을 마친 후 권장하는 AWS 권한 세트입니다. 이러한 정책 템플릿을 사용하여 리소스 권한을 지정하는 것은 AWS Serverless Application Repository의 서버리스 구성 요소를 사용할 때 권장되는 방법 중 하나입니다. 다른 사용자 지정 IAM 정책은 AWS System Manager 파라미터를 검색할 수 있는 기능을 제공하며 이 방법은 Stripe 보안 키 같은 보안 값을 저장할 때 사용되는 모범 사례입니다.

2. 구성 요소 구현 검사

구성 요소의 기본적인 비즈니스 논리가 설계 의도를 충족하는지, 즉 Stripe 요금을 생성하는지를 확인해야 합니다. 또한 알 수 없는 타사 HTTP 호출을 주시하여 유출을 방지하는 것도 중요합니다. 그런 다음 이 프로젝트의 종속성을 검토합니다. 이 검사에는 PureSec을 사용하지만 Protego가 제공하는 도구와 같은 다른 옵션을 선택할 수도 있습니다.

기본적인 비즈니스 논리는 charge-customer.js 파일에 있습니다. 이 파일에는 Stripe 요금 생성을 호출한 다음 생성된 요금이 포함된 알림을 게시하는 단순한 논리가 포함되어 있습니다. 이 논리는 다음과 같은 코드로 나타납니다.

return paymentProcessor.createCharge(token, amount, currency, description)
    .then(chargeResponse => {
      createdCharge = chargeResponse;
      return pubsub.publish(createdCharge, TOPIC_ARN);
    })
    .then(() => createdCharge)
    .catch((err) => {
      console.log(err);
      throw err;
    });

paymentProcessorpubsub 값은 각각 Stripe와 Amazon SNS의 통신에 사용되는 어댑터입니다. 작동 방식을 보고 확인하는 것이 좋습니다.

3. 제한된 환경에서 구성 요소를 배포하고 실행

서버리스 개발의 모범 사례는 서버리스 애플리케이션의 테스트를 위한 분리되고 제한된 AWS 계정을 유지하는 것입니다. 테스트 계정에 엄격한 AWS Billing 및 Amazon CloudWatch 경보가 설정되어 있는지 확인하는 것이 좋습니다.

이 개별 계정에 로그인하고 [Stripe component] 페이지를 연 다음 수동으로 배포합니다. 배포 후에는 실행 상태를 확인해야 합니다. 이 구성 요소에는 Lambda 함수가 하나만 포함되므로 Lambda 콘솔에서 함수를 살펴보고 세부 정보 페이지를 열어 코드를 확인합니다.

4. 프로덕션 환경에서 구성 요소를 사용하기 전에 동작 및 비용 모니터링

테스트 계정에서 모든 기능이 예상대로 작동하면 구성 요소에 모니터링 및 성능 도구를 추가하여 인시던트를 진단하고 구성 요소 성능을 평가합니다. 저는 주로 Epsagon 및 Lumigo를 사용하지만 이러한 단계를 추가하면 이 게시물이 너무 길어질 것 같습니다.

구성 요소의 비용도 추적해야 합니다. 비용을 추적하려면 구성 요소의 비용과 구성 요소 내의 각 AWS 리소스 비용을 추적하는 엄격한 AWS Billing 경보를 추가합니다.

구성 요소가 이 네 가지 테스트를 통과하면 기존의 제품 선택 애플리케이션에 이 구성 요소를 추가하여 배포할 수 있습니다.

기존 애플리케이션에 구성 요소 배포

Stripe 구성 요소를 기존 애플리케이션에 추가하려면 구성 요소의 [Review, Configure, and Deploy] 페이지를 열고 [Copy as SAM Resource]를 선택합니다. 그러면 필요한 템플릿 코드가 클립보드에 복사됩니다. 그런 다음 기존 AWS SAM 템플릿의 Resources 아래에 붙여넣는 방법으로 기존 서버리스 애플리케이션에 추가합니다. 결과는 다음과 같습니다.

Resources:
  ShowProduct:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs8.10
      Timeout: 10
      Events:
        Api:
          Type: Api
          Properties:
            Path: /product/:productId
            Method: GET
  apilambdastripecharge:
    Type: AWS::Serverless::Application
    Properties:
      Location:
        ApplicationId: arn:aws:serverlessrepo:us-east-1:375983427419:applications/api-lambda-stripe-charge
        SemanticVersion: 3.0.0
      Parameters:
        # (Optional) Cross-origin resource sharing (CORS) Origin. 단일 오리진을 지정하거나 "*"를 사용하여 모든 오리진을 지정하거나 빈 상태로 두어 CORS를 적용하지 않을 수 있습니다.
        CorsOrigin: YOUR_VALUE
        # This component assumes that the Stripe secret key needed to use the Stripe Charge API is stored as SecureStrings in Parameter Store under the prefix defined by this parameter. See the component README.
       # SSMParameterPrefix: lambda-stripe-charge # Uncomment to override the default value
Outputs:
  ApiUrl:
    Value: !Sub https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Stage/product/123
    Description: The URL of the sample API Gateway

AWS::Serverless::Application AWS SAM 리소스를 복사하고 붙여넣습니다. 이 리소스는 ApplicationId 및 해당 SemanticVersion을 사용하여 구성 요소를 가리킵니다. 그런 다음 구성 요소의 파라미터를 정의합니다.

  • 데모를 위해 CorsOrigin을 “*”로 설정합니다.
  • SSMParameterPrefix 값은 기본값을 사용하므로 설정하지 않아도 됩니다. 그러나 Stripe 보안 키는 Systems Manager Parameter Store에서 다음 명령을 실행하여 설정합니다.

aws ssm put-parameter --name lambda-stripe-charge/stripe-secret-key --value --type SecureString --overwrite

파라미터에 더해 구성 요소에도 출력이 포함됩니다. 출력은 표면화된 구성 요소 리소스 또는 값으로, 다른 애플리케이션 또는 구성 요소에서 사용할 수 있습니다. 예를 들어 api-lambda-stripe-charge 구성 요소의 출력은 Amazon SNS 주제를 나타내는 SNSTopic입니다. 이 출력을 다른 구성 요소 또는 비즈니스 논리에 연결하면 결제 성공 시 알림을 받을 수 있습니다. 예를 들어 결제 성공 시 이메일을 보내는 lambda-send-email-ses 구성 요소를 연결할 수도 있습니다.

마치기 전에 다음 2개의 명령을 실행합니다.

aws cloudformation package --template-file template.yaml --output-template-file output.yaml --s3-bucket YOUR_BUCKET_NAME

aws cloudformation deploy --template-file output.yaml --stack-name product-show-n-pay --capabilities CAPABILITY_IAM

두 번째 명령의 경우 필요에 따라 파라미터 재정의를 추가할 수 있습니다.

이제 제품 선택 및 결제 애플리케이션이 성공적으로 배포되었습니다.

요약

AWS Serverless Application Repository를 사용하면 공통의 구성 요소, 서비스 및 애플리케이션을 공유하고 재사용할 수 있으므로 핵심 비즈니스 가치를 구축하는 데 집중할 수 있습니다.

단 몇 단계를 수행하는 것으로 고객이 제품을 선택하고 결제할 수 있는 애플리케이션을 만들 수 있으며 몇 시간 또는 며칠이 아닌 몇 분 만에 작업을 완료할 수 있습니다. 신중하게 구성 요소를 분석하고 확인하는 데 긴 시간이 걸리지 않는 것을 알 수 있습니다. 이 구성 요소를 회사의 다른 팀과 공유하면 중복을 제거할 수 있습니다.

지금 바로 AWS Serverless Application Repository를 사용하여 팀의 제품 개발, 기능 제공과 프로덕션용 애플리케이션의 구축 및 공유를 가속화해 보시기 바랍니다.

– Aleksandar Simovic, AWS Serverless Hero