본문으로 건너뛰기

Nest.js - Webpack 적용 방법

  author: Dev.ian
createdAt: 2024-05-28
updatedAt: 2024-08-16

Error : AWS Lambda Size Limit

AWS Lambda 를 Serverless Framework 로 Deploy 하면 아래와 같은 에러로 실패했다.

  ... ○ Created layer package  ${PRJECT_NAME}.serverless/sample-project-dev-nodejs-default.zip (57.4 MB)
... ○ Uploading layer package...
... ○ OK...
ServerlessLayers error:
Action: Lambda:publishLayerVersion
Params: {"Content":{"S3Bucket":"sample-project-sls-deploy-bucket","S3Key":"serverless/sample-project/dev/layers/sample-project-dev-nodejs-default.zip"},"LayerName":"sample-project-dev-nodejs-default","Description":"created by serverless-layers plugin","CompatibleRuntimes":["nodejs"],"CompatibleArchitectures":["x86_64","arm64"]}
AWS SDK error:
Unzipped size must be smaller than 262144000 bytes

⠇ Packaging (245s)
error Command failed with exit code 1.

Nest.js Build: Webpack 적용하여 빌드하기

1) webpack.config.js

entry

  • AWS Lambda 에 Deploy 할 handler 가 있는 파일을 지정한다.
  • 파일의 경로는 프로젝트의 Root 를 기준으로 절대경로를 지정

output.filename

  • webpack 으로 bundling 했을 때, 생성할 파일명 을 지정한다.
  • 설정하지 않으면 main.js 로 생성된다.
  • [name] 에 entry 객체의 key 가 지정된다.
  • [name].bundle.js 처럼 . 을 이용하여 지정하지 않는다.
    • AWS Lambda 가 실행될 때 Runtime.ImportModuleError 가 발생한다.

1개의 Entry 설정

  module.exports = (options, webpack) => {
return {
...options,
entry: `./src/lambda/handler.ts`,
externals: [],
output: {
...options.output,
clean: true,
libraryTarget: 'commonjs2'
},
plugins: [
...options.plugins,
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
],
}
};

여러 개의 Entry 설정

여러 개의 AWS Lambda 함수를 Deploy 할 때는 각 Handler 마다 Webpack Bundling (Webpack의 결과물) 파일이 필요하다.

예를 들어 아래의 3개 AWS Lambda 를 Deploy 한다고 가정하자.

  • convertImage: 이미지를 변환하는 Lambda
  • backup: 이미지를 백업하는 Lambda
  • statisticUser: 유저정보의 통계를 내는 Lambda

이 경우, 각 Lambda Handler 별로 Webpack bundling 을 한 파일들이 필요하다. 소스코드의 내용이 중복되더라도 각 handler 마다 webpack 이 적용된 파일들이 있어야한다는 뜻이다.

  module.exports = (options, webpack) => {
return {
...options,
entry: {
convertImage: './src/lambda/convert-image.ts',
backupS3: './src/lambda/backup-s3.ts',
statisticsUsers: './src/statistics/statistics-users.ts',
},
externals: [],
output: {
...options.output,
clean: true,
libraryTarget: 'commonjs2'
filename: '[name]-bundle.js',
},
plugins: [
...options.plugins,
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
],
}
};

plugins

  • LimitChunkCountPlugin
    • 각 AWS Lambda 함수마다 1개의 파일로 만들어주는 plugin
    • 연결된 소스코드가 많고 길 경우, Webpack 은 자동으로 chunk 하여 bundling 한다.
    • 하나의 파일이 아닌 여러 개의 파일로 분할 될 수 있으므로 파일의 갯수를 지정할 경우 사용한다.

2) Nest.js Build

  • webpack.config.js 파일을 작성했다면 올바르게 build 가 되는지 확인해보자. Nest.js 의 webpack 옵션을 이용하여 build 한다. Webpack bundling 파일은 dist 디렉토리에서 확인할 수 있다.

      $ nest build --webpack --webpackPath src/app/webpack.config.js
  • 꽤나 긴 명령어이므로 AWS Lambda 를 Serverless Framework 로 Deploy 할 때, webpack 을 적용해 build 하도록 package.json 을 수정한다.

      {
    "scripts": {
    "build": "nest build",
    "deploy:lambda": "nest build --webpack --webpackPath src/lambda/webpack.config.js && sls deploy -c serverless.yaml"
    }
    }

Deploy: Serverless Framework

webpack 을 적용해 bundling 한 파일들이 Deploy 할 때 정확하게 업로드 될 수 있도록 한다.

  ...
functions:
handleConvertImage:
handler: dist/convertImage-bundle.handler
package:
individually: true
include:
- dist/convertImage-bundle.js
- dist/?-bundule.js
- dist/??-bundule.js
exclude:
- '**'
timeout: 900
memorySize: 1024
events:
- sns: XXXXXXXXX

handleBackupS3:
handler: dist/backupS3-bundle.backupUserHandler
package:
individually: true
include:
- dist/backupS3-bundle.js
- dist/?-bundule.js
- dist/??-bundule.js
exclude:
- '**'
timeout: 900
memorySize: 1024
events:
- schedule: cron(10 18 L * ? *)

handleStatisticsUsers:
handler: dist/statisticsUsers-bundle.handler
package:
individually: true
include:
- dist/statisticsUsers-bundle.js
- dist/?-bundule.js
- dist/??-bundule.js
exclude:
- '**'
timeout: 900
memorySize: 4096
events:
- schedule: cron(30 22 * * ? *)

handler

  • webpack 으로 생성된 파일명에 해당하는 handler 함수명을 지정
  • webpack.config.js 의 entry 의 key 에 해당하는 파일

include

  • webpack 으로 생성된 파일명을 지정한다.
    • [name]-bundle.js
  • ?-bundle.js
    • 간혹 webpack 의 LimitChunkCountPlugin 를 이용해도 파일이 분할(chunk)되는 경우가 있다.
    • [name]-bundle.js 의 경우, 분할된다면 [name] 에 숫자가 붙어 8-bundle.js10-bundle.js 등의 숫자 파일이 생성된다.
    • 이러한 파일들도 함께 include 해야하기 때문에 글자 수에 맞춰 ?-bundle.js 또는 ??-bundle.js 를 지정한다.
    • 소스코드가 길어질 경우에 분할 파일들이 생성될 수 있기에 반드시 해야하는 것은 아니다.