[찍먹 Cloud Computing] 3. AWS Lambda
Python 기반으로 AWS Lambda 함수를 만들어보자. 2021-07-21

AWS Lambda

안녕하세요? Justkode 입니다. 이번 시간에는 AWS Lambda에 대해서 알아 보고, AWS Lambda 함수를 생성 해 보고, 이를 AWS API Gateway를 통해 연결 하여 사용 해 보는 시간을 가져 보도록 하겠습니다.

AWS Lambda에 대해서 간단하게 설명 하고 넘어 가자면, PaaS (Platform As A Service)의 일종으로, 우리가 AWS Lambda에 우리가 구현한 API Code를 등록 하고, 이에 대한 컴퓨팅 비용을 사용한 만큼만 지불 하는 서비스 입니다.

우리가 따로 운영체제, 런타임 등의 관리를 할 필요 없이 사용자가 Python, Node.js 등의 언어로 만들어진 Lambda Handler Function을 구현 하여 이를 AWS Lambda에 등록하고, 이를 AWS API Gateway에 연결 하면, 외부에서 해당 API를 이용 할 수 있습니다.

AWS Lambda

Lambda 함수 일단 만들기

먼저, 사용 하기 전에, 일단 Lambda 함수를 만들어 보는 시간을 가져 보도록 하겠습니다. AWS Lambda Console에 먼저 접속을 해 주세요. 그 다음, 우측 상단에 있는 함수 생성을 클릭 해 주세요.

AWS Lambda Console 접속 화면

그러면, 이렇게 함수를 생성 하는 창으로 이동하게 됩니다. 첫 번째로, Lambda Handler의 이름을 지정 해 보겠습니다. 함수 이름에 원하는 함수명을 입력 하고, 원하는 런타임(언어)를 선택 해 줍니다.

함수 생성 화면

그 밑에는 함수에 대한 접근 권한 (VPC), 코드 서명을 설정 할 수 있습니다. 이 강의에서는 다루지 않습니다. 세팅이 완료 되셨다면, 우측 하단의 함수 생성을 클릭 하시면 됩니다.

함수 생성 화면

이렇게 함수가 생성된 것을 확인 할 수 있습니다. 그럼 한 번, 스크롤을 내려서 코드를 입력 하는 곳을 확인 해 볼까요?

함수 생성 완료

다음과 같이 코드를 입력 할 수 있는 창이 있는 것을 확인 할 수 있습니다. 여기서 왜 lambda_handler 같은 함수가 나왔는지, 엔트리 함수는 무엇인지 궁금 해 하실 수 있습니다. 한 번 더 스크롤을 내려 볼까요?

코드 입력

그럼 다음과 같은 정보들을 확인 할 수 있는데요, 여기서 런타임 설정 - 핸들러를 확인 하시게 되면, 엔트리 함수가 무엇인지 확인 할 수 있습니다. 일단 다시 돌아가서 엔트리 (혹은 핸들러) 함수에 대한 코드 분석을 해 보도록 하겠습니다.

코드 입력

핸들러 함수는 다음과 같은 파라미터를 갖습니다.

  • event: 이벤트와 관련한 정보를 담고 있습니다. event 객체를 통해서, json형식으로 온 body에 접근 할 수 있습니다. 이 객체는 일반적으로 Python dict 유형입니다. 또한 list, str, int, float 또는 NoneType 유형이 될 수 있습니다.

추가로, 이 예제에서는 Lambda Proxy를 사용 합니다. (여담: 이 Post 쓰면서 이 친구 때문에 하루 삽질함 ^^, 제발 AWS 형님들 도큐먼트좀 이쁘게 써주세요. 검색하면 최상단에 나오게 했으면서 가독성이 진짜 쓰레기야. 우리 한테 "???: 야, 이래도 써? 징하다 징해" 하는 것도 아니고 어?)

