본문 바로가기
IT

[AWS] 서버리스 프레임워크란? (serverless framework)설치부터 배포까지 (node.js)

by 용용 blog 2021. 9. 27.

Provider: AWS(Amazon Web Service)
작업환경: macOS(Mojave, 10.14.6

서버리스(Serverless)란?


 

요즘 이곳저곳에서 MSA(Micro Service Architecture)가 관심이 많아지고 있다.

이에따라 MSA를 편리하게 구현시킬 수 있는 클라우드환경이 주목을 받고있다.

 

기존의 방식으로 간단하게 설명하자면 어느 서비스를 배포하려면 항시 "서버"가 필요하게 된다.

하지만 그 서버에 대한 개선/유지보수에 대한 인프라적인 문제는 필히 남기 마련이다.

e.g. 트래픽이 많아져서 서버를 증설해야겠어요, 조금 더 좋은 서버로 업그레이드 하고 싶어요 등등..

 

이런 인프라적인 문제를 해결하고자, 서버(server)가 없다(less)의 의미로 자리잡은 단어가 서버리스이다.

정말 서버가 존재하지 않고 서비스를 구동할 수 있느냐? 아니다. 서버는 존재하지만, 개발자는 신경쓰지 않아도 된다. 제공사가 그런 부분을 커버해주기 때문이다.

 

AWS(Amazon Web Service)를 기준으로 조금 더 상세하게 설명하자면 EC2 인스턴스로 서버를 생성하여 그 안에 서비스를 배포하는 방식이 아닌, ApiGateway + Lambda 로 서비스를 배포하는 것이다.

 

Client(유저)의 입장에서 보면 요청을 보낼 곳(ApiGateway)과 로직이 실행될 곳(Lambda)만 있으면 되는 것이다.

(물론 Database, Queue, Cache등의 상세내용은 생략한다. AWS의 서비스들로 구성만 하면 되는 문제이니까)

 

이러한 서버리스를 개발할 수 있는 방법은 여러가지가 있다.

 

  1. AWS Console로 한땀 한땀 개발 (ApiGateway 생성, Lambda 생성...)
  2. AWS SAM(Serverless Application Model)
  3. Serverless Framework
  4. 등등

 

위의 방법중 "Serverless Framework"를 이용하기로 하자

 

 

 

Serverless Framework


Serverless Framework는 보편화되어 많은 개발자분들이 사용하는 서버리스 프레임워크이다.

 

구동방식부터 생각을 해보면, 결국 AWS의 CloudFormation이라는 서비스를 이용하는 것이다.

(CloudFormation은 AWS내의 사용하고자 하는 서비스들을 YAML/JSON의 형태로 짜임새에 맞춰 선언 후 전달하면 해당 서비스들을 자동생성/삭제 등을 해주는 서비스라고 생각하면 편하다. 자세한 내용은 docs를 참조한다)

 

실제 CloudFormation에 전달하는 YAML/JSON형태는 러닝커브가 꽤 높아보인다.

이러한 어려움을 Serverless Framework를 사용하면 보다 쉽게 CloudFormation을 이용할 수 있다.

(후일담이지만 원하는 여러 서비스들을 엮으면서, 서버리스 프레임워크에서 지원하지 않는 서비스들의 영역을 만지려는 순간.. 자연스럽게 CloudFormation의 원본 YAML/JSON형태를 작성하게 된다. 서버리스 프레임워크의 지원범위는 지속적으로 늘어나고있으며, 여러 라이브러리가 대체해주고 있다)

 

자 이제 서버리스 프레임워크를 이용하여, Hello-world를 한번 출력해보기로 하자

 

 

 

사전준비


Node.js

서버리스 프레임워크의 지원 애플리케이션은 nodejs, python, java, kotlin, typescript, csharp 등 많은 언어를 지원하지만, nodejs를 선택해서 진행해 보도록 한다. 마찬가지로 설치방법은 생략한다

 

Npm

yarn을 사용해도 되지만, npm으로 진행하도록 한다. Node.js를 설치하면 같이 설치된다

 

Serverless Framework

$ npm i serverless -g

npm을 이용하여 serverless를 설치한다

 

 

 

템플릿(Hello-world)을 통하여 배워보기


작업 경로는 /eduspace 라고 가정한다
작업 툴은 VSCode를 이용한다

 

사전준비를 통하여 서버리스 프레임워크를 이용할 준비가 되었으니, Hello-world 프로젝트를 통하여 어떻게 구동되는지 알아보도록 하자

 

서버리스에서는 프로젝트를 생성할 때 템플릿을 지정하여 생성할 수 있다. 지원되는 템플릿 중 "hello-world"를 사용하도록 한다.

(지원되는 템플릿을 확인하고 싶다면 "sls create —template"를 입력하면 볼 수 있으며, 자세한 CLI에 대한 정보는 링크를 참조한다)

 

 

프로젝트 생성

# serverless 커맨드를 sls로 줄여 사용할 수 있다

# 'create' command Options
# --template(-t) 템플릿을 지정한다
# --template-url(-u) 템플릿 URL을 지정한다
# --template-path 로컬 템플릿 경로를 지정한다
# --path(-p) 프로젝트가 생성될 경로를 지정한다
# --name(-n) 서비스명을 지정한다

$ sls create --template hello-world --path hello-world

Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/mac/Documents/eduspace/hello-world"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.64.1
 -------'

Serverless: Successfully generated boilerplate for template: "hello-world"

 

 

프로젝트 오픈

# VSCode를 이용하여 해당 프로젝트 폴더를 오픈한다
code hello-world/

mac환경에서 'code' 커맨드가 실행되지 않으면 링크를 참조하여 설정한다

 

 

프로젝트 구조

$ tree
.
└── hello-world
    ├── handler.js
    └── serverless.yml

hello-world 프로젝트의 내용은 간단하다. 서버리스 프레임워크의 가장 기본이 되는 "serverless.yml" 파일과 람다에서 구동시킬 실행로직이 담긴 handler.js 가 존재한다.

각 파일들을 상세히 확인해보자

 

 

serverless.yml

# 이 프로젝트의 서비스명
service: hello-world

# 공급자정보
provider:
  name: aws
  runtime: nodejs12.x

# 로직(Lambda)
functions:
  helloWorld:
    handler: handler.helloWorld
    events:
      - http:
          path: hello-world
          method: get
          cors: true

먼저 Serverless framework를 이용하면서 가장 중심이 되는 yml 파일이다

 

공급자 정보에는 사용하는 공급자인 AWS을 작성하고(필수), 람다 들의 런타임은 무엇으로 지정할지 선언한다.

아래에 생성될 람다들에 대해서 공통적인 사항들을 적어 놓는다고 할 수 있다. (공통 람다 메모리 사이즈, 공통 람다 부여 권한, 리전정보, 스테이지정보 등등)

 

로직에는 functions 아래에 들어가는 함수 하나하나가 람다(lambda)라고 생각하면 된다. 람다의 로직은 생성된 핸들러를 연결시킨다. hello-world 예제 에서는 handler.js 를 연결한다고 볼 수 있다

 

추후 'sls deploy' 명령어를 통해서 배포 처리 하게되면, 위의 serverless.yml 파일을 기준으로 CloudFormation에게 전달할 파일을 생성하여 전달한다고 생각하시면 된다

 

(현재 지원되고 있는 serverless.yml 스펙을 확인하고 싶으시면 링크를 통해 확인하세요)

 

 

handler.js

'use strict';

module.exports.helloWorld = (event, context, callback) => {
  const response = {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*', // Required for CORS support to work
    },
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!',
      input: event,
    }),
  };
