[Cloud Computing] 3. AWS Lambda

Minjeong Park·2021년 7월 25일
0

Cloud Computing

목록 보기
4/4
post-thumbnail

🖲️ AWS Lambda가 무엇인가요?

AWS LambdaPaaS의 일종입니다! PaaS가 기억이 안난다면.. 여기를 확인하세욥! 우리가 따로 운영체제와 런타임 등을 관리할 필요가 없습니다. 런타임을 관리하지 않아도 된다는 것은 정말 큰 이점입니다! 중간에 서버가 다운될 수도 있고, 오류가 나서 의도치 않은 현상들이 발생 할 수도 있는데 그런 것에 대한 걱정을 할 필요 없이 함수만 뙇 올리면 되기 때문이죠.

AWS Lamdba를 설명하기 전에, 다음과 같은 상황을 가정해보겠습니다. 우리가 Flask를 이용해 특정 API 함수를 만들어서 EC2에 올렸다고 합시다. EC2는 계속 켜져있기 때문에 많이 오든 적게 오든 요금은 계속 똑같이 나갈 것입니다. '난 쓴 만큼만 내고 싶은데 이렇게 계속 돈이 나가야하나..?' 싶을 수 있습니다. 그래서 API만든 것을 Lambda에 연결을 시키고, 오고 가는 요청의 갯수와 자원에 대해서만 요금을 내게 하는 것입니다.

즉, 예전에 EC2에선 서버를 만들어서 서버 단위로 관리했었는데, Lambda에서는 우리가 만든 함수를 단위로 이용한 만큼 요금을 지불하는 형식입니다.

사용자가 Python, Node.js 등의 언어로 만들어진 Lambda Handler Function을 구현하여 이를 AWS Lambda에 등록하고, 이를 AWS API Gateway에 연결하면, 외부에서 해당 API를 이용할 수 있습니다(AWS API Gateway 에서는 트래픽 관리를 하거나, 로그를 찍거나 하는 등등의 여러 기능이 있습니다.).

📃 Lambda 함수 생성하기

AWS Lambda 콘솔에 접속합니다. 우측의 함수 생성을 눌러서 함수를 생성합니다.

함수를 생성하는 창으로 이동하면 Lambda Handler 함수 이름런타임을 설정해줍니다. 런타임어떤 언어를 쓸지를 뜻합니다.

나머지는 설정은 딱히 건들지 않고 함수 생성을 누르도록 하겠습니다. 그럼 아래와 같이 람다 함수가 생성된 것을 확인할 수 있습니다.

아래로 내려가면 코드 소스가 보입니다. 코드를 확인할 수 있습니다.

더 밑으로 내려가면 런타임 설정에서 핸들러를 설정할 수 있는 곳이 나옵니다. 아래 사진에서 lambda_function.lambda_handler의 의미는, lambda_function.py 안에 있는 lambda_handler를 핸들러 함수로 이용하겠다라고 지정한 것입니다.

Handler 함수 뜯어보기