Lambda Proxy를 사용 하면, Event 객체로 들어오는 데이터는 매~우 많습니다. 대충 어떤 값이 나오는지는 Test 옆 ▼ 버튼 - Configure test event를 눌러 주세요, 그 다음, 테스트 이벤트 구성 - 이벤트 템플릿 - Amazon API Gateway AWS Proxy를 클릭 해보면 다음과 같이 파라미터를 확인 해 볼 수 있습니다.

  • body: Body로 들어온 String 값 입니다.
  • httpMethod: 어떤 HTTP Method 를 사용 하여 요청하였는지에 대한 정보를 담고 있습니다.
  • isBase64Encoded: Base64로 인코딩 되었는지 알려 줍니다.
  • queryStringParameters: Query String을 파싱하여 어떤 파라미터가 들어 왔는지 알려 줍니다.
  • multiValueQueryStringParameters: Query String을 파싱하여 어떤 파라미터가 들어 왔는지 알려 줍니다. 중복된 키를 가진, 여러 가지 Value에 대해서도 출력합니다.
  • headers: HTTP Header 정보를 알려 줍니다.
  • multiValueHeaders: HTTP Header 정보를 알려 줍니다. 중복된 키를 가진, 여러 가지 Value에 대해서도 출력합니다.

클릭 해 보면,

엄청 많음.

  • context: 컨텍스트 정보를 담고 있습니다. 이 객체는 호출, 함수 및 런타임 환경에 관한 정보를 제공하는 메서드 및 속성들을 제공합니다.

Code Implement

한 번, 간단한 계산 연산을 해 주는 코드를 구현 해 볼까요? 아래에 있는 코드는, 연산자, 피연산자 정보를 가지고 있는 해당 jsonbody로 입력 받아, 계산 명령을 실행 하는 코드입니다. 일단 새로운 테스트 이벤트 생성을 클릭 후 테스트 이벤트 구성 - 이벤트 템플릿 - Amazon API Gateway AWS Proxy를 선택하여 템플릿을 가져온 다음, Event Json을 복사해서 넣어 주세요. 다음, 이벤트 이름을 add 라고 한 후에 저장 해 주세요.

  • Event json
{
  "body": null,
  "resource": "/{proxy+}",
  "path": "/path/to/resource",
  "httpMethod": "GET",
  "isBase64Encoded": true,
  "queryStringParameters": {
    "a": "1",
    "b": "2",
    "operator": "+"
  },
  "multiValueQueryStringParameters": {
    "a": [
      "1"
    ],
    "b": [
      "2"
    ],
    "operator": [
      "+"
    ]
  },
  ...
}

다음과 같이 넣어 주세요.

한 번 코드를 구현 해 보겠습니다. 방금 저장한 테스트 이벤트에 작성한 json 객체가 그대로 lambda_handlerevent 파라미터로 들어 갑니다. 이를 알아 두고 코딩을 하면 되겠습니다.

또한, Lambda 프록시 통합 옵션을 나중에 사용하는 API Gateway에서 사용하게 된다면, lambda_handler는 다음과 같은 반환 형식을 유지 하여야 합니다.

{
  "isBase64Encoded" : "boolean",
  "statusCode": "number",
  "headers": { ... },
  "body": "JSON string"
}

자, 이에 맞게 한 번 프로그래밍 해 볼까요? ab로 들어 온 값에 대해 operator 연산자에 해당하는 연산을 하는 API를 만들어 보도록 하겠습니다.

import json

def lambda_handler(event, context):
    # Key Check
    param = event['queryStringParameters']
    print(param)
    if any([e not in param for e in ('operator', 'a', 'b')]):
        return {
            'statusCode': 400,
            'body': json.dumps({"message": "key error"})
        }
        
    operator = param['operator']
    
    try:
        a = int(param['a'])
        b = int(param['b'])
    except Exception:
        return {
            'statusCode': 400,
            'body': json.dumps({
                "message": "value error"
            })
        }
    
    if operator == '+' or operator == ' ':  # query string에서 +는 띄어쓰기로 변환됨
        return {
            'statusCode': 200,
            'body': json.dumps({
                "result": a + b
            })
        }
    elif operator == '-':
        return {
            'statusCode': 200,
            'body': json.dumps({
                "result": a - b
            })
        }
    elif operator == '/':
        return {
            'statusCode': 200,
            'body': json.dumps({
                "result": a / b
            })
        }
    elif operator == '*':
        return {
            'statusCode': 200,
            'body': json.dumps({
                "result": a * b
            })
        }
    else:
        return {
            'statusCode': 400,
            'body': json.dumps({"message": "operator error"})
        }

코드를 완성 했다면, 이제 저장을 하고 배포를 할 시간 입니다. Ctrl + S 입력 후, Deploy를 클릭 해 줍니다. 그러면, Changes deployed 가 뜨면 성공입니다!

Test 옆 Deploy 클릭

