SAM을 통해 AWS Lambda의 NodeJs Express

나는 NodeJS를 좋아하고 Express는 편리하고 사용하기 쉽고 가볍습니다. 요즘 Python과 Flask를 선택하는 경향이 있지만 직장과 개인 프로젝트에서 이것을 사용했습니다. Express에 대해 제가 좋아하는 점은 동일한 프로젝트에서 프론트엔드(및 SSR 콘텐츠)와 API를 호스팅할 수 있다는 것입니다. PoC 또는 소규모 사이트/애플리케이션을 구축하는 경우 이는 완벽하게 이해됩니다.

약 1년 전에 로컬"AWS Programming and Tools" Meetup을 위한 랩을 구축하면서 localstack과 Dynamo를 사용하여 작은 데모를 구축했습니다. Scrumbler의 적응을 구축하는 팀에서 몇 가지 문제가 있으므로 Express의 간단한 예를 작성하고 SAM 템플릿으로 래핑하고 AWS Lambda에 배포했습니다.

이 설정은 단순히 @vendia/serverless-express을 람다의 래퍼/프록시로 사용했습니다. 이러한 방식으로 핫 리로딩으로 로컬에서 개발하고 Lambda로 변경하지 않고 동일한 코드를 푸시할 수 있습니다.

2개의 진입점이 있습니다.
  • 로컬(app.local.js)

  • const app = require('./app')
    const port = 3000
    app.listen(port)
    console.log(`listening on http://localhost:${port}`)
    


    그리고
  • 람다.js

  • const serverlessExpress = require('@vendia/serverless-express')
    const app = require('./app');
    
    exports.handler = serverlessExpress({ app })
    


    그리고 물론 애플리케이션 자체도 마찬가지입니다. 이 애플리케이션은 간단하고 작으며 모두 하나의 파일( app.js )에 있습니다.

    const express = require('express')
    const app = express()
    const router = express.Router()
    const bodyParser = require('body-parser')
    const cors = require('cors')
    const path = require('path')
    
    let FruitBox = [];
    
    //Static content ie images
    app.use('/static', express.static('static'))
    
    router.use(cors())
    router.use(bodyParser.json())
    router.use(bodyParser.urlencoded({ extended: true }))
    
    app.set('view engine', 'ejs');
    app.set('views', path.join(__dirname, 'views'));
    
    router.get('/', function(req, res) {
        res.render('index', { fruitBox: FruitBox })
    })
    
    router.get('/index', function(req, res) {
        res.render('index', { fruitBox: FruitBox })
    })
    
    router.get('/react', function(req, res) {
        res.render('react')
    })
    
    router.get("/ping", async (req, res) => {
        const result = { incomming : 'ping ', resonse : 'pong '}
        res.send(JSON.stringify(result))
    });
    
    router.get("/fruitbox", async (req, res) => {
        res.send(JSON.stringify(FruitBox))
    });
    
    router.get("/fruitbox/:item", async (req, res) => {
        const item = parseInt(req.params.item)
        res.send(JSON.stringify(FruitBox[item]))
    });
    
    
    router.post('/fruitbox', async (req, res) => {
        let result
        try{
            const fruitName = req.body.fruitName;
            const qty = req.body.qty;
            const item = { fruit: fruitName, qty : qty}
            FruitBox.push(item)
            result = FruitBox
            res.status(200)
        }catch(e){
            console.log(e)
            result = { errorMessage : 'Ensure your POST body contains both a fruitName and a qty and content type is application/json '}
            res.status(500);
        }
    
        res.send(result)
    
    })
    
    app.use('/', router)
    
    module.exports = app;
    


    패키지.json

    {
      "name": "FruitBox",
      "version": "1.0.0",
      "description": "Express JS in AWS Lambda deployed to AWS Lambda via SAM",
      "main": "app.js",
      "repository": "https://github.com/kukielp/aws-sam-nodejs-express",
      "author": "Paul Kukiel",
      "license": "MIT",
      "dependencies": {
        "@vendia/serverless-express": "^4.3.2",
        "body-parser": "^1.19.0",
        "cors": "^2.8.5",
        "ejs": "^3.1.6",
        "express": "^4.17.1"
      },
      "devDependencies": {
        "nodemon": "^2.0.11",
        "npm-watch": "^0.7.0"
      },
      "scripts": {
        "dev": "nodemon app.local.js"
      }
    }
    


    이 시점에서 npm 설치를 수행하고 앱을 실행할 수 있어야 합니다.

    npm install
    npm run dev
    


    앱이 시작되고 nodemon이 변경 사항을 감시합니다( 핫 리로딩 ). 그러나 기본 경로(/)는 아직 뷰를 정의하지 않았기 때문에 오류가 발생합니다. API가 작동합니다. 다음으로 이동하여 시도해 볼 수 있습니다.

    http://localhost:3000/fruitbox

    당신이 봐야 할 곳

    []
    


    예, 빈 배열입니다.

    이제 보기에 대한 코드를 추가해 보겠습니다. 이 특정 뷰를 위해 저는 API와의 상호 작용을 시연하고 새로운 과일 항목을 fruitbox에 게시하고 인덱스를 기반으로 전체 fruitbox와 개별 항목을 GET할 수 있는 작은 html 및 js 앱을 만들었습니다.

    그런 다음 해당 파일을 여기에 붙여넣는 대신 직접 링크하겠습니다. Here

    Express에는 @vendia/serverless-express 모듈과 함께 람다에서 직접 최대 5mb의 정적 자산을 제공할 수 있는 다소 멋진 기능도 있습니다. 프로덕션 환경에서는 이것을 S3 및 CloudFront로 오프로드하지만 로컬 개발에 매우 ​​편리합니다.

    아래는 이 실행의 짧은 클립입니다.



    Sam/AWS 배포 미정

    전체 저장소를 볼 수 있습니다here.

    좋은 웹페이지 즐겨찾기