AWS 기술 블로그

AWS Application Composer를 활용한 서버리스 서비스 구현 방법

서비스에서 신규 기능으로 빈번하게 등장하는 기능 중 하나는 알람 기능입니다. 예를 들어 쇼핑몰 업체는 고객에게 배송 안내 알람을 전달하고 공장 운영 환경에서는 장비 장애 알람을 보냅니다. 문제는 이런 알람 서비스를 위해서 별도의 인스턴스를 만들고 웹 서버를 유지하는 건 새로운 관리 포인트를 만드는 일이라는 점입니다. 또한 알람 서비스의 특성상 대규모 고객에게 알람을 보내야 하는 일도 발생할 수 있는데 알람만을 위해서 별도 시스템을 구축하지 않으면 전체 시스템 장애로 이어질 수 있습니다. 그래서 저희는 고객에게 대안으로 서버리스 서비스를 안내해 드리고 있습니다. 서버리스 서비스를 선택하는 경우 고객은 별도의 인프라를 관리할 필요가 없고 비즈니스 로직 코드만 작성하면 됩니다. 확장성이나 안정성 면에서도 AWS가 관리하기 때문에 직접 인프라를 관리하는 것에 비해 공수를 줄일 수 있습니다.

하지만 서버리스 서비스를 선택한다고 해서 모든 문제가 해결되는 것은 아닙니다. 대표적으로 서버리스 서비스가 문제 되는 부분은 서비스 아키텍처를 팀원들과 공유하기 어렵다는 점입니다. 기존 서비스에서는 UML 등 도식도로 아키텍처를 공유했지만, 서비스가 잘게 분리되고 복잡해지는 이 시점에서 기존 방식이 항상 정답은 아닙니다.

이번 게시글에서는 AWS Application Composer 서비스를 통해서 알람 서비스를 서버리스 방식으로 만드는 방법을 소개합니다. 나아가서 실제 메일, Slack 등으로 알람을 전달하는 기능을 직접 구축해 보면서 어떻게 응용 가능한지도 알아봅니다. 사용자는 이 시스템을 이용해서 자신의 서비스에 쉽게 알람 서비스를 추가할 수 있습니다.

솔루션 개요

이번 게시글에서 소개하는 솔루션은 AWS Application Composer를 활용한 알람 서비스입니다. 최종적으로 고객에게 메일과 Slack 메시지를 전송하고 알람 데이터를 Amazon DynamoDB에 저장합니다. 각 과정을 구성하기 위해 사용한 AWS 서비스를 소개합니다.

AWS Application Composer : AWS Application Composer는 시각적으로 서버리스 아키텍처를 디자인하는 도구입니다. 즉시 배포할 수 있도록 IaC(Infrastructure as code) 문서를 생성하고 팀원 간 만들어진 IaC 문서를 공유하면서 아키텍처 모델을 유지 관리할 수 있습니다. 또 다른 장점으로는 AWS 보안 설정을 쉽게 할 수 있다는 점이 있습니다. AWS Application Composer를 사용하지 않는 경우에는 하나의 리소스에서 다른 리소스를 호출할 때 AWS Identity and Access Management(IAM) 설정을 수행해야 합니다. 하지만 Application Composer를 사용하면 각 화면을 보면서 구성요소를 연결하는 것만으로 보안 설정이 만들어집니다. 따라서 설계에만 집중하고 싶은 고객의 경우 유용하게 사용하실 수 있습니다.

AWS Serverless Application Model(SAM) : AWS Serverless Application Model은 서버리스 애플리케이션을 빌드하는데 사용하는 오픈소스 프레임워크입니다. AWS SAM 템플릿을 사용하여 서버리스 애플리케이션을 정의하고 구성하는 함수, API, 권한, 이벤트를 간단하게 만들 수 있습니다.

아키텍처 소개

