서버리스 API 문제 디버깅

이번 장에서는 API Gateway와 Lambda에서 자주 발생하는 문제들과 이를 디버깅하는 방법을 간단히 살펴보겠습니다.

또한 Seed에서 가장 흔한 서버리스 에러 목록을 정리했습니다. Common Serverless Errors를 확인하고, 에러 메시지를 검색하여 해결책이 있는지 확인해 보세요.

서버리스 API에 요청이 들어오면, API Gateway를 거쳐 Lambda로 전달되어 함수를 실행합니다. 이 과정에서 여러 단계를 거치며, 각 단계가 문제의 원인이 될 수 있습니다. 각 단계에 대한 가시성이 높지 않기 때문에 문제를 정확히 찾아내는 것이 까다로울 수 있습니다. 이번 장에서는 다음과 같은 문제들을 살펴보겠습니다:

이 장은 API Gateway에 CloudWatch 로깅을 활성화했고, API Gateway와 Lambda 로그를 읽는 방법을 알고 있다고 가정합니다. 아직 설정하지 않았다면, API Gateway와 Lambda 로그 장을 먼저 확인하세요.

잘못된 API 엔드포인트

가장 기본적이고 흔히 발생하는 문제는 요청한 API Gateway 엔드포인트가 유효하지 않은 경우입니다. API Gateway 엔드포인트는 일반적으로 다음과 같은 형태를 가집니다:

https://API_ID.execute-api.REGION.amazonaws.com/STAGE/PATH
  • API_ID - API Gateway 프로젝트마다 고유한 식별자
  • REGION - API Gateway 프로젝트가 배포된 AWS 리전
  • STAGE - 프로젝트의 스테이지 (serverless.yml에 정의되거나 serverless deploy –stage 커맨드를 통해 전달됨)
  • PATH - API 엔드포인트의 경로 (각 함수에 대해 serverless.yml에 정의됨)

API 요청은 다음과 같은 경우 실패합니다:

  • 지정된 REGION에서 API_ID를 찾을 수 없는 경우
  • API Gateway 프로젝트에 지정된 STAGE가 없는 경우
  • 호출된 API 엔드포인트가 미리 정의된 PATH와 일치하지 않는 경우

이러한 모든 경우, 요청이 API Gateway 프로젝트에 도달하지 않기 때문에 오류가 CloudWatch에 기록되지 않습니다.

누락된 IAM 정책

이 문제는 API 엔드포인트가 aws_iam을 인증자로 사용하고, Cognito Identity Pool에 할당된 IAM 역할이 API Gateway 리소스에 대한 execute-api:Invoke 권한을 부여받지 않았을 때 발생합니다.

이 문제는 디버깅하기 까다로운데, 요청이 아직 API Gateway에 도달하지 않았기 때문에 API Gateway CloudWatch 로그에 오류가 기록되지 않기 때문입니다. 하지만 IAM 정책 시뮬레이터를 사용해 Cognito Identity Pool 사용자가 필요한 권한을 가지고 있는지 확인할 수 있습니다.

시뮬레이터를 사용하기 전에 먼저 API Gateway에 연결하는 데 사용하는 IAM 역할의 이름을 찾아야 합니다. 이 역할은 Cognito Identity Pool 생성 챕터에서 만들었습니다.

AWS 콘솔에서 Cognito를 선택합니다.

Cognito 서비스 선택 스크린샷

다음으로 Manage Federated Identities 버튼을 클릭합니다.

Manage Federated Identities 클릭 스크린샷

그리고 Identity Pool을 선택합니다. 여기서는 notes identity pool이라는 이름을 사용했습니다.

Identity Pool 선택 스크린샷

오른쪽 상단의 Edit identity pool을 클릭합니다.

Edit identity pool 클릭 스크린샷

여기서 Authenticated role의 이름을 기록해 둡니다. 여기서는 Cognito_notesidentitypoolAuth_Role입니다.

Identity Pool 인증 역할 스크린샷

이제 테스트할 IAM 역할을 알았으니 IAM 정책 시뮬레이터를 열어봅시다.

IAM 정책 시뮬레이터 열기

Roles를 선택합니다.

IAM 서비스 시뮬레이터 역할 선택

위 단계에서 기록한 IAM 역할을 선택합니다. 여기서는 Cognito_notesidentitypoolAuth_Role입니다.

IAM 서비스 시뮬레이터 역할 선택