lambda_function.py 안에 있었던 lambda_hanlder 함수를 톺아보도록 하겠습니다!

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
  • Parameter

    • event

    요청이 들어왔을 때 이벤트에 관련된 정보들을 담고 있습니다. json형식으로 온 body에 접근할 수 있습니다. 대체로 Pythondict유형으로 옵니다. 하지만 list, str, int, float 또는 NoneType이 될 수도 있습니다.

    하지만 Lambda Proxy를 사용하면, Event 객체로 들어오는 데이터가 정말 많아집니다. Test 옆의 토글을 열어 Configure test event를 클릭하고, 테스트 이벤트 구성 - 이벤트 템플릿 - Amazon API Gateway Proxy를 클릭하면 정보를 알 수 있습니다.

    {
    "body": "eyJ0ZXN0IjoiYm9keSJ9",
    "resource": "/{proxy+}",
    "path": "/path/to/resource",
    "httpMethod": "POST",
    "isBase64Encoded": true,
    "queryStringParameters": {
      "foo": "bar"
    },
    "multiValueQueryStringParameters": {
      "foo": [
        "bar"
      ]
    },
    "pathParameters": {
      "proxy": "/path/to/resource"
    },
    "stageVariables": {
      "baz": "qux"
    },
    "headers": {
      "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
      "Accept-Encoding": "gzip, deflate, sdch",
      "Accept-Language": "en-US,en;q=0.8",
      "Cache-Control": "max-age=0",
      "CloudFront-Forwarded-Proto": "https",
      "CloudFront-Is-Desktop-Viewer": "true",
      "CloudFront-Is-Mobile-Viewer": "false",
      "CloudFront-Is-SmartTV-Viewer": "false",
      "CloudFront-Is-Tablet-Viewer": "false",
      "CloudFront-Viewer-Country": "US",
      "Host": "1234567890.execute-api.us-east-1.amazonaws.com",
      "Upgrade-Insecure-Requests": "1",
      "User-Agent": "Custom User Agent String",
      "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
      "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
      "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
      "X-Forwarded-Port": "443",
      "X-Forwarded-Proto": "https"
    },
    "multiValueHeaders": {
      "Accept": [
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
      ],
      "Accept-Encoding": [
        "gzip, deflate, sdch"
      ],
      "Accept-Language": [
        "en-US,en;q=0.8"
      ],
      "Cache-Control": [
        "max-age=0"
      ],
      "CloudFront-Forwarded-Proto": [
        "https"
      ],
      "CloudFront-Is-Desktop-Viewer": [
        "true"
      ],
      "CloudFront-Is-Mobile-Viewer": [
        "false"
      ],
      "CloudFront-Is-SmartTV-Viewer": [
        "false"
      ],
      "CloudFront-Is-Tablet-Viewer": [
        "false"
      ],
      "CloudFront-Viewer-Country": [
        "US"
      ],
      "Host": [
        "0123456789.execute-api.us-east-1.amazonaws.com"
      ],
      "Upgrade-Insecure-Requests": [
        "1"
      ],
      "User-Agent": [
        "Custom User Agent String"
      ],
      "Via": [
        "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)"
      ],
      "X-Amz-Cf-Id": [
        "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA=="
      ],
      "X-Forwarded-For": [
        "127.0.0.1, 127.0.0.2"
      ],
      "X-Forwarded-Port": [
        "443"
      ],
      "X-Forwarded-Proto": [
        "https"
      ]
    },

    위와 같은 정보를 알 수 있다고 하네요!

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

🖩 계산기 만들기

Test 옆의 토글을 열어 Configure test event를 클릭하고, 테스트 이벤트 구성 - 이벤트 템플릿 - Amazon API Gateway Proxy를 클릭해서 계산기를 만들기 위해 테스트 이벤트 구성을 해봅시다!

다음과 같이 만들어주면 되는데요.
아래 코드를 그대로 복사 붙여넣기 하고 생성을 눌러주면 됩니다.

{
  "body": "null",
  "resource": "/{proxy+}",
  "path": "/path/to/resource",
  "httpMethod": "GET",
  "isBase64Encoded": true,
  "queryStringParameters": {
    "a": "1",
    "b": "2",
    "operator": "+"
  },
   "multiValueQueryStringParameters": {
    "a": [
      "1"
    ],
    "b": [
      "2"
    ],
    "operator": [
      "+"
    ]
  },
  "pathParameters": {
    "proxy": "/path/to/resource"
  },
  "stageVariables": {
    "baz": "qux"
  },
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, sdch",
    "Accept-Language": "en-US,en;q=0.8",
    "Cache-Control": "max-age=0",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-Country": "US",
    "Host": "1234567890.execute-api.us-east-1.amazonaws.com",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Custom User Agent String",
    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
    "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
    "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "multiValueHeaders": {
    "Accept": [
      "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
    ],
    "Accept-Encoding": [
      "gzip, deflate, sdch"
    ],
    "Accept-Language": [
      "en-US,en;q=0.8"
    ],
    "Cache-Control": [
      "max-age=0"
    ],
    "CloudFront-Forwarded-Proto": [
      "https"
    ],
    "CloudFront-Is-Desktop-Viewer": [
      "true"
    ],
    "CloudFront-Is-Mobile-Viewer": [
      "false"
    ],
    "CloudFront-Is-SmartTV-Viewer": [
      "false"
    ],
    "CloudFront-Is-Tablet-Viewer": [
      "false"
    ],
    "CloudFront-Viewer-Country": [
      "US"
    ],
    "Host": [
      "0123456789.execute-api.us-east-1.amazonaws.com"
    ],
    "Upgrade-Insecure-Requests": [
      "1"
    ],
    "User-Agent": [
      "Custom User Agent String"
    ],
    "Via": [
      "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)"
    ],
    "X-Amz-Cf-Id": [
      "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA=="
    ],
    "X-Forwarded-For": [
      "127.0.0.1, 127.0.0.2"
    ],
    "X-Forwarded-Port": [
      "443"
    ],
    "X-Forwarded-Proto": [
      "https"
    ]
  },
  "requestContext": {
    "accountId": "123456789012",
    "resourceId": "123456",
    "stage": "prod",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "requestTime": "09/Apr/2015:12:34:56 +0000",
    "requestTimeEpoch": 1428582896000,
    "identity": {
      "cognitoIdentityPoolId": null,
      "accountId": null,
      "cognitoIdentityId": null,
      "caller": null,
      "accessKey": null,
      "sourceIp": "127.0.0.1",
      "cognitoAuthenticationType": null,
      "cognitoAuthenticationProvider": null,
      "userArn": null,
      "userAgent": "Custom User Agent String",
      "user": null
    },
    "path": "/prod/path/to/resource",
    "resourcePath": "/{proxy+}",
    "httpMethod": "POST",
    "apiId": "1234567890",
    "protocol": "HTTP/1.1"
  }
}