이번 게시글에서는 소개하는 아키텍처는 실제 서비스 환경처럼 API를 호출해서 알람을 보내는 구조입니다. 알람 시나리오는 아래 순서로 진행합니다.

  1. Amazon API Gateway에서 API를 생성하고 해당 API로 요청을 받으면 AWS Lambda를 호출합니다.
  2. AWS Lambda에서는 Amazon Simple Notification Service(SNS)로 데이터를 전달합니다.
  3. Amazon Simple Notification Service(SNS)에서는 각 기능을 수행할 Lambda와 Amazon Simple Queue Service(SQS)로 데이터를 전달합니다.
  4. 첫번째 Lambda에서는 Amazon Simple Email Service(SES) API를 호출해 이메일을 전송합니다.
  5. 두번째 Lambda는 Slack API를 통해 Slack 메시지를 전달합니다.
  6. Amazon SQS로 받은 데이터는 Lambda를 통해 Amazon DynamoDB에 저장합니다.

사전 준비 사항

솔루션을 배포하기 위해서는 아래 항목을 준비해야 합니다.

단계 요약

  • 단계 1 : AWS Application Composer를 통한 서버리스 서비스 구성 연습
  • 단계 2 : 샘플 코드 다운로드
  • 단계 3 : AWS Serverless Application Model 구성
  • 단계 4 : 동작 확인

단계 1 : AWS Application Composer를 통한 서버리스 서비스 구성 연습

단계 1에서는 프로젝트를 새롭게 생성 해보고 서버리스 구성 요소들을 변경하는 작업을 진행하겠습니다. 그리고 단계 2에서 샘플 코드를 다운받아 실제 동작까지 수행하는 방식으로 핸즈온을 진행합니다.

1-1. AWS 계정에 로그인 후 콘솔에서 AWS Application Composer에 접속한 후 프로젝트 생성 버튼을 누릅니다. 그리고 아래와 같이 New Blank Project(새 빈 프로젝트) 버튼을 눌러 신규 프로젝트를 생성합니다.

1-2. 왼쪽에 있는 아이콘들을 클릭 후 캔버스에 이동합니다. 그리고 구성요소 박스 내부에 원을 클릭 후 다른 구성요소까지 이으면 두 가지 구성요소가 연결됩니다.

1-3 생성한 구성 요소를 더블 클릭하면 속성을 변경할 수 있습니다. Amazon DynamoDB에서는 아래와 같이 ID, 파티션키, 정렬키 등을 설정할 수 있습니다.

1-4 캔버스로 만든 아키텍처는 왼쪽 상단 메뉴 버튼을 클릭 후 변경 사항 저장을 통해 로컬로 내려받을 수 있습니다.

단계 2 : 샘플 코드 다운로드

단계 2는 미리 만들어진 샘플 코드로 진행합니다.

2-1. Github에서 샘플 코드를 git clone하거나 압축파일로 내려받습니다.

2-2 다운로드한 코드를 AWS Application Composer에서 확인해보겠습니다. 단계1과 같이 프로젝트를 생성하지만 이번에는 새 빈 프로젝트가 아니라 기존 프로젝트 로드를 선택하고 다운로드 받은 폴더의 template.yaml 파일을 클릭합니다.

2-3 샘플 코드의 구조를 확인합니다. 아키텍처 소개 섹션에 소개된 것처럼 Amazon API Gateway로 데이터가 입력되고 다른 구성 요소들과 연결되는 구조입니다.

2-2 소스 코드 항목 중 개인 환경에 맞게 수정해야되는 부분이 있습니다. VSCode, Vim등 IDE를 통해 코드 내용을 확인합니다.

2-3 첫번째 수정파일은 template.yaml 파일 입니다. 아래 항목 중 자신이 전달받을 이메일 도메인과 이메일 주소를 변경합니다.

