Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

Serverless 플랫폼 소개

클라우드는 외부에서 관찰할 경우 하나의 거대한 컴퓨팅 리소스로 묘사 할 수 있다. 개발자는 적당량의 CPU, 메모리, 디스크를 빌려서 서비스를 구축한다는게 대략적인 개념이다. 클라우드를 "기존의 컴퓨팅 파워를 빌려서 쓰는 것"으로 좁게 정의하면 IaaS, "컴퓨팅 파워 빌려다 쓰는 것도 귀찮다" 그냥 그 컴퓨팅 파워에다가 너희가 소프트웨어를 올려서 사용할 수 있게 해달라라는 관점으로 좀더 나가면 SaaS 가 된다. 아래 그림을 보자.

 IaaS, SaaS, PaaS

그림은 On-Premises(직접 구축)과 IaaS, PaaS, SaaS 의 차이점을 보여주고 있다. 기본적으로 소프트웨어를 올리기 위한 구성요소가 바뀌는 것은 없다. 어디까지를 클라우드 서비스 제공자에게 위임할 것인지에 따른 차이가 있을 뿐이다. SaaS는 구축할 필요 없이 사용만 하면 되는 점에서 ASP(Application Service Provider)와 유사한 측면이 있다.

인터넷 서비스 개발자들이 실질적으로 사용하는 영역은 IaaS와 PaaS 정도가 될 것이다. 그 중에서도 여전히 IaaS는 우선적으로 생각하게 되는데, 서비스 개발을 위해서는 CPU와 메모리, 디스크에 대한 어느 정도의 유연성을 가질 필요가 있기 때문이다. IaaS 기반에서 개발 노하우가 충분히 쌓였다는 점도 무시 할 수 없는 부분이다.

그렇다면 IaaS에서 CPU와 메모리, 디스크에 대한 관리를 빼면 어떨까 ? 즉 서버를 없애면 좀 더 서비스 개발환경이 유연해지지 않을까 해서 나온 모델이 serverless 모델이다. 인터넷 애플리케이션의 주요 모델인 "서버/클라이언트" 모델에서 클라이언트가 관심 있는 것은 "서버 애플리케이션"이지 서버 그 자체가 아니다. 논리적으로는 클라이언트가 요청을 하면 서버 애플리케이션이 응답하면 되는 것이다.

예를들어 "Hello World" 서비스를 개발한다면, 개발자는 그냥 "Hello world"를 출력하는 함수만 만들면 그만인 것이다. Serverless 플랫폼의 컨셉은
  1. 메모리, CPU, Disk는 저희가 관리하겠습니다.
  2. 개발자는 그냥 코드만 올려주세요.
가 돼겠다.

이러한 serverless 플랫폼은 크게 두 가지 타입으로 나눌 수 있다.
  1. FaaS : Function as a Service. "개발자는 코드(기능 펑션)만 올려주십쇼"하는 타입이다. AWS Lambda, Azure Functions, Google Cloud Function등이 있다.
  2. BaaS : Backend as a Service. "클라이언트(모바일) 애플리케이션을 개발한다고요 ? 백앤드 서비스가 필요하죠 ? 저희가 만들어드리겠습니다" 하는 타입이다. Firebase, Kinvey 등의 서비스가 있다. 이들 서비스는 사용자관리, 접속제어, 푸시 알림, 데이터 저장, SNS, 위치 서비스등의 백앤드 기능을 제공한다.
이 문서에서는 FaaS를 다룰 것이며 그 중에서 AWS Lambda를 기준으로 다룰 것이다.

환경

Serverless 애플리케이션 개발 플랫폼

AWS SAM Local serverless framework를 주로 사용하는 것 같다. AWS SAM Local 보다는 serverless framework가 더 낫다는 글들이 많이 보인다. 그래서 serverless framework로 시작하기로 했다.

AWS Lambda를 이용한 Event Driven serverless Architecture

Lambda는 이벤트 드리븐 아키텍처를 구현하는데 적합한 서비스다. 이벤트 드리븐 아키텍처는 어떤 이벤트 소스로 부터 이벤트가 발생 했을 때, 기능(함수)를 호출하는 방식이다. 즉 데이터베이스에 레코드가 추가됐을 때, 로그가 발생했을 때, HTTP 요청이 들어왔을 때, 파일이 만들어졌을 때 이들 정보를 이벤트로 받아서 처리하는 함수를 호출하는 식이다.

아래는 이벤트 드리븐 방식으로 이미지 처리를 하는 애플리케이션의 예제다.

 서버리스 프레임워크

Application, S3, DynamoDB가 Event Source가 된다.
  1. 사용자가 Application Load Balancer(혹은 API gateway)로 REST API(HTTP Request)를 호출하면, 이벤트가 발생한다. 이미지를 업로드를 위해서 GET API를 호출 한다.
  2. Lambda가 호출 된다. Lambda는 S3 API를 호출해서 upload 권한을 가진 presigned url을 리턴한다. 동시에 DynamoDB에 이 정보를 Insert 한다. ready 상태 정도가 될 것이다. DynamoDB는 레코드에 대해서 TTL 설정을 할 수 있다.
  3. 사용자는 presigned url를 이용해서 s3에 file을 업로드 한다.
  4. 파일이 업로드 되면, Lambda가 호출된다. 섬네일을 만들거나 등등의 작업을 수행한다. 작업이 끝나면 DynamoDB 정보를 Update 한다. 작업 완료 상태가 될 것이다.
  5. DynamoDB는 Update Event를 받아서 Lambda를 호출한다. Lambda는 SNS API를 호출, 클라이언트에 통지하거나 등등의 작업을 수행한다.

Serverless framework

