여러 단계의 주문 워크플로 구축

AWSBeginner
지금 연습하기

소개

주문 이행은 주문을 저장한 다음 완료된 요약을 읽어야 합니다. 이 작업들을 워크플로로 연결하고 실행 기록을 실제 비즈니스 결과와 비교합니다.

Lambda에서 DynamoDB 읽기 및 쓰기와 해당 실습의 IAM 역할 및 로깅 선행 실습을 먼저 완료하세요. 이 독립적인 VM에는 작업자와 테이블이 제공됩니다. 워크플로는 직접 만듭니다. EventBridge 라우팅은 별도의 학습 갈래입니다.

인증 시험 관련 주제

이 실습은 다음 시험 주제에 대한 실습 경험을 제공합니다.

워크플로에 작업자 호출 권한 부여

이 단계에서는 제공된 비즈니스 작업자를 확인하고 Step Functions를 위한 별도의 실행 역할을 만듭니다.

워크플로와 작업자 권한

워크플로 역할은 함수를 호출합니다. 별도의 Lambda 역할은 테이블 작업을 수행합니다.

Terminal 옆에서 AWS View를 사용하여 CLI 쿼리를 이 실습의 실제 리소스 및 결과와 비교하세요. 제공된 참조 데이터를 유지하세요.

워크플로는 작업과 결정을 연결합니다. 상태 머신은 해당 상태들을 정의하고 실행은 특정 입력으로 정의를 실행합니다. 이 새 VM에는 작업자 함수와 독립적인 주문/진단/참조 테이블이 제공됩니다. 아직 상태 머신이나 워크플로 역할은 없습니다. 작업자는 주문을 받고 수량과 합계를 쓰며 나중에 요약을 읽을 수 있습니다. Lambda 실행 역할에는 이미 이러한 별도의 테이블 작업 권한이 있습니다.

프로젝트 디렉터리에서 시작하세요. 셸 할당은 반환된 식별자를 저장하고 --query는 응답 필드를 선택하며 --output text는 재사용할 수 있는 문자열을 생성합니다.

cd /home/labex/project
WORKER_NAME=labex-ev03-worker
WORKER_ARN=$(aws lambda get-function-configuration \
  --function-name labex-ev03-worker \
  --query FunctionArn \
  --output text)
aws lambda get-function-configuration \
  --function-name labex-ev03-worker \
  --query '{Name:FunctionName,Role:Role,Runtime:Runtime,Timeout:Timeout}'
aws stepfunctions list-state-machines

작업자는 Python3.12와 자체 Lambda 역할을 사용하며 머신 목록은 비어 있습니다. Step Functions에는 자체 실행 역할이 필요합니다. 신뢰 정책은 Step Functions 서비스가 해당 역할을 맡도록 허용하고 권한 정책은 생성된 세션이 정확히 이 작업자를 호출하도록 허용합니다. 따옴표가 있는 here-document는 리터럴 JSON을 쓰고 file://는 이를 요청으로 읽습니다.

cat > workflow-trust.json <<'JSON'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "states.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
JSON
ROLE_ARN=$(aws iam create-role \
  --role-name labex-ev03-workflow-role \
  --assume-role-policy-document file://workflow-trust.json \
  --query Role.Arn \
  --output text)

일반 권한 문서를 작성하세요. 셸은 $WORKER_ARN을 넣어 이 권한을 제공된 작업자로 제한합니다.

cat > workflow-invoke.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "lambda:InvokeFunction",
      "Resource": "$WORKER_ARN"
    }
  ]
}
EOF
aws iam put-role-policy \
  --role-name labex-ev03-workflow-role \
  --policy-name InvokeWorker \
  --policy-document file://workflow-invoke.json
aws iam get-role-policy --role-name labex-ev03-workflow-role --policy-name InvokeWorker

정책에는 정확한 함수 ARN 하나가 있습니다. Step Functions는 작업자의 DynamoDB 권한을 받지 않습니다. 작업자는 별도의 Lambda 역할로 해당 호출을 수행합니다. 권한 부여 검사를 실행하세요.

결정과 두 실제 작업 정의

이 단계에서는 수량을 검증하고 주문을 저장하며 실제 요약을 읽는 주문 워크플로를 정의합니다.

입력, 저장된 결과와 요약

StoreOrder는 실제 페이로드를 saved.result 아래에 저장합니다. ReadSummary는 해당 주문 ID를 선택하고 완료된 요약을 읽습니다.

**Amazon States Language (ASL)**는 JSON 상태 머신 정의입니다. StartAt은 첫 상태를 선택합니다. Choice는 조건이 일치하면 한 갈래를 따르고 그렇지 않으면 Default를 따릅니다. Task는 서비스를 호출합니다. Next는 상태를 연결하고 End: true는 성공으로 종료하며 Fail은 오류로 종료합니다.