Transform: AWS::Serverless-2016-10-31
Resources:
  SendItemInfo:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: SendItemInfo
      CodeUri: src/SendItem
      Handler: index.handler
      Runtime: nodejs16.x
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Environment:
        Variables:
          TOPIC_NAME: !GetAtt ItemTopic.TopicName
          TOPIC_ARN: !Ref ItemTopic
      Policies:
        - SNSPublishMessagePolicy:
            TopicName: !GetAtt ItemTopic.TopicName
      Events:
        ApiPOSTitem:
          Type: Api
          Properties:
            Path: /item
            Method: POST
            RestApiId: !Ref Api
  SendItemInfoLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${SendItemInfo}
  ItemTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !GetAtt ItemQueue.Arn
          Protocol: sqs
  ItemQueue:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 345600
  ItemTopicToItemQueuePermission:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: sns.amazonaws.com
            Action: sqs:SendMessage
            Resource: !GetAtt ItemQueue.Arn
            Condition:
              ArnEquals:
                aws:SourceArn: !Ref ItemTopic
      Queues:
        - !Ref ItemQueue
  StoreItemInfo:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: StoreItemInfo
      CodeUri: src/StoreInfo
      Handler: index.handler
      Runtime: nodejs16.x
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Events:
        ItemQueue:
          Type: SQS
          Properties:
            Queue: !GetAtt ItemQueue.Arn
            BatchSize: 1
      Environment:
        Variables:
          TABLE_NAME: !Ref ItemHistoryTable
          TABLE_ARN: !GetAtt ItemHistoryTable.Arn
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref ItemHistoryTable
  StoreItemInfoLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${StoreItemInfo}
  ItemHistoryTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
        - AttributeName: isolate
          AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: id
          KeyType: HASH
        - AttributeName: isolate
          KeyType: RANGE
      StreamSpecification:
        StreamViewType: NEW_AND_OLD_IMAGES
      TimeToLiveSpecification:
        AttributeName: expiration
        Enabled: true
  Api:
    Type: AWS::Serverless::Api
    Properties:
      Name: !Sub
        - ${ResourceName} From Stack ${AWS::StackName}
        - ResourceName: Api
      StageName: Prod
      DefinitionBody:
        openapi: '3.0'
        info: {}
        paths:
          /item:
            post:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SendItemInfo.Arn}/invocations
              responses: {}
      EndpointConfiguration: REGIONAL
      TracingEnabled: true
  SendMail:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: SendMail
      CodeUri: src/SendMail
      Handler: index.handler
      Runtime: nodejs16.x
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Events:
        ItemTopic:
          Type: SNS
          Properties:
            Topic: !Ref ItemTopic
            Region: !Select
              - 3
              - !Split
                - ':'
                - !Ref ItemTopic
      Policies:
        - SESCrudPolicy:
            IdentityName: amazon.com // 개인 이메일 도메인으로 변경
        - SESCrudPolicy:
            IdentityName: amazon@amazon.com // 개인 이메일 주소로 변경
  SendMailLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${SendMail}
  SendSlack:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: SendSlack
      CodeUri: src/SendSlack
      Handler: index.handler
      Runtime: nodejs16.x
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Events:
        ItemTopic:
          Type: SNS
          Properties:
            Topic: !Ref ItemTopic
            Region: !Select
              - 3
              - !Split
                - ':'
                - !Ref ItemTopic
  SendSlackLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${SendSlack}

2-4 Amazon SES 페이지에 접속한 후 개인 메일 주소를 등록합니다. 아쉽지만 아직 Amazon SES는 ApplicationComposer에서 사용할 수 없어 별도로 등록하는 과정이 필요합니다.

2-5 다운로드한 프로젝트 경로 SendMail → index.js 파일을 수정합니다. 코드 중 메일 주소 변경이라고 되어 있는 항목에 자신의 개인 이메일 주소를 입력합니다.

// Load the AWS SDK for Node.js
const AWS = require('aws-sdk');
AWS.config.update({region: 'us-east-1'});

const ses = new AWS.SES({ apiVersion: "2010-12-01" });

