Node.js - AWS Lambda 용량 줄이기(Layer를 사용하자)
Vue.js + AWS Lambda 이용해서 Serverless로 구성하는 꽤나 야심찬 토이 프로젝트를 하고 있습니다(이번엔 기획자도 있습니다).
회사에서 개발용 + 장난감용? 으로 만들어준 공간이 있어서 열심히 가지고 놀고 있던 도중, 배포하는데 어느 순간 배포가 안 되는 오류가 발생했습니다. 오류는 워낙 자주 발생 했어서(Lambda 만지는데 오류가 너무 잦았어서...) 찾아보니 Lambda 코드 스토리지 용량이 초과해서 배포가 안 되는 것을 확인했습니다......
처음에는 데브옵스분께 용량을 늘려달라고 요청할까 했는데, 뭔가 느낌이 싸~ 한게 제가 잘못 막 가지고 놀아서 그런 것 같았습니다.
AWS 콘솔에 들어가서 확인해보는데, 함수 각각의 크기가 너무 큰 것을 확인 했습니다.
다른 함수들은(백엔드 분들이 만든 듯한) 용량이 매우 작은거(KB)에 비해 제가 만든 함수는 MB가 넘는 거에 대해서 생각해봤습니다. 그리고 제 함수들한테 뭔가 문제 있는 것 같아서 얼른 알아보기 시작했습니다.
다른 분들이 만든 함수를 들어가서 살펴보는데 차이점을 찾았는데, 바로 Lambda Layer를 사용한다는 점이었습니다.
Lambda Layer란 간단하게 공통으로 사용하는 라이브러리, 함수 등 만들어 놓은 뒤 람다 함수들이 가져가다 쓰는 것입니다.
저는 여태까지 각각의 함수들이 사용하든, 사용하지 않든 패키지에 포함된 라이브러리들을 다 포함시켜서 용량이 뻥튀기된 것이었습니다.
- 기존 빌드 로그
이러한 문제는 Layer를 쓰면서 해결되었습니다.
- 개선 후 빌드 로그
모듈들을 Layers에 넣고 공통으로 사용할 수 있게 설정했습니다. Layer에 넣을때 압축까지 해주는 모습입니다.
이렇게 설정하니깐 바로 49.7MB 였던 코드 크기는 105.8KB로 줄어들었습니다.
공통 라이브러리를 빼니깐 코드 용량이 매우 작아졌습니다.(뿌듯)
serverless.yml
provider:
name: aws
layers:
devDinnerLibs:
path: layer
package:
exclude:
- node_modules/**
functions:
loginUser:
handler: api/user.loginUser
layers:
- {Ref: DevDinnerLibsLambdaLayer}
events:
- http:
path: login
method: post
cors: true
layers에서 devDinnerLibs 라고 적어놨는데 이게 layer 이름입니다.
함수에서 사용하고자 하는 Layer가 있으면 {Ref: DevDinnerLibsLambdaLayer}라고, (앞 대문자) 이름 + LambdaLayer라고 적어줘야 합니다.(공식문서에 따름)
그리고 아래는 폴더 경로입니다.
node를 사용한다면 하위에 nodejs라는 폴더 아래에 node_modules를 넣어야 합니다.(공식문서에 따름)
현재는 path를 layer로 잡아주었으니, 하위에 nodejs를 만들어서 package.json을 만들어줍니다.
package의 exclude 옵션은 package 설정을 할 때 제외하겠다는 의미입니다.
만약 루트의 node_modules를 제외하지 않으면 Layer는 Layer대로 사용하고, 라이브러리가 포함된 람다 함수도 사용하는 것입니다. 그러면 쓸모없는 Layer만 늘어난 셈입니다.
ex) 사진 1 + layer
그렇기 때문에 루트의 node_modules를 제외해주어야만 Layer + 라이브러리가 포함되지 않은 람다 함수를 사용할 수 있습니다.
ex) 사진 2
후기.
토이 프로젝트 작업해야 하는데, 삘받아서 최적화만 했네요...ㅠ
저 말고 람다 함수 중에 Layer 안 써서 MB 넘는 함수가 있는데, 뭐라고 하면서 놀릴까 고민 중입니다...ㅋㅋ
참고자료
How to publish and use AWS Lambda Layers with the Serverless Framework
How To Add NodeJs Library Dependencies in a AWS Lambda Layer with Serverless Framework