최적화된 Lambda 작업 통합은 arn:aws:states:::lambda:invoke를 사용합니다. Parameters는 함수 인수를 제공합니다. .$로 끝나는 키는 JSONPath를 평가하고 $는 현재 전체 입력을 선택합니다. Lambda 통합은 메타데이터와 Payload를 반환합니다. ResultSelector는 해당 페이로드만 유지하고 ResultPath는 원래 주문 입력을 유지하면서 이를 saved 아래에 넣습니다. 다음 작업은 저장된 주문 ID를 선택합니다. 해당 작업의 OutputPath는 실제 요약 페이로드만 반환합니다.

리터럴 정의를 작성한 다음 jq --arg로 작업자 자리 표시자를 교체하세요.

cat > workflow-template.json <<'JSON'
{
  "StartAt": "CheckQuantity",
  "States": {
    "CheckQuantity": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.quantity",
          "NumericGreaterThan": 0,
          "Next": "StoreOrder"
        }
      ],
      "Default": "Rejected"
    },
    "StoreOrder": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "WORKER_NAME",
        "Payload.$": "$"
      },
      "ResultSelector": {
        "result.$": "$.Payload"
      },
      "ResultPath": "$.saved",
      "Next": "ReadSummary"
    },
    "ReadSummary": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "WORKER_NAME",
        "Payload": {
          "stage": "summary",
          "id.$": "$.saved.result.id"
        }
      },
      "OutputPath": "$.Payload",
      "End": true
    },
    "Rejected": {
      "Type": "Fail",
      "Error": "OrderRejected",
      "Cause": "Quantity must be positive"
    }
  }
}
JSON
jq --arg worker "$WORKER_NAME" '.States.StoreOrder.Parameters.FunctionName=$worker | .States.ReadSummary.Parameters.FunctionName=$worker' workflow-template.json > workflow.json
MACHINE_ARN=$(aws stepfunctions create-state-machine \
  --name labex-ev03-orders \
  --type STANDARD \
  --role-arn "$ROLE_ARN" \
  --definition file://workflow.json \
  --query stateMachineArn \
  --output text)
aws stepfunctions describe-state-machine \
  --state-machine-arn "$MACHINE_ARN" \
  --query '{Name:name,Role:roleArn,Definition:definition}'

응답은 머신과 워크플로 역할을 지정하고 정의는 두 작업 모두에서 제공된 작업자를 지정합니다. 아직 주문은 처리되지 않았습니다. Terminal 옆의 AWS View를 클릭하여 실제 머신 정의와 빈 실행/주문 목록을 보세요. 정의 검사를 실행하세요.

비즈니스 결과와 거부된 실행 검증

이 단계에서는 유효한 주문, 잘못된 수량과 호출 권한이 없는 실행을 수행합니다.

start-execution은 비동기 작업을 시작하고 실행 ARN을 반환합니다. 다음 횟수가 제한된 셸 루프는 실행 중 상태가 끝날 때까지 2초마다 상태를 읽습니다. $(...)는 명령 출력을 저장하고 seq는 루프 횟수를 제공하며 break는 조건이 일치하면 루프를 종료합니다. 루프 이후에도 RUNNING이면 진행하기 전에 서비스를 확인하세요.

EXECUTION_ARN=$(aws stepfunctions start-execution \
  --state-machine-arn "$MACHINE_ARN" \
  --name valid-order \
  --input '{"id":"workflow-order","quantity":3}' \
  --query executionArn \
  --output text)
for attempt in $(seq 1 60); do
  STATUS=$(aws stepfunctions describe-execution \
    --execution-arn "$EXECUTION_ARN" \
    --query status \
    --output text)
  if test "$STATUS" != RUNNING; then break; fi
  sleep 2
done
aws stepfunctions describe-execution \
  --execution-arn "$EXECUTION_ARN" \
  --query '{Status:status,Output:output}'
aws stepfunctions get-execution-history \
  --execution-arn "$EXECUTION_ARN" \
  --query 'events[].type'
aws dynamodb get-item \
  --table-name labex-ev03-orders \
  --key '{"id":{"S":"workflow-order"}}' \
  --query Item

공식 Step Functions Console 실행 목록 예시

공식 Console은 실행 이름과 상태를 시간 정보와 함께 나열합니다. 이름과 워크플로는 이 실습의 Standard 머신과 다릅니다. CLI 상태를 기록 및 저장된 데이터와 비교하세요. 이 실습 결과에는 AWS View를 사용하세요.

출처: AWS Step Functions.

상태는 SUCCEEDED이며 출력에는 주문 ID, total_cents:850, completed:true가 포함됩니다. 실제 DynamoDB 항목의 수량은 3, 합계는 850입니다. 기록에는 주문 저장과 요약 읽기에 해당하는 TaskSucceeded 이벤트 두 개가 있습니다. 실행 상태만으로 비즈니스 결과를 증명할 수는 없습니다. 둘 다 비교하세요.

수량 0으로 Choice 갈래를 테스트하세요.

INVALID_ARN=$(aws stepfunctions start-execution \
  --state-machine-arn "$MACHINE_ARN" \
  --name invalid-order \
  --input '{"id":"invalid-order","quantity":0}' \
  --query executionArn \
  --output text)
