티스토리 뷰
개요
- 사이드 프로젝트 백엔드를 서버리스로 배포하는 방법에 대해 정리한다.
- 포트폴리오 시 링크를 달아야 할 때 서버리스로 배포하면 비용절감에 도움이 될 것이라 생각함
- 클라우드 서비스에 좀 더 익숙해지기 위해 사용
단점
nestjs + lambda를 적용하기 전에 단점부터 알아보자.
- 일단 nestjs 전체를 묶어서 올리는 것이기 때문에 무겁다.
- api gateway에서 routing을 한번, nestjs에서 routing을 한번 더 하기 때문에 속도가 느리다.
즉, 실제 고객한테 제공하는 서비스를 만들 예정이라면 쓰지 않는 것을 추천한다.
방법
순서
- serverless 환경설정
- serverless에 필요한 의존성 설치
- serverless yml 작성
- serverless offline으로 먼저 동작하는지 배포
- serverless deploy를 통해 배포
- script 실행
- api gateway, lambda, dynamodb가 모두 제대로 배포되는지 확인한다.
serverless 환경 설정하기
// serverless.yml (참고용)
service: backend-template
useDotenv: true
package:
individually: true
plugins:
- serverless-offline
- serverless-plugin-typescript
provider:
name: aws
runtime: nodejs18.x # 현재 serverless-offline이 18버전까지만 지원하기 떄문에 18버전으로 사용
region: ap-northeast-2
memorySize: 1024
timeout: 20
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:*
Resource: "*"
# lambda 리소스 설정
functions:
main:
handler: src/main.handler
events:
- http:
method: ANY
path: /
cors: true # cors 에러를 피하기 위해 설정
- http:
method: ANY
path: '{proxy+}'
cors: true # cors 에러를 피하기 위해 설정
resources:
Resources:
# DynamoDB 설정
usersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: Users
AttributeDefinitions:
- AttributeName: unique 속성
AttributeType: S
KeySchema:
- AttributeName: unique 속성
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
challengesTable:
Type: AWS::DynamoDB::Table
Properties:
TableName
AttributeDefinitions:
- AttributeName:
AttributeType: S
KeySchema:
- AttributeName:
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
custom:
serverless-offline:
httpPort: 4000
lambdaPort: 4001
// dependencies
{
"@aws-sdk/client-dynamodb": "^3.441.0",
"@aws-sdk/lib-dynamodb": "^3.441.0",
"@vendia/serverless-express": "^4.10.4",
"aws-lambda": "^1.0.7",
"aws-sdk": "^2.1484.0",
"aws-serverless-express": "^3.4.0",
}
//devdependencies
{
"@types/aws-lambda": "^8.10.125",
"@types/aws-serverless-express": "^3.3.7",
"serverless-offline": "^13.2.0",
"serverless-plugin-typescript": "^2.1.5",
}
기본적으로 위와 같이 설정 했다.
scripts 작성하기
# 서버리스 배포하기
"deploy": "serverless deploy --aws-profile <default일 경우 생략, 지정할 profile 있으면 설정할 것>
# 배포한 서버리스 삭제하기
"remove": "serverless remove --aws-profile <default일 경우 생략, 지정할 profile 있으면 설정할 것>
# 오프라인으로 실행하기
"dev:serverless": "serverless offline"
삽질
- 이번 serverless로 배포하면서 겪었던 삽질들을 모두 정리하려 한다.
그냥 실행이 안되요.
배포 전에 serverless-offline으로 먼저 제대로 실행이 되는지 알아본다.
nestjs의 경우 dev환경에서 로그가 뜨도록 설정해 놓았는데 로그가 뜨지 않는다.
이 경우엔 severless.yml의 memory size를 너무 작게 설정한건 아닌지 한번 확인 해봐야 한다.
cors 에러
아래의 링크를 통해 cors 에러를 해결했다
https://www.serverless.com/blog/cors-api-gateway-survival-guide
내가 사용한 방법은 두가지의 방법이다
- serverless yml에 cors 설정을 추가하는 방식 (위에 yml 파일 작성한거 확인)
- interceptors를 이용해 response시 header를 강제적으로 달아주는 방식이다.
interceptor.ts
// common-headers.interceptor.ts
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class CommonHeadersInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// 원하는 헤더를 여기에 추가합니다.
const response = context.switchToHttp().getResponse();
response.header('Access-Control-Allow-Origin', '*');
response.header('Access-Control-Allow-Credentials', 'true');
// 다음 핸들러 실행
return next.handle();
}
}
// app.module.ts
import { APP_INTERCEPTOR } from '@nestjs/core';
providers: [
AppService,
{
provide: APP_INTERCEPTOR,
useClass: Interceptor, // 작성한 interceptor.ts
},
],
[개선해야 할 점]
- 일단 cors를 해결하는데 집중하기 위해 *표시를 사용했으나 그러면 모든 도메인에서 접근이 가능하기 떄문에 frontend 도메인에서만 사용할 수 있게 변경해야 한다.
- 물론 yml 파일도 마찬가지이다.
cloudwatch 확인하기 (bcrypt error)
lambda가 제대로 실행되는지를 확인하기 위해 cloudwatch 로그를 확인한다.
[에러]
"/var/task/node_modules/bcrypt/lib/binding/napi-v3/bcrypt_lib.node: invalid ELF header" in aws lambda
다음 링크를 확인해보자
bcrypt의 경우 node-gyp를 사용하기 때문에 lambda에서 사용할 때 에러가 난다고 나와있다
bcryptjs로 바꾸면 에러가 발생하지 않는다.
환경변수 관련 이슈
- env 파일에서 불러오지 못해 undefiend가 발생하는 현상
aws console > lambda로 들어가서 환경변수를 설정하는 부분이 있으니 거기에 추가해보자.
개선 사항
- cors 설정 다시하기
- build 해서 올리는데 너무 오래걸린다. yarn berry나 다른 것들을 도입해서 시간을 줄일 수 없는지 한번 확인해 봐야겠다.
- 환경변수 일일이 추가하기 귀찮다 build 단계에서 추가하는 법이 없나 찾아볼 예정이다.
'사이드 프로젝트' 카테고리의 다른 글
nodejs v16에서 nodejs v20으로 마이그레이션 하기 (yarn berry) (0) | 2024.02.06 |
---|---|
코드 스플리팅과 Tree shaking (1) | 2023.12.06 |
Error handling 삽질하기 (2) | 2023.12.04 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 자바스크립트
- storybook scss import
- nextjs 에러핸들링
- 불량 사용자 자바스크립트
- 백준 22862
- storybook scss이슈
- useCallback과 useMemo 사용
- 서버사이드 error handling
- React useMemo
- suspense 장점
- javascript
- 1600 파이썬
- serverless 배포
- nextjs errorboundary
- react suspense
- 미로탈출 명령어
- 표현 가능한 이진트리
- 가장 긴 짝수 연속한 부분 수열
- node 버전 마이그레이션
- serverless nestjs
- CSS
- 선언적 UI
- 에러핸들링
- 서비스 디자인 패턴
- 백준 1600번
- node version yarn berry
- 관심사 분리하기
- nestjs 배포하기
- React useCallback
- storybook react is not defiend 해결
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
글 보관함