AWS Lambda에서 Express 사용하기

2021년 1월 1일

주의 ⛔️

  • 이 글이 작성된지 3년이 넘었어요.
  • 누구나 숨기고 싶은 흑역사가 있답니다.

기존 람다 함수에서 느낀 불편한 점

기존에 express같은 웹 프레임워크를 쓰다가 Lambda로 넘어오게 되니 많은 문제점을 만났습니다.

그 중에서 가장 크게 불편했던 점이 라우팅과 관련된 코드를 다 짜줘야 한다는 것이었습니다. 예를 들면,

if (path === "/") { ... }

이런 코드들을 계속 만들어야 합니다. 각 path 별로 람다 함수를 하나씩 만들어 붙일게 아니라면 말이죠..(예전에 그렇게 했었는데, 너무 비효율적이라고 생각합니다..)

거기다 request parameter validation나, 여러 당연한 기능들을 추가하려고 하면.. 지금보다 더 복잡해질 것 같았습니다.

이런 문제점 때문에 회사에서는 따로 사내 프레임워크를 개발해서 쓰고있긴 한데, 개인 프로젝트에는 회사의 손길(?)이 닿지 않길 바랬습니다.

그래서 저에게 익숙한 express를 AWS Lambda와 연결할 수 있는 방법을 찾아보게 되었습니다.

aws-serverless-express

다행히도, aws-serverless-express라는 람다 함수 핸들러와 express 코드를 연결해주는 라이브러리가 있었습니다.

지금은 그것이 @vendia/serverless-express로 옮겨졌지만, type definitions 문제 때문에 기존의 라이브러리를 사용하게 되었습니다.

aws-serverless-express는 express의 사용법에 변화를 주지 않기 때문에, AWS Lambda와 함께 기존 사용법 그대로 사용할 수 있습니다.

따라서, 기존에 실시간으로 실행시키던 express 코드를 손쉽게 AWS Lambda로 마이그레이션 할 수도 있습니다.

혹여나 API Gateway에서 람다 함수에 넘겨주는 event 객체에 대한 접근이 필요한 경우, x-apigateway-event 헤더에 url encoding되어 있으므로, 이를 decode하고 파싱해서 사용하거나, aws-serverless-express에서 함께 제공하는 middleware를 통해 쉽게 접근할 수 있습니다.

적용

우선 매우 간단한 express 코드부터 작성해줍시다.

import * as express from "express";

const app = express();

app.get("/hello", (req: express.Request, res: express.Response) => {
  return res.status(200).json({ message: "world" });
});

export { app };

그리고 작성한 코드를 import해서 aws-serverless-express에 연결해주면 됩니다.

import * as serverlessExpress from "aws-serverless-express";
import { APIGatewayProxyHandler } from "aws-lambda";

import { app } from "./app";

const server = serverlessExpress.createServer(app);

export const handler: APIGatewayProxyHandler = (event, context) => {
  serverlessExpress.proxy(server, event, context);
};

실행

이제 테스트를 해볼텐데, 이럴 때 굳이 배포하지 않아도 로컬에서 확인해볼 수 있도록 도와주는 serverless-offline이라는 플러그인이 있습니다.

serverless 프레임워크에 대해서는 이전 게시물을 참고해주세요.

플러그인을 설치하고, package.json의 scripts에 커맨드를 하나 추가해줍시다.

npm install -D serverless-offline
"scripts": {
  "start": "serverless offline"
},

그리고 npm start를 입력해주고 조금 기다리면 로컬 환경에서 테스트할 수 있게 됩니다.

result 1

결과

응답이 잘 오네요!

result 2