for attempt in $(seq 1 30); do
  STATUS=$(aws stepfunctions describe-execution \
    --execution-arn "$INVALID_ARN" \
    --query status \
    --output text)
  if test "$STATUS" != RUNNING; then break; fi
  sleep 2
done
aws stepfunctions describe-execution \
  --execution-arn "$INVALID_ARN" \
  --query '{Status:status,Error:error}'
aws dynamodb get-item \
  --table-name labex-ev03-orders \
  --key '{"id":{"S":"invalid-order"}}' \
  --query Item

상태는 OrderRejected와 함께 FAILED이며 invalid-order 항목은 없습니다. Choice가 작업자를 호출하기 전에 이를 거부했습니다.

이제 워크플로의 Invoke 정책만 제거하세요. 작업자 역할과 데이터 권한은 별도로 유지됩니다. 운영자는 여전히 실행을 시작할 수 있지만 워크플로 역할은 해당 작업을 호출할 수 없습니다.

aws iam delete-role-policy --role-name labex-ev03-workflow-role --policy-name InvokeWorker
DENIED_ARN=$(aws stepfunctions start-execution \
  --state-machine-arn "$MACHINE_ARN" \
  --name denied-order \
  --input '{"id":"denied-order","quantity":2}' \
  --query executionArn \
  --output text)
for attempt in $(seq 1 30); do
  STATUS=$(aws stepfunctions describe-execution \
    --execution-arn "$DENIED_ARN" \
    --query status \
    --output text)
  if test "$STATUS" != RUNNING; then break; fi
  sleep 2
done
aws stepfunctions describe-execution \
  --execution-arn "$DENIED_ARN" \
  --query '{Status:status,Error:error}'
aws dynamodb get-item \
  --table-name labex-ev03-orders \
  --key '{"id":{"S":"denied-order"}}' \
  --query Item
aws iam put-role-policy \
  --role-name labex-ev03-workflow-role \
  --policy-name InvokeWorker \
  --policy-document file://workflow-invoke.json

거부된 실행은 호출 시 접근 거부 오류로 실패합니다. 주문을 생성하지 않고 작업자 작업도 수행하지 않습니다. 의도한 정책을 복구했습니다. AWS View는 저장된 주문 하나 옆에 실제 성공 요약과 두 실패를 보여 줍니다.

아래 예시는 실제 성공 요약, 거부된 실행과 비즈니스 주문 하나를 보여 줍니다.

실제 워크플로 요약과 실패한 실행이 표시된 AWS View

실행 검사를 수행하세요.

워크플로 리소스와 테스트 결과 제거

이 단계에서는 제공된 준비물을 유지하면서 완료된 머신, 워크플로 역할, 주문과 로그를 삭제합니다.

세 실행은 모두 종료되었습니다. 머신을 삭제하면 활성 머신 목록에서 제거됩니다. 역할을 삭제하기 전에 소유한 역할 정책을 제거한 다음 실행으로 만든 테스트 주문과 작업자 로그 그룹을 제거하세요.

aws stepfunctions delete-state-machine --state-machine-arn "$MACHINE_ARN"
aws iam delete-role-policy --role-name labex-ev03-workflow-role --policy-name InvokeWorker
aws iam delete-role --role-name labex-ev03-workflow-role
aws dynamodb delete-item \
  --table-name labex-ev03-orders \
  --key '{"id":{"S":"workflow-order"}}'
aws dynamodb delete-item \
  --table-name labex-ev03-attempts \
  --key '{"id":{"S":"workflow-order"}}'
aws logs delete-log-group --log-group-name /aws/lambda/labex-ev03-worker

성공한 인벤토리를 읽어 남은 것을 증명하세요.

aws stepfunctions list-state-machines
aws iam list-roles --query 'Roles[].RoleName'
aws dynamodb scan --table-name labex-ev03-orders --query Items
aws logs describe-log-groups --query logGroups
aws dynamodb scan --table-name labex-ev03-reference --query Items

활성 머신, 주문이나 로그 그룹은 없습니다. 제공된 작업자 역할만 남으며 참조 항목은 변경되지 않습니다. 제공된 작업자와 테이블을 유지하세요. 준비 단계의 소유 범위는 직접 만든 워크플로/리소스와 다릅니다. 네트워크 오류나 인증 오류는 삭제를 증명하지 않습니다.

이 실습에서 만든 일반 파일을 제거하세요.

rm -f workflow-trust.json workflow-invoke.json workflow-template.json workflow.json

AWS View는 빈 머신/실행/주문과 유지된 참조를 보여 줍니다. VM을 종료하기 전에 정리 검사를 실행하세요.

요약

범위가 제한된 워크플로 실행 역할을 만들고 Choice와 두 실제 Lambda 작업을 연결했으며 실제 결과를 다음 작업에 전달하고 실행 기록을 비즈니스 데이터와 비교했습니다. 잘못된 입력과 누락된 호출 권한은 주문을 생성하지 않았습니다. 제공된 준비물을 유지하면서 소유한 워크플로 리소스와 테스트 결과를 제거했습니다.

다음 단원은 일시적인 실패를 위한 재시도와 영구 오류의 명시적인 처리를 추가합니다.