그 다음, 우리가 만든 함수를 테스트 해봐야죠! Test를 누르면, 다음과 같이 결과가 나오게 됩니다.

Test 결과

Test를 누른 후, 모니터링 - 로그를 클릭하면, Lambda 함수를 실행 하면서 출력된 로그들을 열람 할 수 있습니다.

최근의 LogStream을 확인 해 보면, 이렇게 print로 출력 했던 파라미터들을 확인 할 수 있다.

API Gateway

다음은 API Gateway Console로 이동 합니다. 우리가 만든 AWS Lambda 함수를 API Gateway에 등록 하기 위해서 입니다. 일단 스크롤을 좀 내려서, REST API - 구축을 클릭 해 보죠.

REST API - 구축 클릭

그 다음, 프로토콜 선택에서는 REST, 새 API 생성 에서는 새 API, 설정에서는 API 이름을 입력 해 주고, 설명이 필요하다면, 설명도 작성 합니다. 다 입력 하셨다면, API 생성을 클릭 합니다.

REST API - 구축 클릭

그러면, 이제 우리가 만든 API와 관련한 대시보드가 나오게 됩니다. 일단 좌측의 메뉴에서 API - 리소스를 클릭하고, 리소스 - 작업 - 리소스 생성을 클릭 합니다. 하위 리소스를 설정 해야 하기 때문이죠. 하위 리소스를 분리 하여 생성 함으로써, 우리는 하나의 API에 대해 여러 가지 함수를 붙여 넣을 수 있습니다. 비슷한 기능을 하는 함수끼리 묶을 수가 있다는 뜻이죠. (ex: /user/login (로그인), /user/modify (유저 정보 수정 등))

리소스 - 작업 - 리소스 생성 클릭

그 다음에는 우측에 새 하위 리소스를 생성하는 창이 뜨게 됩니다. 리소스 이름리소스 경로를 입력 해 주고, CORS 옵션이 필요 하다면, API Gateway CORS 활성화도 체크 해 줍니다. 여기서 리소스 경로는 등록 할 API의 경로를 입력 해 주시면 됩니다.

다 완료하면 리소스 생성 클릭

그 다음, 우리가 만든 함수를 등록 할 차례 입니다. 리소스 - 작업 - 메서드 생성을 클릭 해 주세요. 타입은 ANY를 선택 해 줍니다. 우리는 AWS Lambda Proxy를 사용 하기 때문에, HTTP Method 정보를 가져 올 수 있기 때문이죠.

리소스 - 작업 - 메서드 생성 클릭

ANY 클릭후 옆에 체크 무늬 클릭

그러면 이렇게 메서드를 설정하는 창이 뜨게 되는데요. 통합 유형 - Lambda 함수를 선택 해 주시고, Lambda 프록시 통합 사용 - 체크, Lambda 함수는 방금 만드신 AWS Lambda 함수의 이름을 입력 해 주세요, 리전에 맞게 하시면 됩니다.

다음과 같이 설정 하시고, 저장

마지막으로, 이렇게 우리가 만든 API스테이지에 올려 실제로 배포 할 시간입니다. 리소스 - 작업 - API 배포를 클릭 해 주세요.

리소스 - 작업 - API 배포 클릭

그럼 배포할 스테이지를 선택하라는 창이 뜹니다. 그러면 배포 스테이지 - [새 스테이지]를 클릭, 스테이지 이름을 입력 합니다. 그 다음, 스테이지 설명 및 배포 설명을 기호에 맞게 작성 후, 저장을 눌러 주세요.

입력 후 저장

자! 그러면 이렇게 우리가 만든 API를 스테이지에 등록 완료 하였습니다. 위에 있는 URL 호출에 있는 엔드포인트를 복사 하여 한번 테스트 해 보겠습니다.

입력 후 저장

성공적으로 작동 되는 것을 볼 수가 있습니다!

반환도 잘 되고, Status Code도 잘 적용 되는 모습.

마치며

이렇게 AWS Lambda를 사용해 보는 시간을 가져 보았습니다. 이 글에서는 다루지 않았지만, 트리거 기능을 이용하여, S3 이미지가 들어오면 자동으로 이미지 리사이징을 해 주는 등의 기능 또한 있으니, 트리거에 대해서 따로 공부 해 보시는 것도 추천드립니다! 다음 시간에는 AWS RDS, AWS DynamoDB에 대해서 공부 해 보는 시간을 가져 보도록 하겠습니다.