서버리스 애플리케이션에서 오류 처리

AWS Step Functions 및 AWS Lambda 사용

이 자습서에서는 AWS Step Functions를 사용하여 워크플로 런타임 오류를 처리하는 방법을 배웁니다. AWS Step Functions는 여러 Lambda 함수를 디버깅하고 변경하기 쉬운 유연한 워크플로로 쉽게 조정할 수 있는 서버리스 조율 서비스입니다. AWS Lambda는 서버를 프로비저닝하거나 관리하지 않고도 코드를 실행할 수 있는 컴퓨팅 서비스입니다. 

Lambda 함수는 처리되지 않은 예외가 발생하거나, 구성된 제한 시간보다 오래 실행되거나, 메모리가 부족한 등의 경우에 실패할 수 있습니다. 특히 분산 애플리케이션의 경우, 모든 Lambda 함수에 API 조절 또는 소켓 시간 초과와 같은 상황을 처리하는 오류 처리 로직을 작성하고 유지 관리하는 것은 시간이 많이 걸리고 복잡합니다. 각각의 Lambda 함수에 이 코드를 내장하면 함수 간에 종속성이 나타나며, 환경이 변화함에 따라 그러한 모든 관계를 관리하기가 어려워집니다.

이를 방지하고 작성하는 오류 처리 코드의 양을 줄이려면 AWS Step Functions를 사용하여 함수 오류 처리를 지원하는 서버리스 워크플로를 생성하면 됩니다. 개발자가 생성한 함수 예외 오류(예: 파일을 찾을 수 없음)이든 예상치 못한 오류(예: 메모리 부족)이든 관계없이, 발생하는 오류의 유형에 따라 조건부 로직으로 응답하도록 Step Functions를 구성할 수 있습니다. 이 방식으로 워크플로 로직을 비즈니스 로직과 분리하면 Lambda 함수의 비즈니스 로직을 변경하지 않고도 워크플로가 오류에 응답하는 방식을 수정할 수 있습니다.

이 자습서에서는 AWS Step Functions를 사용하여 이러한 오류를 정상적으로 처리하는 서버리스 워크플로를 설계하고 실행합니다. RESTful API에 대한 호출을 모의 구현하고 다양한 응답 코드와 예외를 반환하는 AWS Lambda 함수를 생성합니다. 그런 다음 AWS Step Functions를 사용하여 발생하는 예외에 따라 서로 다른 로직으로 응답하며 재시도 및 포착 기능이 있는 상태 시스템을 새성합니다.

이 자습서를 사용하려면 AWS 계정이 필요합니다.

AWS Step Functions 또는 AWS Lambda는 추가 요금 없이 사용할 수 있습니다. 이 자습서에서 생성하는 리소스는 프리 티어에 해당합니다. 

프리 티어에 대해 자세히 알아보기 >>


1단계. API를 모의 구현하는 Lambda 함수 생성

이 단계에서는 몇 가지 기본 API 상호 작용을 모의 구현하는 Lambda 함수를 생성합니다. 이 Lambda 함수는 이벤트 파라미터에 입력으로 제공하는 오류 코드에 따라 가상의 API로부터의 응답을 시뮬레이션합니다.


a.  AWS Management Console을 엽니다. 이 단계별 안내서는 계속 열어 놓을 수 있습니다. 이 화면이 로드되면 먼저 사용자 이름 및 암호를 입력하여 시작합니다. 다음으로, 검색 창에 Lambda를 입력하고 Lambda를 선택하여 서비스 콘솔을 엽니다.

( 확대하려면 클릭 )


b. [함수 생성]을 선택합니다.

( 확대하려면 클릭 )


c. [새로 작성]을 선택된 상태로 둡니다. 이제 다음과 같이 Lambda 함수를 구성합니다.

[이름]에 MockAPIFunction을 입력합니다.
[런타임]에서 [Python 3.6]을 선택합니다.
[역할]에서 [사용자 지정 역할 생성]을 선택합니다.

새 IAM 창이 열립니다. [역할 이름]을 lambda_basic_execution으로 두고 [허용]을 클릭합니다. 자동으로 Lambda 콘솔로 다시 돌아갑니다.

[함수 생성]을 클릭합니다.

( 확대하려면 클릭 )


d. [MockAPIFunction] 화면에서 아래로 스크롤하여 [함수 코드] 섹션으로 이동합니다. 이 자습서에서는 Python에서 Lambda 함수를 작성하는 프로그래밍 모델을 사용하여 함수를 생성합니다. 코드 창에서 모든 코드를 다음 코드로 바꾼 후 [저장]을 선택합니다.

class TooManyRequestsException(Exception): pass
class ServerUnavailableException(Exception): pass
class UnknownException(Exception): pass