s
  callback(null, response);
};

일반적인 Node.js 문법으로 정의된 메시지를 리턴하는 로직이다

 

 

로컬에서 확인

$ sls invoke local --function helloWorld

{
    "statusCode": 200,
    "headers": {
        "Access-Control-Allow-Origin": "*"
    },
    "body": "{\"message\":\"Go Serverless v1.0! Your function executed successfully!\",\"input\":\"\"}"
}

serverless.yml의 functions에 정의된 이름의 함수를 로컬에서 구동시키는 명령어를 실행해보니, handler.js에 지정된대로 리턴된 것을 볼 수 있다.

(서버리스 프레임워크의 명령어는 링크에서 자세히 확인할 수 있다)

 

 

배포 처리

$ sls deploy --stage dev --region ap-northeast-2 -v

위의 한개의 함수(helloWorld)가 담긴 프로젝트를 실제로 AWS에 등록하여 확인해보도록 하자

 

위의 명령어는 배포명령어를 실행하되, 스테이지는 dev, 배포리젼은 ap-northeast-2(서울)이며 상세내용을 표시해달라는 명령어이다.

(기본스테이지와 배포리젼은 serverless.yml 파일에 provider에 입력하면 적지 않아도 된다)

 

위의 명령어를 입력하면 아래와 같은 결과를 볼 수 있다

 

 

 

 

 

 

 

 

serverless.yml 파일에 helloWorld라는 함수(Lambda) 한개만 넣었음에도 상세내용을 모두 표기하는 옵션을 입력하니 꽤 많은 내용의 일을 한다고 볼 수 있다.

 

