서버리스는 말그대로 서버가 없다라는 의미를 지니고 있다. 실제로 서버가 없다기 보다는 서버를 필요할때만 사용하는 개념이다.
개발자가 서버를 관리 해야하는 비중이 줄어든다는 장점이 있다.
aws가 알아서 scale-up을 진행하기 때문에 api 호출이 급작스럽게 늘어나도 aws에서 알아서 서버를 지원해준다.
서버리스의 장점을 가장 잘 나타내는 예시로, 쇼핑몰을 생각해보면 된다. 일반적으로 고객들은 저녁 시간 혹은 퇴근 이후의 시간에 쇼핑몰을 가장 많이 이용하고, 밤부터 출근 이전까지의 시간에 사용자가 가장 많이 줄어들게 된다. 가장 이용 횟수가 많은 저녁에 대비하여 여러대의 서버를 구매하는 경우 이용자가 적은 새벽에는 해당 서버들은 필요가 없어지게 된다.
이러한 점은 매우 경제적이지 못하기 때문에 서버리스를 사용하는 것이 좋다. 필요할때만 서버의 숫자를 늘리고 필요 없을때는 서버의 숫자를 자율적으로 줄이며, 사용한 시간만큼의 비용만 지불하게 된다면 경제적으로 서버를 사용할 수 있다.
단점은 서버가 필요할때만 사용되므로 cold-start라는 서버의 구동 시간이 존재한다는 점이다. 사용해보면 이 cold-start가 체감 가능할 정도로 느리진 않지만(토이프르젝트일 경우.. 실제 서비스는 콜드 스타트가 엄청 납니다), 프로그램이 무거워 질수록 cold-start의 시간은 늘어나기때문에 이 시간을 줄이기 위한 많은 plug-in과 개발 방법들이 존재한다.
또한 서버리스가 무조건 저렴하지는 않다. 이 서버리스의 사용 비용과 aws-cloudwatch등의 비용이 동시에 들기 때문에 가격이 꼭 저렴하지도 않다.
$ 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를 사용하여 자동으로 배포해보자.
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
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을 만드는 방법은 아래를 참고하면 편하다.
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 시크릿값
serverless-plugin-typescript typescript
https://www.serverless.com/plugins/serverless-plugin-typescript
서버리스 framework는 기본적으로 js 파일을 읽기때문에 typescript를 사용하는 경우 해당 plugin을 추가해줘야한다.
serverless-offline
https://www.serverless.com/plugins/serverless-offline
로컬 테스트를 진행할때 필요한 framework이다. sls invoke local 명령어를 사용해도 되지만 서버측 렌더링을 확인하고 싶다면 위 프레임워크를 활용하는 것이 좋다.
serverless-plugin-cloudwatch-dashboard
https://www.serverless.com/plugins/serverless-plugin-cloudwatch-dashboard
aws-logwatch를 사용하여 서버 로그를 확인 할 수 있다. 서버와 같이 가격이 매겨지므로 대용량 서비스일때의 aws 가격 계산도 함께 해야한다.
serverless-deployment-bucket
https://www.serverless.com/plugins/serverless-deployment-bucket
s3 버킷은 s3에 담을 객체에 대한 컨테이너이다. Bucket을 생성해야 s3에 zip 파일을 올려 api 호출을 진행할 수 있다.
serverless 실행 확인
//서버리스 로컬에서 배포 확인
$ serverless offline
//또는 sls offline 로 입력해도 된다.
//서버리스 aws 배포
$ serverless deploy
//또는 sls deploy 로 입력해도 된다.