Node.js

Express로 AWS Lambda에 REST API 배포하기

오늘은 express를 사용하여 serverless로 동작하는 lambda 에 배포 해보도록 하겠습니다.

 

왜 serverless를 선택했나?

일단 쓴 만큼만 서버를 이용하기 때문에 저같은 작은 프로젝트를 개발한다면 비용 절감이 가능합니다. 

또한 서버리스는 기본적으로 확장이 용이합니다. 제가 원하는 대로 더 늘리고 줄일 수 있어서 선택했습니다. 

아직 제 프로젝트에 무슨 기능이 들어갈지 다 정해지지 않아서요

하지만 단점도 있습니다.  

오래 실행되는 프로세스에는 적합하지 않아요. 동일한 가동 시간을 가정했을때 비교했을때 서버리스는 더 비쌉니다.

또한 중요한 요소인 속도가 느립니다. 이벤트 기반으로 호출되어 동작하기 때문에 컨테이너를 실행하는데 대기시간이 걸려서 느릴 수 밖에 없는거죠.

기능 자체가 작게 구분되어 있어서 보안에 문제가 있을 수 있는 것과 서버리스 환경 복제가 어렵기 때문에 테스팅 및 디버깅이 힘들 수 있다는 단점도 있습니다. 

그렇다면 이제 배포를 한번 시작해 보도록 하겠습니다.

 

1. aws cli 설치

일단 배포를 시작하기 전에 aws cli를 설치 해주세요.

aws 인증설정 까지 해주세요.

 

[AWS] 📚 AWS CLI 설치 & 등록 방법 - 쉽고 빠르게 설명

AWS CLI (Command Line) AWS Command Line Interface는 쉘 커맨드를 사용하여 AWS 서비스와 상호 작용할 수 있는 도구이다. 우리가 브라우저로 아마존 웹 서비스 홈페이지(콘솔 홈)에 가서 서비스를 이용한 것

inpa.tistory.com

 

 

2. serverless 설치

npm install -g serverless

serverless 프레임워크를 사용해서 복잡한 serverless 환경의 배포를 편하게 할 수 있습니다.

구동방식을 간략하게 설명하면 AWS의 CloudFormation이라는 서비스를 사용한다고 합니다.CloudFormation은 AWS내의 사용하고자 하는 서비스들을 YAML/JSON의 형태로 짜임새에 맞춰 선언 후 전달하면 해당 서비스들을 자동생성/삭제 등을 해주는 서비스라고 합니다.

 

3. 로컬 개발 환경을 위한 serverless-offline 설치

npm install serverless-offline --save-dev

배포 하지 않고도 local에서도 개발을 편리하게 할 수 있어요

 

4. typescript 사용을 위한 serverless-plugin-typescript 설치

설치함으로 typescript를 사용할 수 있게 됩니다.

yarn add --dev serverless-plugin-typescript typescript
# or
npm install -D serverless-plugin-typescript typescript

 

- express code

저는 간단한 게시판을 만들어보려고 하는데요. 

저는 serverless-http를 사용했습니다. 

serverless를 사용하지 않는 일반적인 express랑 export 하는 부분 빼고는 거의 다르지 않습니다.

여기서 제가 헤맸던건 cors 문제였는데요

(CORS(Cross-Origin Resource Sharing) :추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다.)

express 에서 cors를 먼저 적어주지 않으면 aws lambda로 배포 했을때 CORS 설정이 안먹는 경우가 생기더라구요.

물론 aws gateway로 CORS 설정을 하는 방법도 있습니다. 하지만 저는 벡엔드에서 CORS 설정하는 것이 더 편하다고 생각하여 코드내에서 해결했습니다.

이 부분에서 중요한 것은 CORS를 gateway에서 설정하던 express에서 설정하던 한가지 방법으로 하는 것입니다.

express와 gateway간 header 처리에 차이가 있을 수 있기 때문에 CORS 설정이 비정상적으로 이루어질 수 있기 때문입니다.

따라서 만약 전체적인 요청에 CORS 설정을 해야한다면 모든 lambda 함수에 일관된 CORS설정을 적용시킬 수 있으므로 gateway, 각각 다른 요청에 CORS를 설정해야 한다면 express에서 설정하는 것이 효율적입니다.

 

// src/index.ts
require("dotenv").config();
import express from "express";
import serverless from "serverless-http";
import cors from "cors";

const mongoose = require("mongoose");

import { boardRouter } from "./routes/board";

const app = express();

const corsOptions = {CORS설정};
app.use(cors(corsOptions));

mongoose
  .connect(MONGODB)
  .catch((err: Error) => console.log(err))
  .finally(() => console.log("success"));

app.use("/board", boardRouter);
export const handler = serverless(app);

 

serverless.yml 설정

serverless.yml 설정을 해주어야 합니다.

service: project

provider:
  name: aws
  runtime: nodejs18.x
  region: ap-northeast-2
  environment:
    NODE_ENV: production
    MONGO_DB_SRV:

functions:
  app:
    handler: src/index.handler
    events:
      - http:
          method: POST
          path: /board
      - http:
          method: GET
          path: /board/{proxy+}
plugins:
  - serverless-offline
  - serverless-plugin-typescript
custom:
  serverless-offline:
    httpPort: 8080

service: 프로젝트의 이름

provider: 어떤 클라우드 서비스 제공자에서 실행되는지 어떤 환경 변수를 가지는지 어떤 runtime을 가지는지 제공합니다.

environment에서는 사용할 환경변수를 적습니다. process.env를 제외한 부분만 써주면 됩니다.

function: 서버리스 어플리케이션에서 사용할 모든 개별 함수를 나열합니다.

app:부분은 이 함수의 이름이 app 이라는 뜻입니다.

handler는 실행할 코드의 경로를 써줍니다.

events는 트리거나 이벤트를 정의합니다. 

plugins 부분에서는 사용할 plugin들을 적어주면 됩니다.

custom에서는 로컬 개발 환경에서 사용할 serverless-offline의 포트 번호를 설정해 주었습니다.

 

이제  배포를 할 차례입니다.

sls deploy

를 입력하고 기다리게 되면 배포 성공이 뜨면서 

각각의 엔드포인트들을 보여줍니다. 

 

저는 처음에 아래 에러를 마주했는데요.

{
	"message": "Internal server error"
}

저는 위에서 말했던 CORS 문제와 

다른 plugin을 설정해 준 까닭에 코드가 제대로 작동하지 않았던 까닭입니다.

이 에러가 뜨는 이유는 다양한 이유가 있어서 

아래 api 로그를 보는 방법도 알아놓으면 좋을 것 같습니다.

 

HTTP API Lambda 통합 관련 문제 해결 - Amazon API Gateway

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com