AWS

[AWS] aws 강의 섹션 28 (Step Function, AppSync, Amplify)

대기업 가고 싶은 공돌이 2024. 12. 5. 19:55

AWS Step Functions

  • 스텝 펑션은 특정 워크 플로우를 설계하고 해당 워크 플로우를 aws의 리소스와 연결시켜
    자동으로 워크 플로우를 실행하도록 도와주는 도구다.
  • 한 워크플로우 당 한 개의 상태 관리 머신이 할당 될 수 있다.

예시: 이미지 처리 워크플로우

  1. 이미지를 S3에 업로드.
  2. 업로드된 이미지를 Lambda로 처리 (크기 변경, 필터 적용 등).
  3. 처리된 이미지를 S3에 저장.
  4. 처리가 완료되었다는 알림을 사용자에게 보냄.

이러한 워크 플로우를 정의하고 워크 플로우대로 리소스를 실행 시키도록 도와준다.

 

  • Json으로 작성된다.
  • 워크 플로우를 시각화해서 시각적으로 수행이 어디까지 진행되는지 확인할 수 있다.

  • 스텝 펑션의 시작은 SDK 호출, API 게이트웨이, 이벤트 브릿지 등등으로 시작할 수 있다.

Step Function - Task States

  • 위 사진의 네모칸을 Task라고 한다.
  • 태스크 상태란 말 그대로 특정 태스크를 설계하는 작업이다.
    • 예를 들어, 람다 펑션을 호출하는 작업을 설계하려 한다면
      호출할 리소스의 이름을 정의하고
    • 해당 작업이 어느 정도 시간이 흐르면 실패로 간주하고
    • 해당 작업이 성공하면 어떤 작업을 호출할지
    • 실패하면 어떤 작업을 할지 정의하는 것이 태스크 상태이다.
  • 이 모든 것들을 태스크 상태에서 정의할 수 있다. 
  • 한 번에 한 가지 일만 수행한다.
    • EC2나 ECS, 온 프레미스 서버에서 활동을 수행한다.
    • 외부 작업으로부터, 할 일을 받아오기 위해 풀을 시도한다.
    • 활동을 다 마치고 나서 결과물을 다시 스텝 펑션에 되돌려 주는 식으로 진행된다.

이 모든 것은 Json으로 정의된다.

 

Example - invoke Lambda Function

  • 유형은 태스크이며
  • 리소스는 람다 함수 호출이다.
  • 매개변수로 함수 이름이 있는데, 함수 이름을 지정하고 람다 함수에 페이로드를 입력값으로 전달한다.
  • 이후 다음 태스크 state로 넘어가라는 명령과
  • 시간초과는 300초를 준다고 정의돼 있다.

Step Function - States

1. choice State

  • 조건을 테스트하여 특정 분기로 보낼지 또는 기본 분기로 보낼지 결정하는 상태이다.
    • :
      "사용자가 VIP인가요?" →
      • VIP면 A 분기로 이동.
      • VIP가 아니면 기본(Default) 분기로 이동.

2. Fail or Succed State

  • 워크플로우를 성공(Success) 또는 **실패(Fail)**로 종료시키는 상태이다.
    • Fail State: 오류가 발생했거나 작업을 중단해야 할 때 사용.
    • Succeed State: 모든 작업이 성공적으로 끝났음을 알림.
    • :
      • 결제 실패 시 → Fail State로 종료.
      • 주문이 완료되면 → Succeed State로 종료.

3. Pass State

  • 입력값을 출력값으로 그대로 전달하거나 고정된 데이터를 삽입하는 상태이다. 작업을 기다리지 않고 바로 다음 단계로 넘어간다.
    • :
      "기본 메시지를 추가로 삽입" → {"message": "작업 시작"}와 같은 데이터를 전달.

4. Wait State

  • 특정 시간만큼 대기하거나, 특정 날짜/시간까지 대기하는 상태이다.
    • :
      • "5초 동안 대기".
      • "2024년 12월 31일까지 대기".

5. Map State

  • 특정 단계를 동적으로 반복 실행하는 상태입니다. 주로 배열 데이터를 처리할 때 사용된다.
    • :
      • 고객 리스트를 순회하며 각각의 고객에게 이메일 전송.
      • 반복적으로 작업 실행(예: 여러 파일 처리).