def lambda_handler(event, context):
    statuscode = event["statuscode"]    
    if statuscode == "429":
        raise TooManyRequestsException('429 Too Many Requests')
    elif statuscode == "503":
        raise ServerUnavailableException('503 Server Unavailable')
    elif statuscode == "200":
        return '200 OK'
    else:
        raise UnknownException('Unknown error')

( 확대하려면 클릭 )


e. Lambda 함수가 생성되고 나면, 창의 상단으로 스크롤하여 페이지 오른쪽 상단의 Amazon 리소스 이름(ARN)을 기록해 둡니다. Amazon 리소스 이름(ARN)은 AWS 리소스를 고유하게 식별하며, 여러 AWS 서비스 및 API 호출에 걸쳐 AWS 항목과 정책을 추적하고 사용하는 데 도움이 됩니다. Step Functions에서 특정 리소스를 참조해야 할 경우에 ARN이 필요합니다.

( 확대하려면 클릭 )


2단계. AWS Identity and Access Management(IAM) 역할 생성

AWS Step Functions는 코드를 실행하고 다른 AWS 리소스(예: Amazon S3 버킷에 저장된 데이터)에 액세스할 수 있습니다. 보안을 유지하려면 AWS Identity and Access Management(IAM)를 사용하여 이러한 리소스에 Step Functions 액세스 권한을 부여해야 합니다.


a. 다른 브라우저 창에서 AWS Management Console로 이동하여 검색 창에 IAM을 입력합니다. [IAM]을 클릭하여 서비스 콘솔을 엽니다.

( 확대하려면 클릭 )


b. [역할]을 클릭한 후 [역할 생성]을 선택합니다.

( 확대하려면 클릭 )


c. [신뢰할 수 있는 유형의 엔터티 선택] 페이지의 AWS 서비스 목록에서 [Step Functions]를 선택한 후 [다음: 권한]을 선택합니다.

( 확대하려면 클릭 )


d. [권한 정책 연결] 페이지에서 [다음: 검토]를 선택합니다.

 

( 확대하려면 클릭 )


e. [검토] 페이지에서 [역할 이름]에 step_functions_basic_execution을 입력하고 [역할 생성]을 클릭합니다.

( 확대하려면 클릭 )


f. 새 IAM 역할이 생성되어 Lambda 함수의 IAM 역할 아래에 있는 목록에 표시됩니다.

( 확대하려면 클릭 )


3단계. Step Functions 상태 시스템 생성

API 응답을 모의 구현하는 단순한 Lambda 함수를 생성했으므로, 이제 API를 호출하고 예외를 처리하는 Step Functions 상태 시스템을 생성할 수 있습니다.

이 단계에서는 Step Functions 콘솔을 사용하여 [재시도] 및 [포착] 필드가 있는 태스크 상태를 사용하여 다양한 API 응답 코드를 처리하는 상태 시스템을 생성합니다. 태스크 상태를 사용하여 모의 API Lambda 함수를 호출합니다. 그러면 상태 시스템에 입력으로 제공한 API 상태 코드가 반환됩니다.


a. AWS Step Functions 콘솔을 엽니다. [상태 시스템 생성] 페이지에서 [새로 작성]을 선택합니다. [세부 정보] 섹션에서 상태 시스템의 이름을 MyAPIStateMachine으로 지정한 후 [기존 역할 사용]을 선택합니다.

( 확대하려면 클릭 )


b. 다음으로, 모의 API로부터 수신되는 응답에 따라 서로 다른 조치를 취하는 상태 시스템을 설계합니다. API에 연결할 수 없는 경우 워크플로가 다시 시도합니다. 재시도는 일시적인 오류를 해결하는 데 유용합니다. 이 워크플로는 모의 API에서 발생하는 다양한 예외도 포착합니다.

[상태 시스템 정의] 섹션의 내용을 다음 코드로 바꿉니다.

{
  "Comment": "An example of using retry and catch to handle API responses",
  "StartAt": "Call API",
  "States": {
    "Call API": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
      "Next" : "OK",
      "Comment": "Catch a 429 (Too many requests) API exception, and resubmit the failed request in a rate-limiting fashion.",
      "Retry" : [ {
        "ErrorEquals": [ "TooManyRequestsException" ],
        "IntervalSeconds": 1,
        "MaxAttempts": 2
      } ],
      "Catch": [ 
        {
          "ErrorEquals": ["TooManyRequestsException"],
          "Next": "Wait and Try Later"
        }, {
          "ErrorEquals": ["ServerUnavailableException"],
          "Next": "Server Unavailable"
        }, {
          "ErrorEquals": ["States.ALL"],
          "Next": "Catch All"
        }
      ]
    },
    "Wait and Try Later": {
      "Type": "Wait",
      "Seconds" : 1,
      "Next" : "Change to 200"
    },
    "Server Unavailable": {
      "Type": "Fail",
      "Error":"ServerUnavailable",
      "Cause": "The server is currently unable to handle the request."
    },
    "Catch All": {
      "Type": "Fail",
      "Cause": "Unknown error!",
      "Error": "An error of unknown type occurred"
    },
    "Change to 200": {
      "Type": "Pass",
      "Result": {"statuscode" :"200"} ,
      "Next": "Call API"
    },
    "OK": {
      "Type": "Pass",
      "Result": "The request has succeeded.",
      "End": true
    }
  }
}

