TypeScript 및 Jest 지원 작업: AWS SAM 자습서
게시 됨: 2022-03-11서버리스 애플리케이션 구축을 위한 강력한 도구인 AWS 서버리스 애플리케이션 모델(SAM)은 JavaScript와 자주 쌍을 이룹니다. 중견기업 및 대기업 개발자의 62%가 서버리스 코드로 JavaScript를 선택합니다. 그러나 TypeScript는 인기가 치솟고 있으며 개발자가 세 번째로 많이 사용하는 언어로 JavaScript를 훨씬 능가하고 있습니다.
JavaScript 상용구를 찾는 것은 어렵지 않지만 TypeScript로 AWS SAM 프로젝트를 시작하는 것은 더 복잡합니다. 다음 자습서에서는 AWS SAM TypeScript 프로젝트를 처음부터 생성하는 방법과 여러 부분이 함께 작동하는 방법을 보여줍니다. 독자는 따라가기 위해 AWS Lambda 함수에 어느 정도 익숙해지면 됩니다.
AWS SAM TypeScript 프로젝트 시작
서버리스 애플리케이션의 기초에는 다양한 구성 요소가 포함됩니다. 먼저 AWS 환경, npm 패키지 및 Webpack 기능을 구성한 다음 Lambda 함수를 생성, 호출 및 테스트하여 애플리케이션이 작동하는지 확인할 수 있습니다.
환경 준비
AWS 환경을 설정하려면 다음을 설치해야 합니다.
- AWS CLI
- AWS SAM CLI
- Node.js와 npm
이 튜토리얼에서는 위의 2단계에서 Docker를 설치하여 애플리케이션을 로컬에서 테스트해야 합니다.
빈 프로젝트 초기화
프로젝트 디렉터리인 aws-sam-typescript-boilerplate 와 코드를 저장할 src 하위 폴더를 생성해 보겠습니다. 프로젝트 디렉토리에서 새 npm 패키지를 설정합니다.
npm init -y # -y option skips over project questionnaire 이 명령은 프로젝트 내부에 package.json 파일을 생성합니다.
웹팩 구성 추가
Webpack은 주로 JavaScript 애플리케이션에 사용되는 모듈 번들러입니다. TypeScript는 일반 JavaScript로 컴파일되므로 Webpack은 웹 브라우저용으로 코드를 효과적으로 준비합니다. 두 개의 라이브러리와 사용자 정의 로더를 설치합니다.
- 웹팩: 핵심 라이브러리
- webpack-cli: Webpack용 명령줄 유틸리티
- ts-loader: Webpack용 TypeScript 로더
npm i --save-dev webpack webpack-cli ts-loader AWS SAM CLI 빌드 명령인 sam build 는 각 기능에 대해 npm install 을 실행하려고 시도하므로 개발 프로세스가 느려지고 중복이 발생합니다. aws-sam-webpack-plugin 라이브러리의 대체 빌드 명령을 사용하여 환경 속도를 높입니다.
npm i --save-dev aws-sam-webpack-plugin 기본적으로 Webpack은 구성 파일을 제공하지 않습니다. 루트 폴더에 webpack.config.js 라는 사용자 지정 구성 파일을 만들어 보겠습니다.
/* eslint-disable @typescript-eslint/no-var-requires */ const path = require('path'); const AwsSamPlugin = require('aws-sam-webpack-plugin'); const awsSamPlugin = new AwsSamPlugin(); module.exports = { entry: () => awsSamPlugin.entry(), output: { filename: (chunkData) => awsSamPlugin.filename(chunkData), libraryTarget: 'commonjs2', path: path.resolve('.') }, devtool: 'source-map', resolve: { extensions: ['.ts', '.js'] }, target: 'node', mode: process.env.NODE_ENV || 'development', module: { rules: [{ test: /\.tsx?$/, loader: 'ts-loader' }] }, plugins: [awsSamPlugin] };이제 다양한 부분을 살펴보겠습니다.
-
entry:AWS::Serverless::Function리소스에서 엔트리 객체(Webpack이 번들 빌드를 시작하는 위치)를 로드합니다. -
output: 이것은 빌드 출력의 대상을 가리킵니다(이 경우.aws-sam/build). 여기서 우리는 또한 진입점의 반환 값을module.exports에 할당하는commonjs2로 대상 라이브러리를 지정합니다. 이 진입점은 Node.js 환경의 기본값입니다. -
devtool: 빌드 출력 대상에 소스 맵app.js.map을 생성합니다. 원본 코드를 웹 브라우저에서 실행 중인 코드에 매핑하고 환경 변수NODE_OPTIONS를 Lambda에 대해--enable-source-maps로 설정하면 디버깅에 도움이 됩니다. -
resolve: JavaScript 파일보다 TypeScript 파일을 먼저 처리하도록 Webpack에 지시합니다. -
target: 이것은 Webpack이 Node.js를 우리 환경으로 대상으로 지정하도록 지시합니다. 이것은 Webpack이 컴파일할 때 청크를 로드하기 위해 Node.jsrequire함수를 사용한다는 것을 의미합니다. -
module:test조건을 만족하는 모든 파일에 TypeScript 로더를 적용합니다. 즉, 확장자가.ts또는.tsx인 모든 파일이 로더에서 처리되도록 합니다. -
plugins: 이것은 Webpack이aws-sam-webpack-plugin식별하고 사용하는 데 도움이 됩니다.
첫 번째 줄에서 이 파일에 대한 특정 ESLint 규칙을 비활성화했습니다. 나중에 구성할 표준 ESLint 규칙은 require 문 사용을 권장하지 않습니다. 우리는 예외를 만들 것이므로 Webpack에서 import 하는 것을 선호 require .
TypeScript 지원 설정
TypeScript 지원을 추가하면 다음을 통해 개발자 경험이 향상됩니다.
- 누락된 유형 선언에 대한 경고 메시지 방지.
- 유형 검증을 제공합니다.
- IDE 내에서 자동 완성을 제공합니다.
먼저 프로젝트에 대한 TypeScript를 로컬로 설치합니다(TypeScript가 전역적으로 설치된 경우 이 단계 건너뛰기).
npm i --save-dev typescript사용 중인 라이브러리의 유형을 포함합니다.
npm i --save-dev @types/node @types/webpack @types/aws-lambda 이제 프로젝트 루트에 TypeScript 구성 파일 tsconfig.json 을 생성합니다.
{ "compilerOptions": { "target": "ES2015", "module": "commonjs", "sourceMap": true, "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, }, "include": ["src/**/*.ts", "src/**/*.js"], "exclude": ["node_modules"] } 여기서는 TypeScript 커뮤니티에서 권장하는 기본 구성을 따릅니다. src 폴더 아래에 있는 파일을 프로그램에 추가하기 위해 include 를 추가했고 node_modules 폴더에 대한 TypeScript 컴파일을 피하기 위해 exclude 를 추가했습니다. 이 코드를 직접 건드리지는 않겠습니다.
Lambda 함수 생성
지금까지 서버리스 애플리케이션에 대한 Lambda 코드를 작성하지 않았으므로 바로 시작해 보겠습니다. 이전에 생성한 src 폴더에서 다음 Lambda 함수를 사용하여 app.ts 파일이 포함된 test-lambda 하위 폴더를 생성합니다.
import { APIGatewayEvent } from 'aws-lambda'; export const handler = async (event: APIGatewayEvent) => { console.log('incoming event is', JSON.stringify(event)); const response = { statusCode: 200, body: JSON.stringify({ message: 'Request was successful.' }) }; return response; };이 간단한 자리 표시자 함수는 본문과 함께 200 응답을 반환합니다. 한 단계 더 거쳐 코드를 실행할 수 있습니다.
AWS 템플릿 파일 포함
AWS SAM에는 코드를 변환하고 클라우드에 배포하려면 템플릿 파일이 필요합니다. 루트 폴더에 template.yaml 파일을 만듭니다.
AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: AWS SAM Boilerplate Using TypeScript Globals: Function: Runtime: nodejs14.x # modify the version according to your need Timeout: 30 Resources: TestLambda: Type: AWS::Serverless::Function Properties: Handler: app.handler FunctionName: "Test-Lambda" CodeUri: src/test-lambda/ Events: ApiEvent: Type: Api Properties: Path: /test Method: get 이 템플릿 파일은 HTTP GET API에서 액세스할 수 있는 Lambda 함수를 생성합니다. Runtime: 행에서 참조된 버전은 사용자 정의가 필요할 수 있습니다.
애플리케이션 실행
애플리케이션을 실행하려면 Webpack으로 프로젝트를 빌드하기 위해 package.json 파일에 새 스크립트를 추가해야 합니다. 파일에는 빈 테스트 스크립트와 같은 기존 스크립트가 있을 수 있습니다. 다음과 같이 빌드 스크립트를 추가할 수 있습니다.
"scripts": { "build": "webpack-cli" } 프로젝트 루트에서 npm run build 를 실행하면 빌드 폴더 .aws-sam 이 생성된 것을 볼 수 있습니다. Mac 환경에 있는 사람들은 Command + Shift +를 눌러 숨김 파일을 표시해야 할 수도 있습니다. 폴더를 볼 수 있습니다.
이제 기능을 테스트하기 위해 로컬 HTTP 서버를 시작합니다.
sam local start-api웹 브라우저에서 테스트 엔드포인트를 방문하면 성공 메시지가 표시되어야 합니다.
콘솔은 함수가 실행되기 전에 Docker 컨테이너에 탑재되었음을 표시해야 합니다. 이것이 우리가 Docker를 더 일찍 설치한 이유입니다.
Invoking app.handler (nodejs14.x) Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs14.x:rapid-1.37.0-x86_64. Mounting /Users/mohammadfaisal/Documents/learning/aws-sam-typescript-boilerplate/.aws-sam/build/TestLambda as /var/task:ro, delegated inside runtime container전문적인 환경을 위한 개발 워크플로 향상
우리 프로젝트는 시작되어 실행 중이며 몇 가지 마무리 작업을 추가하면 생산성과 협업을 향상시킬 탁월한 개발자 경험을 보장할 수 있습니다.

핫 리로딩으로 빌드 최적화
코드가 변경될 때마다 빌드 명령을 실행하는 것은 지루합니다. 핫 리로딩은 이 문제를 해결할 것입니다. 파일 변경 사항을 감시하기 위해 package.json 에 다른 스크립트를 추가할 수 있습니다.
"watch": "webpack-cli -w" 별도의 터미널을 열고 npm run watch 를 실행합니다. 이제 코드를 변경하면 프로젝트가 자동으로 컴파일됩니다. 코드의 메시지를 수정하고 웹페이지를 새로고침하여 업데이트된 결과를 확인하세요.
ESLint 및 Prettier로 코드 품질 향상
ESLint 및 Prettier 없이는 TypeScript 또는 JavaScript 프로젝트가 완료되지 않습니다. 이러한 도구는 프로젝트의 코드 품질과 일관성을 유지합니다.
먼저 핵심 종속성을 설치해 보겠습니다.
npm i --save-dev eslint prettierTypeScript 프로젝트에서 ESLint와 Prettier가 함께 작동할 수 있도록 몇 가지 도우미 종속성을 추가합니다.
npm i --save-dev \ eslint-config-prettier \ eslint-plugin-prettier \ @typescript-eslint/parser \ @typescript-eslint/eslint-plugin 다음으로 프로젝트 루트 내부에 ESLint 구성 파일 .eslintrc 를 만들어 린터를 추가합니다.
{ "root": true, "env": { "es2020": true, "node": true, "jest": true }, "parser": "@typescript-eslint/parser", "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended" ], "ignorePatterns": ["src/**/*.test.ts", "dist/", "coverage/", "test/"], "parserOptions": { "ecmaVersion": 2018, "sourceType": "module", "ecmaFeatures": { "impliedStrict": true } }, "rules": { "quotes": ["error", "single", { "allowTemplateLiterals": true }], "default-case": "warn", "no-param-reassign": "warn", "no-await-in-loop": "warn", "@typescript-eslint/no-unused-vars": [ "error", { "vars": "all", "args": "none" } ] }, "settings": { "import/resolver": { "node": { "extensions": [".js", ".jsx", ".ts", ".tsx"] } } } } 우리 파일의 extends 섹션은 Prettier 오류를 편집기에서 볼 수 있는 ESLint 오류로 표시하기 위해 마지막 줄로 Prettier 플러그인 구성을 유지해야 합니다. TypeScript에 대해 ESLint 권장 설정을 따르고 있으며 rules 섹션에 몇 가지 사용자 정의 기본 설정이 추가되었습니다. 사용 가능한 규칙을 자유롭게 탐색하고 설정을 추가로 사용자 정의하십시오. 다음을 포함하기로 결정했습니다.
- 작은따옴표 문자열을 사용하지 않으면 오류가 발생합니다.
-
switch문에default케이스를 제공하지 않을 때의 경고입니다. - 함수의 매개변수를 재할당하면 경고가 표시됩니다.
- 루프 내에서
await문을 호출하면 경고가 표시됩니다. - 시간이 지남에 따라 코드를 읽을 수 없고 버그가 발생하기 쉬운 미사용 변수에 대한 오류입니다.
Prettier 형식과 함께 작동하도록 ESLint 구성을 이미 설정했습니다. ( eslint-config-prettier GitHub 프로젝트에서 더 많은 정보를 얻을 수 있습니다.) 이제 Prettier 구성 파일 .prettierrc 를 생성할 수 있습니다.
{ "trailingComma": "none", "tabWidth": 4, "semi": true, "singleQuote": true }이 설정은 Prettier의 공식 문서에서 가져왔습니다. 원하는 대로 수정할 수 있습니다. 다음 속성을 업데이트했습니다.
-
trailingComma: 후행 쉼표를 피하기 위해 이것을es5에서none으로 변경했습니다. -
semi: 각 줄 끝에 세미콜론이 있는 것을 선호하기 때문에false에서true로 변경했습니다.
마지막으로 ESLint와 Prettier가 작동하는 모습을 볼 시간입니다. app.ts 파일에서 response 변수 유형을 const 에서 let 으로 변경합니다. 이 경우에 let 을 사용하는 것은 좋은 방법이 아닙니다. response 의 값을 수정하지 않기 때문입니다. 편집기는 오류, 깨진 규칙 및 코드 수정 제안을 표시해야 합니다. ESLint 및 Prettier가 아직 설정되지 않은 경우 편집기에서 활성화하는 것을 잊지 마십시오.
Jest 테스트로 코드 유지 관리
Jest, Mocha 및 Storybook과 같은 많은 라이브러리를 테스트에 사용할 수 있습니다. 다음과 같은 몇 가지 이유로 프로젝트에서 Jest를 사용할 것입니다.
- 배우는 것이 빠릅니다.
- 최소한의 설정이 필요합니다.
- 사용하기 쉬운 스냅샷 테스트를 제공합니다.
필요한 종속성을 설치해 보겠습니다.
npm i --save-dev jest ts-jest @types/jest 다음으로 프로젝트 루트 내부에 Jest 구성 파일인 jest.config.js 를 생성합니다.
module.exports = { roots: ['src'], testMatch: ['**/__tests__/**/*.+(ts|tsx|js)'], transform: { '^.+\\.(ts|tsx)$': 'ts-jest' } };파일에서 세 가지 옵션을 사용자 지정합니다.
-
roots: 이 배열에는 테스트 파일을 검색할 폴더가 포함되어 있습니다.src하위 폴더 아래만 검사합니다. -
testMatch: 이 glob 패턴 배열에는 Jest 파일로 간주될 파일 확장자가 포함됩니다. -
transform: 이 옵션을 사용하면ts-jestjest 패키지를 사용하여 TypeScript에서 테스트를 작성할 수 있습니다.
src/test-lambda 안에 새로운 __tests__ 폴더를 만들어 봅시다. 그 안에 첫 번째 테스트를 생성할 handler.test.ts 파일을 추가합니다.
import { handler } from '../app'; const event: any = { body: JSON.stringify({}), headers: {} }; describe('Demo test', () => { test('This is the proof of concept that the test works.', async () => { const res = await handler(event); expect(res.statusCode).toBe(200); }); }); package.json 파일로 돌아가서 테스트 스크립트로 업데이트하겠습니다.
"test": "jest" 터미널로 이동하여 npm run test 를 실행하면 테스트 통과를 환영해야 합니다.
.gitignore 로 소스 제어 처리
소스 제어에서 특정 파일을 제외하도록 Git을 구성해야 합니다. 필요하지 않은 파일은 건너뛰기 위해 gitignore.io를 사용하여 .gitignore 파일을 만들 수 있습니다.
# Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* .pnpm-debug.log* # Runtime data pids *.pid *.seed *.pid.lock npm-debug.log package.lock.json /node_modules .aws-sam .vscode # TypeScript cache *.tsbuildinfo # Optional npm cache directory .npm # Optional ESLint cache .eslintcache준비, 설정, 구축: 성공을 위한 청사진
이제 TypeScript가 포함된 완전한 AWS SAM 상용구 프로젝트가 있습니다. 우리는 ESLint, Prettier 및 Jest 지원을 통해 기본을 올바르게 하고 높은 코드 품질을 유지하는 데 집중했습니다. 이 AWS SAM 자습서의 예제는 청사진 역할을 하여 다음 대규모 프로젝트를 처음부터 순조롭게 진행할 수 있습니다.
Toptal 엔지니어링 블로그는 이 기사에 제공된 코드 샘플을 검토한 Christian Loef에게 감사를 표합니다.
