이 연재글은 AWS 람다(lambda) 실습의 5번째 글입니다.

이번 장에는 lambda를 좀더 쉽게 개발하고 관리하기 위하여 serverless에서 제공하는 몇가지 plugin을 사용해 보겠습니다. serverless에서 제공하는 plugin은 종류가 엄청나게 많으므로 자세한 내용은 아래 링크에서 확인하시면 됩니다.

https://github.com/serverless/plugins

또한 다음 명령어를 입력하면 현재 사용가능한 모든 plugins 목록과 간략한 설명을 볼 수 있습니다.

$ sls plugin list
@endemolshinegroup/serverless-dynamodb-autoscaler - Autoscale DynamoDB resources with a single AWS AutoScalingPlan
@haftahave/serverless-ses-template - A serveless plugin that allows automatically creating, updating and removing AWS SES Templates using a configuration file and keeps your AWS SES Templates synced with your configuration file.
@serverless/enterprise-plugin - The Serverless Enterprise Plugin
@unly/serverless-env-copy-plugin - Fetch environment variables and write it to a .env file - Maintained fork from https://github.com/Jimdo/serverless-dotenv
@unly/serverless-plugin-dynamodb-backups - Configure automated DynamoDB "On-Demand" backups and manage backups lifecycle, powered by AWS Lambda
api-gateway-stage-tag-plugin - A shim to tag API Gateway stages until CloudFormation/Serverless support arrives.
...............

검색어로 원하는 plugin만 검색도 가능합니다. 설치하는 명령어까지 자세하게 알려주므로 편리합니다.

$ sls plugin search -q sns
5 plugin(s) found for your search query "sns"

serverless-offline-sns - Serverless plugin to run a local SNS server and call serverless SNS handlers with events notifications.
serverless-plugin-external-sns-events - Add ability for functions to use existing or external SNS topics as an event source
serverless-plugin-tagsns - Serverless plugin to add Tags to SNS Topics
serverless-sns-filter - Serverless plugin to add SNS Subscription Filters to events
serverless-tag-sns-topic - Serverless plugin to tag SNS Topi

To install a plugin run 'serverless plugin install --name plugin-name-here'

It will be automatically downloaded and added to your package.json and serverless.yml file

serverless offline plugin

api gateway를 에뮬레이트해주는 plugin 입니다. lambda 함수에 api gateway를 트리거로 추가한것과 같은 환경을 로컬에 구현 해주는 plugin입니다.

$ sls plugin install -n serverless-offline
Serverless: Installing plugin "serverless-offline@latest" (this might take a few seconds...)
Serverless: Successfully installed "serverless-offline@latest"

serverless.yml에 설치한 plugin이 추가된것을 확인 할 수 있습니다.

plugins:
  - serverless-offline

serverless.yml에 다음과 같이 http endpoint를 설정해 놓습니다.

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: hello/get
          method: get
          cors: true

터미널에서 offline 서버를 시작합니다. 해당 서버는 3000번 port로 실행됩니다.
서버가 실행된 후 http://localhost:3000/hello/get 으로 접근하면 lambda를 실행할 수 있습니다.

$ sls offline start
Serverless: Starting Offline: dev/ap-northeast-2.

Serverless: Routes for hello:
Serverless: GET /hello/get
Serverless: POST /{apiVersion}/functions/helloworld-dev-hello/invocations

Serverless: Offline [HTTP] listening on http://localhost:3000
Serverless: Enter "rp" to replay the last request

브라우저에서 실행해도 되지만 여기서는 터미널에서 curl로 실행해 보겠습니다. 아래 내용을 터미널에서 실행하면 아무것도 출력되지 않는것을 확인할 수 있습니다. 결과를 console.log로 찍기 때문입니다.

$ curl http://localhost:3000/hello/get

console log는 offline server에 출력됩니다. 확인해 보면 /hello/get에 의해 lambda가 실행되었고 해당 로그가 찍히는것을 확인할 수 있습니다.

Serverless: GET /hello/get (λ: hello)
redis-set-result: OK
1. REDIS RESULT
Hello Lambda
2. DB RESULT
id = 238, comment = 고고고고고
id = 237, comment = sa
id = 236, comment = hi
id = 235, comment = test
id = 234, comment = yyyy
3. HTTP RESULT
id = 1, name = Leanne Graham, email = Sincere@april.biz
id = 2, name = Ervin Howell, email = Shanna@melissa.tv
id = 3, name = Clementine Bauch, email = Nathan@yesenia.net
id = 4, name = Patricia Lebsack, email = Julianne.OConner@kory.org
id = 5, name = Chelsey Dietrich, email = Lucio_Hettinger@annie.ca
id = 6, name = Mrs. Dennis Schulist, email = Karley_Dach@jasper.info
id = 7, name = Kurtis Weissnat, email = Telly.Hoeger@billy.biz
id = 8, name = Nicholas Runolfsdottir V, email = Sherwood@rosamond.me
id = 9, name = Glenna Reichert, email = Chaim_McDermott@dana.io
id = 10, name = Clementina DuBuque, email = Rey.Padberg@karina.biz

Request 정보 확인하기

Gateway를 통해 들어오는 Request 정보(Header, Body, PathParameter, RequestParameter)는 event객체에서 얻을수 있습니다. 실제로 출력해보기 위해 handler.js에 user function을 작성합니다.