( 확대하려면 클릭 )


c. [API 호출] 태스크 상태에서 “Resource” 줄(7번째 줄)을 찾습니다. ARN 텍스트를 클릭한 후 목록에서 ARN을 선택하여 이 ARN을 방금 생성한 모의 API Lambda 함수의 ARN으로 업데이트합니다.

( 확대하려면 클릭 )


d. 시각적 워크플로 창의 옆에 있는 새로 고침 버튼을 클릭하여 방금 설계한 워크플로에 해당하는 상태 시스템 다이어그램이 Step Functions에 표시되도록 합니다. 시각적 워크플로를 검토한 후 [상태 시스템 생성]을 클릭합니다.

( 확대하려면 클릭 )


4단계. 오류 처리 워크플로 테스트

오류 처리 워크플로를 테스트하기 위해, 상태 시스템을 호출하여 오류 코드를 입력으로 모의 API를 호출합니다.


a. [실행 시작]을 클릭합니다.

( 확대하려면 클릭 )


b. 새 실행 대화 상자가 나타납니다. 이 대화 상자에서 상태 시스템의 입력 데이터를 입력할 수 있습니다. 여러분이 API 역할을 하여 모의 API에서 반환할 오류 코드를 제공합니다. 기존 텍스트를 아래의 코드로 바꾼 후 [실행 시작]을 선택합니다.

{
    "statuscode": "200"
}

( 확대하려면 클릭 )


c. [실행 세부 정보] 화면에서 [입력]을 클릭하여 상태 시스템에 제공한 입력을 확인합니다. 다음으로, [출력]을 클릭하여 상태 시스템 실행의 결과를 확인합니다. 워크플로가 성공적인 API 호출로서 statuscode 200을 해석한 것을 확인할 수 있습니다.

( 확대하려면 클릭 )


d. [시각적 워크플로]에서 워크플로에 녹색으로 표시되는 각 실행의 실행 경로를 확인할 수 있습니다. [API 호출] 태스크 상태를 클릭한 후 [단계 세부 정보] 화면의 [입력] 및 [출력] 필드를 펼칩니다.

이 태스크 상태가 제공한 입력을 사용하여 모의 API Lambda 함수를 성공적으로 호출하고 해당 Lambda 함수의 출력 [200 OK]를 캡처한 것을 확인할 수 있습니다.

( 확대하려면 클릭 )


e. 다음으로, 시각적 워크플로에서 [정상] 태스크 상태를 클릭합니다. [단계 세부 정보]에서 이전 단계(API 호출 태스크 상태)의 출력이 이 단계에 입력으로 전달된 것을 확인할 수 있습니다. 정상 상태는 단순히 출력에 입력을 전달하고 작업을 수행하지 않는 전달 상태입니다. 전달 상태는 상태 시스템을 구성하고 디버깅할 때 유용합니다.

( 확대하려면 클릭 )


5단계. 상태 시스템의 실행 검사


a. [실행 세부 정보] 화면의 상단으로 스크롤하여 [MyAPIStateMachine]을 클릭합니다.

( 확대하려면 클릭 )


b. [실행 시작]을 다시 클릭합니다. 이번에는 다음 입력을 제공한 후 [실행 시작]을 클릭합니다.

{
    "statuscode": "503"
}

( 확대하려면 클릭 )


c. [실행 이벤트 기록] 섹션에서 각 실행 단계를 펼쳐 워크플로가 예상대로 동작했는지 확인합니다. 이 실행은 원래 실패하도록 만들어졌으므로, 놀라지 마십시오. 다음을 알 수 있습니다.

  1. Step Functions가 입력을 캡처함
  2. 해당 입력이 API 호출 태스크 상태로 전달됨
  3. API 호출 태스크 상태가 해당 입력을 사용하여 MockAPIFunction을 호출함
  4. MockAPIFunction이 실행됨
  5. ServerUnavailableException이 발생하여 MockAPIFunction이 실패함
  6. API 호출 태스크 상태의 catch 문이 해당 예외를 포착함
  7. catch 문이 워크플로를 실패 처리함
  8. 상태 시스템의 실행이 완료됨