6. Parallel State

  • 여러 작업을 병렬로 실행하는 상태입니다. 각 분기가 독립적으로 실행된다.
    • :
      • 동시에 "이미지 처리"와 "동영상 처리"를 실행.
      • 분리된 데이터 작업을 병렬로 처리.

 Step Functions - Error Handling

  • 오류는 언제 일어날까? 상태 머신의 정의에 문제가 있을 수 있다. 
  • 또는 람다 함수가 예외 처리하여 태스크가 실패할 때도 오류가 일어난다.
  • step functions의 오류 처리 매커니즘을 캐치해야 한다.
  • 또는 네투워크 파티션 이벤트와 같은 일시적인 실패가 있다.
  • 오류를 처리하는 방법은 두 가지가 있다.
    1. 태스크를 재시도하는 것
    2. 오류를 Catch 했을 때 실행할 코드를 실행
  • 이러한 오류 처리는 상태 머신 내부가 아닌 외부에서 핸들링 해야한다.
  • 상태 머신 내부는 최대한 간단하게 만들어야 한다.

Step Functions - Error Handling, Error Codes

사전에 정의돼 있는 에러 코드들이다.

  • States.ALL: 모든 종류의 에러와 매칭된다.
  • States.TimeOut: 시간 초과 오류와 매칭된다.
  • States.TaskFailed: 태스크의 실행 중 실패할 때 매칭된다.
    • 예를 들어 코드 내부에서 예외를 throw 하는 상황이 있겠다.
  • State.Permissions: 어떤 코드를 실행할 권한이 충분치 않은 경우에 매칭된다.

Step Functions - Retry (Task or Parallel State)

  • Retry에는 오류를 기반으로 재시도할 작업 및 횟수를 정의할 수 있다.
  • ErrorEquals는 특정 오류와 매칭한다.
  • IntervalSeconds: 재시도 전에 얼마나 오래 대기해야 하는지를 표시한다.
    • 1이면 1초 후에 재시도 한다.
  • BackoffRate: 재시도 후의 지연을 곱한다.
    • 지수 백오프를 구현하기 위함이다.
  • MaxAttempts: 재시도의 횟수를 정의한다. 기본 값은 3이고 0일 경우 재시도를 하지 않는다.
  • 람다 함수 내에 Catch 문을 정의할 경우 태스크 실행에 오랜 시간이 걸리고 시간 초과가 될 수 있다.
    • 그러니 예외 처리는 람다함수 외부인 Step Fubctions에서 정의하도록 하자.

모든 재시도가 끝나면 Catch문으로 이동하게 된다.

Step functions - Catch

  • ErrorEquals: 위 설명과 동일하다.
  • Next: 다음으로 이동할 State를 정의한다.
    • 위 예시에서 첫 번째에 Next가 CustomErrorFallback으로 정의돼 있다.
      이는 맨 마지막에 정의된 CustomErrorFallback으로 이동하게 된다.
    • 재시도 단계에서 재시도를 충분하게 수행하고 만약 통과하지 못 했을 경우
      이곳 Catch에 들어와 다음 상태로 넘어가서 무언가를 수행하라고 정의하는 곳이다.
  • ResultPath: 다음 필드를 지정하는 것으로 전송되는 입력값의 경로를 결정한다.

Step Functions - ResultPath

  • 아까 본 resultPath에 대해서 더 자세하게 살펴보자

  • ResultPath는 $.error이다. 
  • 기본적으로 step Function은 에러가 발생한다면 아웃풋 값에 인풋 값을 내보낸다고한다.
  • 여기서 result Path는 아웃풋 값에 에러에 대한 정보를 포함시키는 변수 명을 정의하는 것이다.
  • 현재 예시에서 Result Path는 $.error이다. 그렇다면 인풋값이 {foo : bar} 일 때 에러가 발생한다면
    아웃풋은 어떻게 나올까?

  • 다음과 같이 아웃풋 값의 error 필드에 에러에 대한 정보가 담긴 것을 확인할 수 있다.
  • 여기 담긴 에러 메시지를 통해 에러를 분석할 수 있다.

Step functions - Wait for Task Token

 

  • Task Token 생성:
    Step Function의 특정 단계에서 Task Token이라는 고유한 식별자를 생성한다.
    이 토큰은 외부 시스템이나 사용자에게 전달된다.
  • 외부 작업 요청:
    외부 시스템(예: 다른 서비스나 사용자)이 이 토큰을 사용해 작업을 완료하고 Step Function으로 결과를 다시 보낸다.
  • 토큰 수신:
    외부에서 토큰과 결과 데이터를 반환하면 Step Function은 다음 단계로 진행한다.
    반대로, 일정 시간 안에 토큰이 반환되지 않으면 오류가 발생하거나 타임아웃 처리된다.