module.exports.user = async event => {
  if(event.headers)
    console.log("Request Header -> User-Agent :", event.headers['User-Agent']);
  if(event.body)
    console.log("Request Body ->", event.body);
  if(event.pathParameters && event.pathParameters.id)
    console.log("Request PathParameter -> id :", event.pathParameters.id);
  if(event.queryStringParameters && event.queryStringParameters.isValid)
    console.log("Request queryString -> isValid :",event.queryStringParameters.isValid);
};

user function을 호출할수 있도록 serverless.yml에 function을 추가합니다. pathParameter 설정은 괄호를 이용하여 표현 합니다. ex) {id}

functions:
  hello:
    // 생략
  user:
    handler: handler.user
    events:
      - http:
          path: user/{id}
          method: post
          cors: true

offline 서버를 실행 합니다. log를 보면 Routes for user로 엔드포인트가 등록된것을 확인할 수 있습니다.

$ sls offline start
Serverless: Starting Offline: dev/ap-northeast-2.

Serverless: Routes for hello:
Serverless: GET /hello/get
Serverless: POST /{apiVersion}/functions/helloworld-dev-hello/invocations

Serverless: Routes for user:
Serverless: POST /user/{id}
Serverless: POST /{apiVersion}/functions/helloworld-dev-user/invocations

Serverless: Offline [HTTP] listening on http://localhost:3000
Serverless: Enter "rp" to replay the last request

다른 터미널에서 curl로 다음 내용을 요청하면 offline 서버 console에 리퀘스트 내용이 출력됩니다.

Request

$ curl -X POST \
  -H "Content-type: application/json" \
  -H "Accept: application/json" \
  -d '{"foo":"bar", "aws":"lambda"}' \
  "localhost:3000/user/10?isValid=true"

Response

Serverless: POST /user/10 (λ: user)
Request Header -> User-Agent : curl/7.64.1
Request Body -> {"foo":"bar", "aws":"lambda"}
Reqeust PathParameter -> id : 10
Request queryString -> isValid : true

serverless prune plugin

lambda를 배포하면 aws 서버에는 배포별로 버전이 생성됩니다. 과거 버전부터 최신 배포 버전까지 모두 히스토리가 남기 때문에 롤백을 하거나 특정 버전을 지정해 서비스 하는것이 가능합니다.

이러한 편리함이 있는 반면 이렇게 버전별로 계속 남기다 보니 소스코드가 사용하는 코드 스토리지의 용량이 점점 늘어나게 됩니다.

사실 배포 버전은 최신 버전외에 과거 몇개의 버전정도만 유지해도 서비스를 유지하는데 큰 지장이 없습니다. serverless에서 지원하는 prune plugin은 과거 버전의 코드를 자동으로 삭제하는 기능을 제공하여 코드 관리의 편리성을 제공합니다. 다음과 같이 설치합니다.

$ sls plugin install -n serverless-prune-plugin
Serverless: Installing plugin "serverless-prune-plugin@latest" (this might take a few seconds...)
Serverless: Successfully installed "serverless-prune-plugin@latest"

serverless.yml에 plugin이 추가된것을 확인할 수 있습니다.

plugins:
  - serverless-offline
  - serverless-prune-plugin

serverless.yml에 prune plugin 설정을 추가합니다. 아래는 자동으로 최신 5개의 버전만 남기고 자동으로 삭제하라는 설정입니다.

service: helloworld

custom:
  prune:
    automatic: true
    number: 5

배포를 진행하면 로그를 통해 과거 버전이 삭제되는것을 볼수 있습니다. aws에서 보면 역시나 동일하게 최신버전만 남고 삭제가 된 것을 확인할 수 있습니다.

Serverless: Prune: Querying for deployed function versions
Serverless: Prune: helloworld-production-hello has 21 additional versions published and 0 aliases, 16 versions selected for deletion
Serverless: Prune: Deleting Function helloworld-production-hello v18...
Serverless: Prune: Deleting Function helloworld-production-hello v17...
Serverless: Prune: Deleting Function helloworld-production-hello v16...
Serverless: Prune: Deleting Function helloworld-production-hello v15...
Serverless: Prune: Deleting Function helloworld-production-hello v14...
Serverless: Prune: Deleting Function helloworld-production-hello v13...
Serverless: Prune: Deleting Function helloworld-production-hello v12...
Serverless: Prune: Deleting Function helloworld-production-hello v11...
Serverless: Prune: Deleting Function helloworld-production-hello v10...
Serverless: Prune: Deleting Function helloworld-production-hello v9...
Serverless: Prune: Deleting Function helloworld-production-hello v8...
Serverless: Prune: Deleting Function helloworld-production-hello v7...
Serverless: Prune: Deleting Function helloworld-production-hello v6...
Serverless: Prune: Deleting Function helloworld-production-hello v5...
Serverless: Prune: Deleting Function helloworld-production-hello v4...
Serverless: Prune: Deleting Function helloworld-production-hello v3...
Serverless: Prune: helloworld-production-user has 2 additional versions published and 0 aliases, 0 versions selected for deletion
Serverless: Prune: Pruning complete.
Serverless: Removing old service artifacts from S3...
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.

실습 코드 GitHub 주소
https://github.com/codej99/SeverlessAwsLambda

연재글 이동[이전글] aws lambda 개발하기(4) – serverless로 트리거(trigger), 대상(destination), 실행역할(role), VPC, 기본 설정
[다음글] aws lambda 개발하기(6) – Multi Endpoint Restful api 개발