exports.handler = async (event) => {

  let message = event.Records[0].Sns.Message
  try {
    const params = {
      Destination: {
        ToAddresses: ["amazon@amazon.com"], // 메일 주소 변경
      },
      Message: {
        Body: {
          Html: {
            Charset: "UTF-8",
            Data: message,
          },
        },
        Subject: {
          Charset: "UTF-8",
          Data: "Special Price",
        },
      },
      Source: "amazon@amazon.com", // 메일 주소 변경
    };

    const { MessageId } = await ses.sendEmail(params).promise();

    return {
      statusCode: 200,
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ MessageId }),
    };
  } catch (error) {
    console.log(error.message);
    return {
      statusCode: 500,
      body: JSON.stringify({ message: "Error send email" })
    }
  }
}

2-6 다운로드한 프로젝트 경로 SendSlack → index.js 파일을 수정합니다. 개인의 Slack Webhook URL과 Workspace를 생성 후 개인 정보로 코드를 수정합니다. Slack Webhook URL을 생성 방법은 링크에서 확인하실 수 있습니다.

const https = require('https');

const doPost = (message) => {

  console.log(message)
// 본인 슬랙 정보로 변경 필요
  const data = {
    "channel": "#anycompany-slack",
    "username": "SpecialPrice_BOT",
    "text": message,
    "icon_emoji": ":sos:"
  };

  return new Promise((resolve, reject) => {
    const options = {
      host: 'hooks.slack.com',
      path: '/services/AWSAWSAWS', // 본인 슬랙 경로로 변경 필요
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      }
    };

    const req = https.request(options, (res) => {
      resolve(JSON.stringify(res.statusCode));
    });

    req.on('error', (e) => {
      reject(e.message);
    });
    
    req.write(JSON.stringify(data));

    req.end();
  });
};


exports.handler = async (event) => {
  let message = event.Records[0].Sns.Message
  await doPost(message)
    .then(result => console.log(`Status code: ${result}`))
    .catch(err => console.error(`Error doing the request for the event: ${JSON.stringify(event)} => ${err}`));
};

단계 3 : AWS Serverless Application Model 구성

3-1. AWS SAM CLI를 설치합니다.

3-2 터미널 창을 켜서 샘플 코드가 있는 경로로 이동 후 sam build 명령어 입력해서 빌드를 시작합니다.

$ sam build

3-3 빌드가 완료되면 아래와 같이 출력됩니다.

Running NodejsNpmBuilder:CleanUpNpmrc
Running NodejsNpmBuilder:LockfileCleanUp

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided
yeonuk@bcd0743a application_composer %

3-4 빌드가 완료되면 sam deploy —guided 명령어를 입력해서 배포를 시작합니다. 배포 중간에 나오는 Stack Name, AWS Region 등 설정은 아래 명령어와 동일하게 진행합니다. 특히 리전 정보는 코드에 이미 설정되어 있는 부분들이 있어 us-east-1로 설정하셔야 합니다.

$ sam deploy --guided

Configuring SAM deploy
======================

    Looking for config file [samconfig.toml] :  Not found

    Setting default arguments for 'sam deploy'
    =========================================
    Stack Name [sam-app]: price-alert
    AWS Region [ap-northeast-2]: us-east-1
    #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
    Confirm changes before deploy [y/N]: y
    #SAM needs permission to be able to create roles to connect to the resources in your template
    Allow SAM CLI IAM role creation [Y/n]: y
    #Preserves the state of previously provisioned resources when an operation fails
    Disable rollback [y/N]: n
    SendItemInfo may not have authorization defined, Is this okay? [y/N]: y
    Save arguments to configuration file [Y/n]: y
    SAM configuration file [samconfig.toml]:
    SAM configuration environment [default]:

    Looking for resources needed for deployment:

3-5 설정을 완료하면 어떤 리소스들이 추가될지 보여주는 화면이 나옵니다. Deploy this changeset? 항목에서 를 입력합니다.