서비스로 API Gateway를 선택하고 Invoke 액션을 선택합니다.

IAM 서비스 시뮬레이터 액션 선택

서비스를 확장하고 API Gateway 엔드포인트 ARN을 입력한 후 Run Simulation을 선택합니다. 여기서 사용하는 형식은 Cognito Identity Pool 생성 챕터에서 사용한 것과 동일합니다: arn:aws:execute-api:YOUR_API_GATEWAY_REGION:*:YOUR_API_GATEWAY_ID/*. 여기서는 arn:aws:execute-api:us-east-1:*:ly55wbovq4/*입니다.

API Gateway 엔드포인트 ARN 입력

IAM 역할이 올바르게 구성되었다면 Permission 아래에 allowed가 표시됩니다.

IAM 서비스 시뮬레이터 권한 허용

하지만 문제가 있다면 denied가 표시됩니다.

IAM 서비스 시뮬레이터 권한 거부

이 문제를 해결하고 역할을 수정하려면 AWS 콘솔로 돌아가 서비스 목록에서 IAM을 선택합니다.

IAM 서비스 선택 스크린샷

왼쪽 메뉴에서 Roles를 선택합니다.

IAM Roles 선택 스크린샷

그리고 Identity Pool이 사용하는 IAM 역할을 선택합니다. 여기서는 Cognito_notesidentitypoolAuth_Role입니다.

notes identity pool 인증 역할 선택 스크린샷

정책 목록에서 정책을 확장합니다.

인증 역할 정책 확장 스크린샷

Edit policy를 클릭합니다.

인증 역할 정책 편집 스크린샷

여기서 정책을 편집해 API Gateway를 호출할 수 있는 권한이 있는지 확인합니다. 정책에 다음과 같은 블록이 있는지 확인하세요.

...
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"
      ],
      "Resource": [
        "arn:aws:execute-api:YOUR_API_GATEWAY_REGION:*:YOUR_API_GATEWAY_ID/*"
      ]
    }
...

마지막으로 Save를 클릭해 정책을 업데이트합니다.

인증 역할 정책 저장 스크린샷

이제 정책을 테스트하면 API Gateway 엔드포인트를 호출할 수 있음을 확인할 수 있습니다.

Lambda 함수 오류

Lambda 함수를 호출할 수 있지만 잡히지 않은 예외로 인해 제대로 실행되지 않으면 오류가 발생합니다. 이러한 경우 디버깅은 상당히 간단합니다. 이럴 때 AWS Lambda는 오류 객체를 문자열로 변환한 후 스택 트레이스와 함께 CloudWatch로 전송합니다. 이는 Lambda와 API Gateway의 CloudWatch 로그 그룹에서 모두 확인할 수 있습니다.

Lambda 함수 타임아웃

때로는 Lambda 함수가 타임아웃되는 경우가 발생할 수 있습니다. 일반적으로 Lambda 함수는 전달된 콜백 함수를 호출하여 실행을 종료합니다. 기본적으로 콜백은 Node.js 런타임 이벤트 루프가 비워질 때까지 기다린 후 호출자에게 결과를 반환합니다. 만약 Lambda 함수가 데이터베이스 서버와 같은 곳에 열린 연결을 가지고 있다면, 이벤트 루프가 비워지지 않아 콜백은 연결이 닫히거나 Lambda 함수가 타임아웃될 때까지 무한정 기다리게 됩니다.

이 문제를 해결하기 위해 callbackWaitsForEmptyEventLoop 속성을 false로 설정할 수 있습니다. 이렇게 하면 콜백이 호출되는 즉시 AWS Lambda가 프로세스를 중단하도록 요청할 수 있으며, 이벤트 루프에 이벤트가 남아 있어도 상관없습니다.

export async function handler(event, context, callback) {

  context.callbackWaitsForEmptyEventLoop = false;

  ...
};

이 방법을 사용하면 Lambda 함수가 데이터베이스 연결을 닫지 않고도 호출자에게 결과를 반환할 수 있습니다. 이를 통해 Lambda 함수가 여러 호출에서 동일한 연결을 재사용할 수 있으며, 실행 시간도 단축됩니다.

이것들은 서버리스 API 작업 중 자주 발생하는 몇 가지 일반적인 문제들입니다. 추가로 다루어 주길 원하는 문제가 있다면 댓글로 알려주세요.