이러한 기능은 비동기 작업이나 사용자 승인 프로세스를 처리하는 데 유용하다.

토큰을 활용해서 외부에서 작업을 실시하고 토큰이 다시 반환되면 나머지 스텝을 진행하는 방식이다.

 

  • step functions의 태스크에서 리소스 필드에 .waitFortaskToken을 추가하면 실행을 계속하기 전에
    특정 태스크 토큰이 반환될 때가지 대기하도록 Step Functions에 알려줄 수 있다.

  • 이 경우, sqs:sendMessage라는 리소스에 .waitForTaskToken을 붙였는데
    모두 제대로 작동될 경우 sendTaskSuccess가 아닌 경우엔 SendTaskFailure Api를 호출하여 
    태스크 토큰이 반환될 때까지 태스크가 일시 중지된다.

  • 맨 처음 SQS를 호출한다 당연히 SQS를 호출할 때 바디에는 인풋값과 토큰 값이 담겨있어야 한다.
  • 이후 SQS가 작업을 마치고 SendTaskSuccess API를 호출하는데 반환값에는
    태스크 토큰이 포함되어 있어야 한다.
  • 이러한 흐름으로 람다 ECS, 써드 파티 애플리케이션 모든 곳에 활용이 가능하다.
  • 토큰값이 멀쩡하다면, 나머지 스텝을 이어나간다.

이 방식의 장점은 외부 매커니즘과 손쉽게 통합할 수 있다는 것이다. 

 

Step Functions - Activity Tasks

Activity Tasks는 바로 위의 WaitForTaskToken과 작동 방식이 거의 동일하다.

외부 어플리케이션을 호출하여 작업을 수행한 후에 다음 Step으로 넘어가는 방식이다.

 

  • Activity 등록:
    • 사용자가 Step Function에 Activity를 등록한다.
    • Activity는 외부에서 처리할 작업을 정의한 이름 같은 역할을 한다.
  • Step Function에서 Activity 호출:
    • Step Function 워크플로우가 실행되면 Activity Task 단계에서 작업 요청이 생성된다.
  • 작업 대기:
    • 외부 애플리케이션(예: 서버, 서비스 등)이 **"Poll"**을 통해 Step Function에서 처리해야 할 작업 요청을 확인한다.
    • GetActivityTask API를 통해 작업을 풀 해간다.
  • 외부에서 작업 수행:
    • 외부 애플리케이션이 작업을 처리하고 결과를 Step Function으로 반환한다.
    • 토큰을 반환할 때와 동일하게, SendTaskSuccess와 SendTaskFailure API를 사용해서
      응답을 보낸다.
  • 워크플로우 진행:
    • Step Function은 반환된 결과를 받아 다음 단계로 진행한다.

 

토큰과의 차이점

  • EC2 인스턴스나 그 빡의 애플리케이션들이 Step Functions에서 특정 작업을 폴링하므로, 
    EC2 인스턴스가 Step Functions에 연결할 수만 있으면 되기 때문에 작업이 더 수월하다.

추가로 고려해야할 점

  • TimeOutSeconds와 HeartBeatSeconds다
  • TimeOutSeconds는 당연히 작업이 수행되는데 기다리는 시간이고,
    HeartBeatSeconds는 상태 확인이다.
  • 상태확인이 멀쩡하게 지속된다면, 최대 1년까지 대기를 할 수 있다고 한다.

Step Functions - Standard VS Express

  • step function 워크 플로우를 실행하는 방법에는 두 가지가 있는데
  • 첫 번째는 기본값으로 설정돼있는 Standard를 사용하는 것이고 
  • 두 번째는 Express 방식이다.
    • Express 워크 플로우에는 비동기식 워크플로우와 동기식 워크플로우가 존재한다.