( 확대하려면 클릭 )


d. 다음으로, 429 실행을 시뮬레이션합니다. [실행 세부 정보] 화면의 상단으로 스크롤하여 [MyAPIStateMachine]을 클릭합니다. [실행 시작]을 클릭합니다. 다음 입력을 제공하고 [실행 시작]을 클릭합니다.

{
    "statuscode": "429"
}

( 확대하려면 클릭 )


e. 이제 워크플로의 재시도 동작을 조사합니다. [실행 이벤트 기록] 섹션에서 각 실행 단계를 다시 펼쳐 Step Functions가 MockAPILambda 함수 호출을 두 번 더 시도하고 두 번 모두 실패했는지 확인합니다. API가 일시적으로 응답하지 않는 상태일 수 있으므로, 이때 워크플로는 [대기] 및 [나중에 시도] 상태(오른쪽 이미지)로 전환됩니다.

다음으로, [대기] 상태를 사용하여 응답 코드가 200으로 변경되고 워크플로 실행이 성공적으로 완료됩니다. 실제 애플리케이션에서는 429 예외를 이렇게 처리하지 않겠지만, 이 자습서에는 편의상 간단히 설명합니다.

( 확대하려면 클릭 )


f. 워크플로의 인스턴스를 하나 이상 실행합니다. 이번에는 상태 시스템에서 처리되지 않는 임의의 API 응답을 제공합니다.

{
    "statuscode": "999"
}

[실행 이벤트 기록]을 사용하여 실행을 다시 조사합니다. 조사를 끝낸 후 [MyAPIStateMachine]을 다시 클릭합니다. [실행] 창에서 모든 워크로드 실행의 기록을 확인하고 개별 실행 항목으로 이동할 수 있습니다.

( 확대하려면 클릭 )


6단계. 리소스 종료

이 단계에서는 AWS Step Functions 및 AWS Lambda 관련 리소스를 종료합니다.

중요: 현재 사용되지 않는 리소스를 종료하면 비용이 절감되므로 권장됩니다. 리소스를 종료하지 않으면 요금이 부과될 수 있습니다.


a. AWS Step Functions 콘솔 창의 상단에서 [상태 시스템]을 클릭합니다.

( 확대하려면 클릭 )


b. [상태 시스템] 창에서 MyAPIStateMachine을 클릭하고 [삭제]를 선택합니다. 대화 상자에서 [상태 시스템 삭제]를 선택하여 작업을 확인합니다. 1~2분 안에 Step Functions가 진행 중인 실행이 완료된 것을 확인하고 나면 상태 시스템이 삭제됩니다.

( 확대하려면 클릭 )


c. 다음으로, Lambda 함수를 삭제합니다. AWS Management Console 메뉴에서 [서비스]를 클릭한 후 [Lambda]를 선택합니다.

( 확대하려면 클릭 )


d. [함수] 화면에서 [MockAPIFunction]을 클릭하고 [작업]을 선택한 후 [삭제]를 선택합니다. [삭제]를 다시 클릭하여 삭제를 확인합니다.

( 확대하려면 클릭 )


e. 마지막으로, IAM 역할을 삭제합니다. AWS Management Console 메뉴에서 [서비스]를 클릭한 후 [IAM]을 선택합니다.

( 확대하려면 클릭 )


f. 이 자습서용으로 생성한 IAM 역할 2개를 모두 선택한 후 [역할 삭제]를 클릭합니다. 대화 상자에서 [예, 삭제합니다]를 클릭하여 삭제를 확인합니다.


이제 AWS Management Console에서 로그아웃해도 됩니다.

( 확대하려면 클릭 )


축하합니다!

AWS Step Functions와 AWS Lambda를 사용하여 네트워크 API의 오류 처리 워크플로를 생성했습니다. AWS Lambda를 사용하면 사실상 모든 유형의 애플리케이션이나 백엔드 서비스에 대한 코드를 별도의 관리 없이 실행할 수 있습니다. 코드를 업로드하기만 하면, Lambda에서 높은 가용성으로 코드를 실행 및 확장하는 데 필요한 모든 것을 처리합니다.

AWS Step Functions를 AWS Lambda와 결합하면 서버리스 애플리케이션을 위해 AWS Lambda 함수를 간편하게 오케스트레이션할 수 있습니다. Step Functions에서는 상태를 관리하고 오케스트레이션하는 기본 애플리케이션 없이 Lambda 함수를 사용하여 복잡한 워크플로를 제어할 수 있습니다. 또한 Amazon EC2 및 Amazon ECS와 같은 컴퓨팅 리소스를 사용하는 마이크로서비스 오케스트레이션에도 Step Functions를 사용할 수 있습니다.

다른 자습서 학습

AWS Step Functions 둘러보기