생성 후 Test 옆의 토글을 열어 방금 만든 add를 확인할 수 있습니다.

addlambda_handlerevent로 들어갑니다. 이 event에 들어가는 걸 뽑아내서 코드로 작성하면 되겠지요!

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"})
        }

위 코드를 lambda_function.py에 복붙해서 넣고, Ctrl+S를 눌러 저장하고, Deploy를 누르고, Test를 누르면 실행할 수 있습니다!

위 같이 Test 결과를 확인할 수 있습니다.

모니터링 > 로그 로 가면 로그 또한 확인할 수 있습니다. LogStream에 적혀있는 링크를 누르면 각 로그를 타임스탬프 별로 볼 수 있습니다.

🗝 API 구축하고 배포하기

API Gateway 콘솔로 이동해서 REST API 카드를 찾아 구축을 누릅니다.

프로토콜REST, 새 API 생성새 API를 선택합니다. 그 외 설정은 원하는 대로 하면 됩니다. 그 후 API 생성을 누릅니다.

메인 콘솔로 넘어 오면 리소스 > 작업 > 리소스 생성으로 하위 리소스를 설정해주러 가봅시다!

다음과 같이 입력해 주면 됩니다. API Gateway COR3 활성화는 체크해주는 게 좋습니다. 우리가 서버를 만들 때 대부분 외부에서 사용할 수 있게 할 것이기 때문입니다. 리소스 생성을 눌러줍니다.

이제 메소드를 만들어 줍시다. 작업 > 메서드 생성을 눌러서 만들고 ANY로 한 다음 체크를 누르면 됩니다.

설정은 아래 나와있는대로 하면 됩니다. Lambda 함수는 아까 했던 걸로 해야겠죠? 이렇게 하면 anyLambda 함수가 연결이 됩니다.

메서드가 연결이 된 것을 확인할 수 있습니다.

이제 실제로 배포를 해보겠습니다. 작업 > API 배포를 클릭해 이동합니다.

다음과 같이 설정하고 배포를 누릅니다.

그렇게 되면 우리가 만든 API에 대해 URL 호출, 즉 end point가 나오는데요. 이를 통해 접속할 수 있습니다.

✔ 배포 확인하기

해당 URL로 접속하면 {"message":"Missing Authentication Token"}가 나오는데요!

저는 calc이라는 하위메소드를 만들었으므로 그 링크로 들어가면, {"message": "Internal server error"} 라며 에러가 뜨지만, 내부 서버에 접속한 것을 알 수 있습니다.

현재 링크에 ?a=1&b=3&operator=/를 추가하여 쿼리문을 작성해보면(postman으로도 가능합니다!) 이렇게 result값이 잘 나오는 것을 확인할 수 있습니다.😊

profile
아자아잣

0개의 댓글