각 방식의 특징

  • Standard 워크 플로우의 특징
    • 최대 실행 시간: 1년
    • 실행 모델: 중복없이 정확하게 1회 실행 보장
    • 속도: 초당 약 2,000개의 표준 워크 플로우를 실행할 수 있다.
    • 실행 기록: 최대 90일까지의 기록이 보관되며 CloudWatch를 사용하여, 더 많은 로그를 보거나
      로그 보존 설정을 통해 로그를 영구 보관할 수도 있다.
    • 비용: 다른 State로 변환하는 횟수에 따라 비용이 책정된다.
    • 사용 케이스: 비 멱등성 작업에 사용된다. (결제 처리하는 요청)
  • Express 워크 플로우  특징
    • 최대 실행 시간: 5분
    • 속도: 초당 최대 100,000개
    • 실행 기록: 기록을 추적할 수 없다
      • cloudwatch 로그를 통해서만 실행 결과와 분석 자료를 얻을 수 있다.
    • 비용: 실행 횟수, 실행 기간, 메모리 사용량에 따라 청구된다.
    • 사용 케이스: iot 데이터 수집, 스트리밍 데이터 처리, 모바일 앱 백엔드 등에 사용된다.
    • 동기 비동기 차이점
      • 비동기식은 최소 1회 실행 보장
      • 동기식은 최대 1회 실행 모델
    • 비동기식은 같은 작업이 두 번 실행될 수도 있다 따라서 이경우 같은 동작이 2회 실행될 때
      동일한 효과가 두 번 발생하지 않도록 중요도를 관리해야 한다.

AWS AppSync

  • GraphQL을 관리하는 서비스이다
    • 만약 GraphQL API를 AWS에 구축하려면, AppSync만 알면 된다.

 

그렇다면 GraphQL은 무엇일까?

특징을 간단히 살펴보자

 

  • 필요한 데이터만 요청하기
    • GraphQL에서는 필요한 데이터만 요청할 수 있다.
    • 예를 들어, 사용자 정보 API에서 이름(name)과 이메일(email)만 필요한 경우, 그것만 요청해서 받을 수 있다.
    • REST API에서는 불필요한 데이터를 포함한 전체 응답을 받는 경우가 많지만, GraphQL은 이를 해결해 준다.
  • 단일 엔드포인트
    • REST API에서는 각각의 데이터에 대해 여러 URL(엔드포인트)이 필요하다.
    • GraphQL에서는 모든 요청을 하나의 URL로 처리한다.
    • 서버에 쿼리를 보내 필요한 데이터를 한 번에 가져올 수 있다.
  • 요청과 응답 구조가 유연
    • 요청 시 데이터를 **쿼리(Query)**로 작성하며, JSON 형식으로 응답을 받는다.
    • 클라이언트가 원하는 구조로 데이터를 요청할 수 있어 불필요한 데이터 전송이 줄어든다.
  • 서버와 클라이언트 간의 데이터 협업 강화
    • 클라이언트가 요청한 데이터만 반환하기 때문에 클라이언트와 서버 간의 통신 효율이 높아진다.

다시 AppSync로 넘어오자

  • Appsync의 GraphQL은 다이나모 디비, 오로라, 엘라스틱 서치 등등의 소스와 통합되고 
    어디서든 데이터를 가져올 수 있다.
  • AWS Lambda로 패턴을 확장할 수 있다.
  • appsync는 Websocket과 연결하여 실시간으로 데이터를 주고받을 수 있다.
  • 모바일 환경에서 로컬 데이터와 연결하고, 실시간으로 데이터를 동기화 시켜야한다.
    appsync는 cognitosync를 대체해서 그러한 작업을 해줄 수 있다. 
  • 마지막으로 appSync를 시작하려면 1개의 GraphQL 스키마를 업로드 해야한다.

뭔가 좀 이해하기 어려운데 정리하자면,

  • GraphQL API를 기반으로 여러 데이터 소스를 통합하는 서비스다.
  • 위에서 예시로 든 모든 데이터베이스 서비스를 다 연결 시켜 GraphQL 쿼리로 한 번에 데이터를
    다 가져올 수 있다.
  • 심지어 오프라인 상황에서도 응답을 받아 저장해둔 후에, 나중에 동기화 시켜 한번에 요청을 처리할 수도 있다고 한다.

GraphQL example

  • AppSync를 시작하기 위해 GraphQL 스키마를 생성해야 한다.

  • 맨 왼쪽은 스키마다.
  • 오른쪽 위는 쿼리문을 보내는 것이고
  • 해당 쿼리가 도착하면 리솔버를 통해 특정 데이터베이스에서 결과값을 가져온다.
  • 이후 결과값을 JSON형식으로 반환한다.

AppSync - Security

  • Appsync GraphQL API와 통신할 수 있게 해주는 방법은 네 가지가 있다.
    1. API_KEY: 키를 생성하고 해당 키를 이용해 접근한다.
    2. AWS_IAM: IAM 사용자, ROLE, cross-account access등을 설정해서 사용할 수 있다.
    3. OPENID_CONNECT: openid 커넥트 공급자와 JSON WEB TOKEN을 통합한다.
    4. AMAZON_COGNITO_USER_POOLS:  아이디 비밀번호를 통해 로그인 하여 사용자 풀에서 사용자 정보를 가져온다.
  • 마지막으로 HTTPS 보안을 원한다면 AppSync앞에 CloudFront를 붙이는 것을 추천한다고 한다.