위의 배포내용을 간략하게 정리하면 아래와 같다.

  1. serverless.yml 파일을 토대로 cloudformation에 전달할 내용 패키징 (.serverless 폴더에 담김)
  2. 해당 파일을 S3로 올려야하니 S3 버킷 생성 (미리 생성된 S3버킷을 지정하면 해당 버킷으로 담깁니다)
  3. 생성된 S3 버킷에 접근권한(Policy) 적용
  4. 서비스 배포를 위한 CloudFormation stack 생성 (serverless 한개의 서비스당 한개의 stack을 가진다고 보면 됩니다)
  5. 제작된 람다의 퍼블릭 접근 경로 (endpoint)가 필요하니 ApiGateway를 생성
  6. 람다의 실행로그를 위해 로그그룹 생성
  7. 로그적재 등의 권한을 가진 람다권한생성 및 람다에 적용
  8. ApiGateway가 람다에 접근할 수 있도록 퍼미션 설정
  9. 람다의 지정된 접근경로를 ApiGateway에 리소스로 생성 및 연결
  10. 완성된 ApiGateway + Lambda 세트 배포 처리

 

위의 내용을 보니 Serverless Framework(혹은 CloudFormation)가 얼마나 많은 일을 대신 해주는 것인지 확인 할 수 있다

 

 

배포결과 확인

$ sls invoke --function helloWorld

{
    "statusCode": 200,
    "headers": {
        "Access-Control-Allow-Origin": "*"
    },
    "body": "{\"message\":\"Go Serverless v1.0! Your function executed successfully!\"}"
}

아까와는 다르게 local 을 뺀 invoke 명령어를 사용하면 실제 AWS에 올라간 함수를 실행시켜 리턴값을 보여준다

 

$ curl -GET https://xxxxxxxxxx.execute-api.ap-northeast-2.amazonaws.com/dev/hello-world

배포시에 배포가 완료된 후 Endpoint를 알려주는데 이 경로로 직접 curl 명령어를 통하여 확인할 수도 있다

(기본 handler.js에서 요청입력값도 반환되게끔 리턴값이 설정되어있어서, 직접 curl 같은 것으로 요청하게되면 꽤 긴 내용이 리턴된다. 당황하지말자)

 

 

배포 삭제

$ sls remove --stage dev --region ap-northeast-2 -v

배포 삭제 처리는 개념상으로 "CloudFormation의 Stack을 삭제해라"라고 볼 수 있다

그러하여 해당 스택에서 생성한 모든 리소스를 자동적으로 삭제 처리 된다.

그렇다는 말은 추후 데이터베이스와 같은 삭제되지 않아야 하는 리소스의 관리를 잘 해야 한다는 말이다

 

위의 명령어를 입력하면 아래와 같은 결과를 볼 수 있다

 

 

 

 

 

 

생성처리 된 리소스를 모두 지운 후 완료되는 모습을 볼 수 있다

 

 

 

 

 

정리


지금까지 Serverless Framework를 살펴보았다

 

환경설정 및 간단한 제공 템플릿으로 서버리스가 어떻게 구성되어 돌아가는지에 대한 정보를 확인할 수 있었으며 개발자들이 로직에 집중하기 위하여 정말 많은 부분이 자동화되고 있는 것을 느꼈다

 

잘만 구성해서 사용하면 MSA식의 개발도 잘 구성되며, 특히 인프라의 구성이 유연해질 것 같다. 반대로 인프라 생성이 자유로워짐에 따라서 삭제되지 않아야 하는 리소스들의 대한 엄격한 관리가 필요할 것 같다 (Retain옵션이라던가, CloudFormation의 StackPolicy를 통한 삭제정책 등등)

 

서버리스 프레임워크도 큰 맥락에서 보면 "AWS CloudFormation"이라는 서비스를 "이용할 뿐" 이라는 생각도 든다

간단한 예제를 통하여 구동방식만 확인하는 목적덕에, 직접적인 코드수정과 플러그인의 연계등은 작성할 수 없었지만 이 글을 토대로 추가적인 연계내용들을 다른 글들을 통해 작성할 수 있을 것 같다

 

 

 

 

 

참고


 

https://www.serverless.com/

 

Serverless: Develop & Monitor Apps On AWS Lambda

Easily develop and monitor auto-scaling applications on AWS Lambda, API Gateway, DynamoDB, etc., with the Serverless Framework and Serverless Monitoring Dashboard.

www.serverless.com

https://docs.aws.amazon.com/cloudformation/index.html

 

https://docs.aws.amazon.com/cloudformation/index.html

 

docs.aws.amazon.com

 

'IT' 카테고리의 다른 글

[AWS] Codebuild 로컬에서 빌드 테스트 하기  (1) 2021.09.28

댓글