Serverless framework는 serverless 기업에서 제공하는 Serverless framework다. Serverless framework는 serverless 애플리케이션의 개발, 테스트, 배포, 모니터링을 할 수 있는 통합된 환경을 제공한다.

serverless framework 설치

serverless를 설치한다.
# node --version
v10.15.2

#  npm --version
5.8.0

# npm install -g serverless

Serverless 서비스 생성 및 전개
serverless framework가 지원하는 언어(혹은 플랫폼)은 node.js, python, golang, C#, Java를 지원한다. 나는 go언어를 사용한다. 아래와 같이 go 언어 기반의 서비스를 만든다>
# serverless create -t aws-go-dep -p helloworld

Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/home/yundream/workstation/helloworld"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.58.0
 -------'

Serverless: Successfully generated boilerplate for template: "aws-go-dep"

서비스 디렉토리로 이동해서 애플리케이션을 컴파일해보자. 컴파일 전에 주요 패키지를 설치했다.
# cd helloworld
# go get github.com/aws/aws-lambda-go/events
# go get github.com/aws/aws-lambda-go/lambda
# make
env GOOS=linux go build -ldflags="-s -w" -o bin/hello hello/main.go
env GOOS=linux go build -ldflags="-s -w" -o bin/world world/main.go

# serverless deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
........
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service helloworld.zip file to S3 (6.17 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
................................................
Serverless: Stack update finished...
Service Information
service: helloworld
stage: dev
region: us-east-1
stack: helloworld-dev
resources: 17
api keys:
  None
endpoints:
  GET - https://gvgmz7mye2.execute-api.us-east-1.amazonaws.com/dev/hello
  GET - https://gvgmz7mye2.execute-api.us-east-1.amazonaws.com/dev/world
functions:
  hello: helloworld-dev-hello
  world: helloworld-dev-world
layers:
  None
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.
<Paste>
  • stage : 프로젝트 배포는 dev, qa, stage, product 등의 여러 단계(stage)를 가지기 마련이다. 이러한 단계는 개발/테스트/배포 환경을 만드는 데 유용하다. 이 애플리케이션은 "dev" 단계다. 애플리케이션들이 dev 단계에 배포되면 기본적인 테스트를 끝내고 QA나 Stage 단계로 넘어갈 것이다.
  • region : .aws/config의 설정과 상관없이 us-east-1이 기본으로 잡힌다. "serverless.yml"을 수정해서 region을 변경할 수 있다. 어쨋든 명령 한번에 지구 반대편에 사용할 수 있는 API가 전개되다니 놀라운 세상이다.
  • resources : 람다 애플리케이션이 사용하는 리소스다. AWS의 경우 DynamoDB, ELB, AWS S3와 같은 것들이 리소스가 된다.
  • api keys : REST API가 비공개로 제공할 경우 사용한다. serverless.yml에 api key 목록을 설정 할 수 있는데, 이렇게 하면 api key를 가지고 있는 사용자만이 API를 사용 할 수 있도록 제어 할 수 있다.
  • endpoints : API 호출 endpoint
테스트를 하고 위 결과를 분석해보자.
# curl https://gvgmz7mye2.execute-api.us-east-1.amazonaws.com/dev/hello -i
	HTTP/2 200 
		content-type: application/json
		content-length: 70
		date: Tue, 26 Nov 2019 03:47:27 GMT
		x-amzn-requestid: 488ed1ae-5791-4425-b6ba-0bbeb57cd761
		x-amz-apigw-id: Dv38fGsQoAMF8ww=
		x-mycompany-func-reply: hello-handler
		x-amzn-trace-id: Root=1-5ddca04f-a3c8ce90c3a08b6e70a435da;Sampled=0
		x-cache: Miss from cloudfront
		via: 1.1 32e89bf2264b92d268f51f4eb961f18c.cloudfront.net (CloudFront)
		x-amz-cf-pop: ICN55-C1
		x-amz-cf-id: n0ds4MzsR3070CUtKW05S4kjVEpzx3xNrJC8sN4tbXqzCRNee_6nCA==

		{"message":"Go Serverless v1.0! Your function executed successfully!"}
  • x-amz-apigw-id : AWS API Gateway의 식별번호
  • x-mycompany-func-replay: 요청을 처리한 핸들러 이름
  • x-amzn-trace-id : 요청에 대한 유일한 식별자로 이 값을 이용해서 클라이언트의 요청을 추적 할 수 있다.
아주 아주 간단하게 API를 배포할 수 있었다.

약간 더 복잡한 애플리케이션 제작

DynamoDB를 Event Source로 하는 애플리케이션을 만들어보려 한다. 이 애플리케이션은 아래와 같이 작동한다.

 예제 프로그램

  1. 어떤 정보를 포함한 레코드를 게시한다.
  2. 레코드가 게시되면 Lambda 코드가 실행된다. Lambda 코드는 ElasticCache에 레코드가 게시됐음을 Publish 한다.
  3. Subscriber가 게시된 메시지를 읽는다.
경매 시스템이라고 가정해보자. 상품을 게시하면 이 정보는 데이터베이스에 들어가고, 구독자에게 게시될 것이다. 게시가 되고 구독자들이 액션을 취할 때 마다 상품 게시자에게 이 정보가 전달된다. 게시자가 마음에 드는 경매신청을 접수하면 경매가 종료되고 다음 단계에 진입 할 것이다.

이 과정에서 데이터베이스에 있는 정보가 변경될 것이다. 기존 방식이라면 유저가 호출한 API가 비지니스로직을 처리하고 데이터베이스를 업데이트 하는 식으로 개발을 할 것이다. 이벤트 기반 시스템에서는 이벤트 소스인 데이터베이스를 기준으로 호출과 처리가 분리된다.

.... 계속

Event Router

.... 계속