AWS Amplify - create mobile and web application

  • 모바일과 웹 어플리케이션을 구축할 수 있게 해주는 서비스로 여러 가지의 하위 서비스로 구성돼있다.
    1. Amplify Studio: 프론트와 백 모두에서 앱을 시각적으로 구축할 수 있도록 해주는 서비스다.
    2. Amplify CLI: 작업을 CLI로 수행할 수 있게 해준다.
    3. Amplify Libraries: 로그인을 위한 Cognito나 스토리지를 위한 S3같은 기존의 서비스와 연결 시켜준다.
    4. Amplify Hosting: 애플리케이션을 호스팅하여 아주 빠르게 전달한다.

AWS Amplify

  • 모바일 및 웹 애플리케이션 개발을 시작하기 위한 셋업 툴이다. 
  • 모바일 및 웹 애플리케이션을 위한 Elastic Beanstalk이라고 보면 된다.
  • Amplify는 데이터 저장, 인증 , 파일 저장 및 머신러닝과 같은 기술을
    제공하는데 모두 AWS 서비스를 기반으로 한다.
  • 백엔드의 경우 다음과 같은 라이브러리를 제공한다.

 

  • 프론트엔드 라이브러리도 제공한다.

 

  • Amplify는 이 모든 것을 사용할 수 있게 도와주며
    안정성과 보안, 확장성에 대한 모범 사례를 준수하여 만들어졌다.

AWS Amplify - Important Features

  • Authentication: 별도의 설치 없이 즉시 사용 가능한 인증 기능을 제공한다.
    • amplify add auth 명령어를 사용해서 AWS Cognito를 활용해 
      사용자 등록, 인증, 계정 복구 등의 작업을 수행할 수 있고
      MFA, 소셜 로그인 등을 지원하며
    • 프론트 엔드에서 이를 빌드하고 Cognito와 통합할 수 있도록 사전 구축 컴포넌트를 제공하고
      권한도 세분화 하여 부여할 수 있다.
  • Data Store
    • amplify add api 명령어를 사용해서 API에는 Appsync 데이터 저장소에는 DynamoDB를 사용하게 된다.
    • 데이터 스토어를 통해 데이터와 로컬 데이터로 작업한 다음, 복잡한 코드 없이 클라우드에 자동으로 
      동기화 할 수 있다.
    • GraphQL과 Appsync를 기반으로 한다.
    • 실시간으로 사용할 수 있으며, Amplify 스튜디오로 데이터 모델링도 가능하다. 

AWS Amplify - Hostiong

  • 애플리케이션을 배포하고자 할 때 사용하는 서비스다.
  • amplify add hosting 명령어를 사용하면 최신 웹 앱을 빌드하고 호스팅할 수 있고, 
    빌드, 테스트, 배포와 같은 CI/CD 프로세스를 수행하며 
    풀 리퀘스트 미리 보기, 사용자 지정 도메인 생성, 모니터링을 수행하고
  • 리디렉션, 사용자 지정 헤더, 암호 보호 등을 설정할 수 있다고 한다.
  • Netlify, vercel amplify 같은 서비스와 비슷하다고 한다.
  • 코드 저장소에서 코드를 받으면 CI/CD 프로세스가 프론트엔드를 구축한 다음, 
    클라우드 프론트 같은 곳에 배포한다.
  • 마찬가지로 CI/CD 프로세스를 통해 백엔드를 선택적으로 구축하고 
    amplify에 백엔드를 배포할 수도 있다.

AWS Amplify - End to End Testing

  • 선택적으로 테스트를 실행할 수 있으며 단위 테스트와 종단간 테스트라는 
    두 가지 유형의 테스트가 있는데 Amplify의 테스트 단계에서는 종단간 테스트를 실행한다고 한다.
    • 이 테스트의 목표는 코드를 프로덕션으로 푸시하기 전에 regressions을 포착할 수 있도록 하는 것이다.
    • 테스트 단계를 사용해서 빌드 과정 중 테스트 명령을 실행하고
      amplify.yml 파일에서 테스트 단계를 정의한 다음, Cypress 테스트 프레임워크를 사용해 테스트를 생성할 수 있다고 한다.
      • 배포를 한 후에 엔드 유저가 직접 실행을 해보고 앱이 예상대로 작동하는지를 테스트하는 방식이라 보면 된다.