본문 바로가기
개발/Nest.js

Nest.js serverless + AWS Lambda 배포하기

by jeounpar 2023. 3. 19.

소스코드 : https://github.com/jeounpar/nestjs-aws-lambda

1. nest 프로젝트 생성

$ nest new aws-lambda-test

 

2. serverless 모듈 설치

$ npm install -g serverless
$ npm install --save aws-serverless-express aws-lambda
$ npm install --save-dev serverless-plugin-typescript serverless-plugin-optimize serverless-offline plugin
$ serverless plugin install -n serverless-plugin-warmup

 

3. aws credential 설정

$ vi ~/.aws/credentials
# ~/.aws/credentials
[default]
aws_access_key_id=KEY_ID
aws_secret_access_key=ACCESS_KEY

 

4. 프로젝트 최상단에 serverless.yaml 파일 생성

service: aws-lambda-test

plugins:
  - serverless-plugin-typescript
  - serverless-plugin-warmup
  - serverless-offline

provider:
  name: aws
  region: ap-northeast-2
  runtime: nodejs16.x

functions:
  main:
    handler: src/lambda.handler
    events:
      - http:
          method: any
          path: /

 

5. src/lambda.ts 파일 생성

import { Handler, Context } from 'aws-lambda';
import { Server } from 'http';
import { createServer, proxy } from 'aws-serverless-express';
import { eventContext } from 'aws-serverless-express/middleware';
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import { AppModule } from './app.module';
import express from 'express';
const binaryMimeTypes: string[] = [];

let cachedServer: Server;

async function bootstrapServer(): Promise<Server> {
  if (!cachedServer) {
    const expressApp = express();
    const nestApp = await NestFactory.create(
      AppModule,
      new ExpressAdapter(expressApp),
    );
    nestApp.use(eventContext());
    await nestApp.init();
    cachedServer = createServer(expressApp, undefined, binaryMimeTypes);
  }
  return cachedServer;
}

export const handler: Handler = async (event: any, context: Context) => {
  cachedServer = await bootstrapServer();
  return proxy(cachedServer, event, context, 'PROMISE').promise;
};

lambda로 들어오는 request를 nest.js의 컨트롤러에 연결하기 위한 설정 파일

 

6. tsconfig.json 수정

{
  "compilerOptions": {
	...
    "tsBuildInfoFile": ".tsbuildinfo",
    "esModuleInterop": true
  }
}

 

7. serverless 테스트

$ serverless offline start

GET /dev

 

8. app.controller.ts & app.service.ts 코드 추가

// app.controller.ts
import { Controller, Delete, Get, Patch, Post, Put } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getTest(): string {
    return this.appService.getTest();
  }

  @Post()
  postTest(): string {
    return this.appService.postTest();
  }

  @Delete()
  deleteTest(): string {
    return this.appService.deleteTest();
  }

  @Put()
  putTest(): string {
    return this.appService.putTest();
  }

  @Patch()
  patchTest(): string {
    return this.appService.patchTest();
  }
}
// app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getTest(): string {
    return 'Get Test';
  }

  postTest(): string {
    return 'Post Test';
  }

  deleteTest(): string {
    return 'Delete Test';
  }

  putTest(): string {
    return 'Put Test';
  }

  patchTest(): string {
    return 'Patch Test';
  }
}

 

9. aws lambda 배포

aws CloudFormation -> s3 -> lambda -> API Gateway

$ serverless deploy

 

10. API 테스트

GET 테스트
POST 테스트
DELETE 테스트
PUT 테스트
PATCH 테스트

 

11. lambda 삭제

$ serverless remove