Node JS & Serverless 배포

Alli_Eunbi·2022년 8월 9일
2
post-custom-banner

Serverless를 사용하는 이유

서버리스는 말그대로 서버가 없다라는 의미를 지니고 있다. 실제로 서버가 없다기 보다는 서버를 필요할때만 사용하는 개념이다.
개발자가 서버를 관리 해야하는 비중이 줄어든다는 장점이 있다.
aws가 알아서 scale-up을 진행하기 때문에 api 호출이 급작스럽게 늘어나도 aws에서 알아서 서버를 지원해준다.
서버리스의 장점을 가장 잘 나타내는 예시로, 쇼핑몰을 생각해보면 된다. 일반적으로 고객들은 저녁 시간 혹은 퇴근 이후의 시간에 쇼핑몰을 가장 많이 이용하고, 밤부터 출근 이전까지의 시간에 사용자가 가장 많이 줄어들게 된다. 가장 이용 횟수가 많은 저녁에 대비하여 여러대의 서버를 구매하는 경우 이용자가 적은 새벽에는 해당 서버들은 필요가 없어지게 된다.
이러한 점은 매우 경제적이지 못하기 때문에 서버리스를 사용하는 것이 좋다. 필요할때만 서버의 숫자를 늘리고 필요 없을때는 서버의 숫자를 자율적으로 줄이며, 사용한 시간만큼의 비용만 지불하게 된다면 경제적으로 서버를 사용할 수 있다.

단점은 서버가 필요할때만 사용되므로 cold-start라는 서버의 구동 시간이 존재한다는 점이다. 사용해보면 이 cold-start가 체감 가능할 정도로 느리진 않지만(토이프르젝트일 경우.. 실제 서비스는 콜드 스타트가 엄청 납니다), 프로그램이 무거워 질수록 cold-start의 시간은 늘어나기때문에 이 시간을 줄이기 위한 많은 plug-in과 개발 방법들이 존재한다.
또한 서버리스가 무조건 저렴하지는 않다. 이 서버리스의 사용 비용과 aws-cloudwatch등의 비용이 동시에 들기 때문에 가격이 꼭 저렴하지도 않다.


Serverless FrameWork 활용

$ yarn global add serverless

$ yarn add @vendia/serverless-express aws-lambda
$ yarn add -D @types/aws-lambda serverless-offline

serverless 프레임워크를 install 해준다. 서버리스 framework를 사용하지 않고 직접 aws에 파일을 압축하고 api gateway를 등록하는 등 수동적인 방법은 있지만, 작성자는 시도하다 포기했다. 여간 귀찮은 방법이 아니다. framework를 사용하여 자동으로 배포해보자.

  • serverless.yml은 아래와 같이 입력해준다.
    service 이름은 project 이름으로 주었다.
    plugins는 다양하게 설정 가능하다.
service: alarmie
frameworkVersion: '3'

plugins:
  - serverless-plugin-optimize
  - serverless-offline
  - serverless-plugin-typescript
  - serverless-plugin-cloudwatch-dashboard
  - serverless-deployment-bucket

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

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

custom:
  enable_optimize:
    local: false
  • lambda.ts를 아래와 같이 입력해준다.
    lambda는 handler라는 함수를 가지고 있다. 이 handler는 반드시 export되어야 한다.
    handler는 실행하려는 코드가 포함된 파일 및 모듈을 가리킨다.
// 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 "./src/app.module"

const express = require("express")

// NOTE: If you get ERR_CONTENT_DECODING_FAILED in your browser, this is likely
// due to a compressed response (e.g. gzip) which has not been handled correctly
// by aws-serverless-express and/or API Gateway. Add the necessary MIME types to
// binaryMimeTypes below
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.enableCors()
        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
}

AWS Iam 자격증명 만들기

aws Iam을 만드는 방법은 아래를 참고하면 편하다.
https://www.youtube.com/watch?v=KngM5bfpttA

그리고 나서 만든 iam에 lambda 함수, s3, cloundformation, cloudwatch등의 권한을 부여하면 해당 iam을 활용하여 serverless framework가 aws에 api gateway 생성, s3 파일 업로드 등 대부분의 역할을 수행해준다.

여기서 권한 추가 버튼을 클릭 하고 들어가서 "기존 정책 직접 연결"에 들어가 필요한 권한들을 검색하여 추가하면 된다.
귀찮으면 AdministratorAccess를 주면 모든 것에 권한이 주어지니 그걸 부여해주면 된다.

사실 이러한 모든 권한에 access에 접속 가능한 admin은 남발하면 안된다. 하지만 toy project이기도 하고 개인 계정이므로 사용하기로 한다.

유튜브를 참고했다면, 아래 명령어를 사용하여 iam의 secret-key를 입력해주면 된다. 이렇게 되면 serverless framework가 자체적으로 iam에 접근하여 배포 과정을 수행해준다.

serverless config credentials --provider aws --key 키값 --secret 시크릿값

추가하면 좋은 plugin


serverless 실행 확인

//서버리스 로컬에서 배포 확인
$ serverless offline
//또는 sls offline 로  입력해도 된다.

//서버리스 aws 배포
$ serverless deploy
//또는 sls deploy 로  입력해도 된다.

에러사항

  1. serverless가 handler를 찾지 못했다, 혹은 lambda 모듈을 찾지 못했다는 에러를 뱉는 경우,
    : handler 위치 확인
    lambda.ts 에 있는 handler를 호출 해야하므로 serverless.yml에 lambda.handler로 입력 되어 있는지 확인 하고, lambda.ts의 파일이 프로젝트 루트 경로에 있는지 확인 해야한다. 혹시나 lambda.ts에 handler가 export 되어 있는지도 한번 확인 해보자.
    작성자의 경우, lambda.ts가 project/src/lambda.ts 경로에 있었기 때문에 작동하지 않았다.

  1. serverless가 offline에서는 작동하나 sls deploy를 진행하면 403 혹은 502에러를 뱉는 경우,
    : node 버전이 일치하는지 확인
    작성자의 경우 serverless.yml의 노드버전과 프로젝트의 node version이 달라서 에러가 났다.
profile
BACKEND
post-custom-banner

0개의 댓글