CloudFormation stack changeset
-----------------------------------------------------------------------------------------------------------------------------------------------------
Operation                             LogicalResourceId                     ResourceType                          Replacement
-----------------------------------------------------------------------------------------------------------------------------------------------------
+ Add                                 ApiDeployment9ecf704443               AWS::ApiGateway::Deployment           N/A
+ Add                                 ApiProdStage                          AWS::ApiGateway::Stage                N/A
+ Add                                 Api                                   AWS::ApiGateway::RestApi              N/A
+ Add                                 ItemHistoryTable                      AWS::DynamoDB::Table                  N/A
+ Add                                 ItemQueue                             AWS::SQS::Queue                       N/A
+ Add                                 ItemTopicToItemQueuePermission        AWS::SQS::QueuePolicy                 N/A
+ Add                                 ItemTopic                             AWS::SNS::Topic                       N/A
+ Add                                 SendItemInfoApiPOSTitemPermissionPr   AWS::Lambda::Permission               N/A
                                      od
+ Add                                 SendItemInfoLogGroup                  AWS::Logs::LogGroup                   N/A
+ Add                                 SendItemInfoRole                      AWS::IAM::Role                        N/A
+ Add                                 SendItemInfo                          AWS::Lambda::Function                 N/A
+ Add                                 SendMailItemTopicPermission           AWS::Lambda::Permission               N/A
+ Add                                 SendMailItemTopic                     AWS::SNS::Subscription                N/A
+ Add                                 SendMailLogGroup                      AWS::Logs::LogGroup                   N/A
+ Add                                 SendMailRole                          AWS::IAM::Role                        N/A
+ Add                                 SendMail                              AWS::Lambda::Function                 N/A
+ Add                                 SendSlackItemTopicPermission          AWS::Lambda::Permission               N/A
+ Add                                 SendSlackItemTopic                    AWS::SNS::Subscription                N/A
+ Add                                 SendSlackLogGroup                     AWS::Logs::LogGroup                   N/A
+ Add                                 SendSlackRole                         AWS::IAM::Role                        N/A
+ Add                                 SendSlack                             AWS::Lambda::Function                 N/A
+ Add                                 StoreItemInfoItemQueue                AWS::Lambda::EventSourceMapping       N/A
+ Add                                 StoreItemInfoLogGroup                 AWS::Logs::LogGroup                   N/A
+ Add                                 StoreItemInfoRole                     AWS::IAM::Role                        N/A
+ Add                                 StoreItemInfo                         AWS::Lambda::Function                 N/A
-----------------------------------------------------------------------------------------------------------------------------------------------------


Changeset created successfully. arn:aws:cloudformation:us-east-1:018023422026:changeSet/samcli-deploy1682091194/4c4ec0bb-15b8-4c57-a618-6bc622c9e819


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

3-6 5분 정도 대기하면 리소스 배포가 완료되고 Successfully created/updated stack – price-alert in us-east-1 이라는 문구를 확인하실 수 있습니다. 만약 실패한다면 단계2부터 다시 진행 부탁드립니다.

CREATE_IN_PROGRESS                    AWS::ApiGateway::Deployment           ApiDeployment9ecf704443               Resource creation Initiated
CREATE_COMPLETE                       AWS::ApiGateway::Deployment           ApiDeployment9ecf704443               -
CREATE_IN_PROGRESS                    AWS::ApiGateway::Stage                ApiProdStage                          -
CREATE_IN_PROGRESS                    AWS::ApiGateway::Stage                ApiProdStage                          Resource creation Initiated
CREATE_COMPLETE                       AWS::ApiGateway::Stage                ApiProdStage                          -
CREATE_COMPLETE                       AWS::Lambda::Permission               SendItemInfoApiPOSTitemPermissionPr   -
                                                                            od
CREATE_COMPLETE                       AWS::CloudFormation::Stack            price-alert                           -
-----------------------------------------------------------------------------------------------------------------------------------------------------


Successfully created/updated stack - price-alert in us-east-1

단계 4 : 동작 확인

4-1 Amazon API Gateway 콘솔 페이지에 접속해서 만들어진 API를 확인합니다.

4-2 생성된 API를 클릭하고 화면 왼쪽 스테이지 버튼을 클릭합니다. 그리고 Prod → / → /item → POST 를 차례로 클릭해서 /item의 URL 경로를 확인합니다.

4-3 Postman이나 Curl등 API 호출 도구를 이용해서 /item 경로 URL을 Post 방식으로 호출합니다.

Body에 들어가는 항목은 아래와 동일하게 입력합니다. 타임 세일! 치킨 1마리 9900원!은 원하는 대로 변경할 수 있고 message는 수정하실 경우 코드도 같이 수정해야합니다.

{
  "message": "타임 세일! 치킨 1마리 9900원!"
}

4-4 /item 경로 호출 후 각 기능을 확인합니다. 가장 먼저 Slack으로 알림 메세지가 오는지 확인합니다.

4-5 이메일로 알람 메시지가 오는지 확인합니다.

4-6 Amazon DynamoDB 페이지에서 알람 정보가  제대로 들어있는지 확인합니다.

리소스 삭제

리소스 삭제의 경우 생성 방법과 동일하게 터미널 창에서 프로젝트에 경로로 이동 후 sam delete region us-east-1 명령어를 입력합니다. 뒤이어 나오는 항목들도 아래와 동일하게 입력합니다. Deleted successfully 문구가 나오면 정상적으로 삭제 완료된 상황입니다.

$ sam delete --region us-east-1
    Are you sure you want to delete the stack price-alert in the region us-east-1 ? [y/N]:  y
    Are you sure you want to delete the folder price-alert in S3 which contains the artifacts? [y/N]: y
    - Deleting S3 object with key price-alert/74e34d23b3d0a443150fc2808f577b94
    - Deleting S3 object with key price-alert/7ff274a4dda558f31e31783d09aaa79c
    - Deleting S3 object with key price-alert/36a64026e685303d7f04f42931aaa41f
    - Deleting S3 object with key price-alert/cb016c36084a296ce60e00b1e31c891e
    - Deleting S3 object with key price-alert/4711b84605d088b51b97c1bf7df12f0a.template
    - Deleting Cloudformation stack price-alert

Deleted successfully

결론

이 글에서는 AWS Application Composer와 AWS SAM을 사용하여 간단한 서버리스 알람 서비스를 구성해 봤습니다. 그리고 실제 구성한 서비스의 동작을 확인해 보면서 실무에 적용할 수 있는 방법을 알아보았습니다. 서비스에 새로운 기능을 개발 중이시라면 AWS Application Composer를 도입을 추천합니다. 시각적으로 아키텍처를 디자인할 수 있고 팀원간 공유가 간편합니다. 또한 AWS Application Composer로 만들 수 있는 다른 아키텍처들이 궁금하시다면 AWS의 여러 서버리스 관련 정보를 모아놓은 서버리스 랜드에서 확인 가능합니다.

참고자료

Yeonuk Lim

Yeonuk Lim

임연욱 솔루션즈 아키텍트는 Software 개발 경험을 바탕으로 현재는 엔터프라이즈 고객들의 기술 역량 강화와 클라우드 도입 검토 지원, 클라우드 시스템 설계 등의 업무를 수행하고 있습니다. 또한 AWS의 서버리스 기술을 전파하는 역할도 담당하고 있습니다.

Hyunsoo Cho

Hyunsoo Cho

조현수 솔루션즈 아키텍트는 이커머스/금융/SaaS 산업군에서 소프트웨어 개발자 경험을 바탕으로 디지털 기업의 다양한 요구사항에 적합한 아키텍처를 설계하고, AWS 기반의 제품과 서비스 개발에 도움을 주는 역할을 수행하고 있습니다.

Yongzhe Ren

Yongzhe Ren

렌(Yongzhe Ren) 솔루션즈 아키텍트는 다양한 분야의 엔지니어 경험을 바탕으로, 고객의 비즈니스 성과를 달성하도록 최적의 아키텍처를 구성하는 역할을 수행하고 있습니다.