aws lambda handler callback

example.ts
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
import {
APIGatewayProxyCallback,
APIGatewayProxyEvent,
APIGatewayProxyResult,
Context,
} from 'aws-lambda';
import { makeResponse } from './makeResponse';
import { service } from './service';

export const handler = async (
_e: APIGatewayProxyEvent,
_c: Context,
callback: APIGatewayProxyCallback
): Promise<APIGatewayProxyResult | undefined> => {
let response;

try {
const res = await service();
response = makeResponse(200, res);
} catch (err) {
console.error(err);
callback(err as any);
}

return response;
};

상황

  • 람다 로직에서 외부 api를 호출하는 경우가 있다
  • 근데 종종이 운 나쁘게 실패할 때가 생긴다
  • 람다는 에러가 발생하면 알아서 재시도를 한다
  • 재시도를 시키기 위해 실패를 알려야 한다
  • catch에 잡히면 재시도를 했으면 좋겠다

해결

  • 3번째 인자로 callback을 받고, catch에서 호출해준다

참고

cron 표현식

Cron syntax has five fields separated by a space, and each field represents a unit of time.

┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of the month (1 - 31)
│ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
│ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
 *  *  *  *  *

  • 크론 표현식 쓸 때마다 까먹는다
  • 깃허브 액션 문서 보다가 잘 정리되어 있는 거 발견해서 스크랩한다

참고

람다가 한번 호출했는데 여러 번 실행된다?!

  • 람다가 2회, 3회 중복 실행되는 경험을 한 적이 있다
  • 구성 > 일반 구성으로 들어가 보면 메모리 및 제한 시간을 설정할 수 있다
  • 제한 시간이 3초인 것을 5초로 늘려주어서 해결했다
  • 람다는 제한 시간 안에 실행을 끝내지 못하면 실패하였다고 생각하여 설정한 재시도 횟수만큼 같은 함수를 재실행한다

TMI

  • 내가 작성한 람다에는 인터넷을 사용하여 어떤 api를 콜하는 로직이 있었다
  • 람다는 스케쥴러를 통해서 트리거 된다
  • 그런데 해당 api가 간헐적으로 여러 번 호출된 것을 확인하였고, 문제가 무엇인지 알아보다가
  • 제한시간을 너무 짧게 둔 것이 문제임을 알게 되었다

AWS 프리티어 사용기

aws 프리티어가 만료되었드아…

  • aws 프리티어 사용하면서 써본 서비스 정리해보기
  • 처음 클라우드 환경을 써보면서 처음이라 과금될까 봐 엄청 쫄았던 이야기
  • 어디까지 무료로 쓸 수 있었나 정리해보기

AWS 프리티어 사용기 요약

  • 과금된 적 없음 (정확히는 $0.01가 두 달간 찍혔는데 실제로는 “인보이스에 대해 면제된 지불금” 이라면서 과금 안 됨)
  • EC2, RDS 는 안 꺼도 된다 (난 아껴 쓴다고 초반에는 껐다 켰다를 반복했다)
  • AWS 가입한 날을 기억해 놓자. 따로 프리티어 만료 이메일이 오거나 하지 않는다 (가입 후 1년)
  • 프리티어 종료는 Billing Management Console에서 경고 및 알림 란에서 프리티어 여부를 확인할 수 있다

  • 나는 이제 끝나서 프리티어 관련 문구가 안 보이는 것을 확인할 수 있다
  • 프리티어가 끝났어도, 람다 같은 일부 서비스는 과금되는 사용량까지 여유가 있어서 요긴하게 쓸 수 있다
    • 프리티어가 끝나고 일정 용량 무료인 서비스 확인은 여기서

ec2

  • 처음 ec2 인스턴스를 생성할 때 혹시나 잘못된 옵션 선택으로 과금이 되지 않을까 걱정했다
  • 생활코딩님 영상을 보고 처음 aws를 시작했는데,
  • 옵션 하나하나 영상과 일치시키려고 확인 또 확인했다
  • 그런데 지금은 그냥 기본값으로 생성하면 된다는 것을 알았다 ㅋㅋ
  • 또, ec2 사용하지 않을 때는 항상 종료시켰다, rds도 마찬가지다
  • 그런데 그냥 ec2나 rds를 사용할 때 하나의 인스턴스만 사용한다면 굳이 종료시킬 필요가 없다
  • 한 달 내내 켜놔도 과금되지 않는다
  • ec2 인스턴스를 한번 껐다가 켜면(이하 껐키) ip가 바뀐다
  • ip를 고정시키기 위해서는 탄력적 ip 라는 것을 사용해야 하는데
  • ec2를 껐키하지 않는다면 딱히 필요 없다 (재부팅을 사용하면 ip가 바뀌지 않는다)
  • 그래도 사용해보고 싶다면 탄력적 ip는 프리티어에서 1개까지 무료로 사용 가능하다
  • 키페어를 잘 보관하자

rds

  • ec2와 마찬가지로 한 달 내내 켜놔도 과금되지 않는다
  • 처음 rds를 생성하면 퍼블릭한 접근이 가능하기 때문에 비밀번호를 잘 설정하자
  • 나는 root/1234로 했다가 해킹당했다 ㅋㅋㅋㅋㅋ
  • 딱히 공부 목적으로 중요한 정보는 없어서 다행이었다
  • rds 삭제할 때 스냅샷을 생성하지 않도록 한다
  • 스냅샷 보관 비용이 발생한다 (프리티어 적용 안됨!)

s3

  • 이것도 생성할 때 기본값으로 생성한다
  • 기본적으로 클라우드 포메이션이나 람다같은 AWS 서비스를 사용하다보면 자동으로 사용하게 된다
  • AWS의 여러 서비스들은 s3에 의존한다
  • 근데 프리티어에서 공부수준으로 서비스를 활용해서 과금될 걱정은 없다

api gateway

  • 람다를 트리거할 때 주로 사용했다
  • 백엔드가 서버리스인 웹에서 람다를 호출해야 할 때 cors 설정이 필요하다
  • cors 설정할 때 삽질을 엄청했는데
  • 처음에는 수동으로 cors를 설정하려고 이것저것 설정을 했는데
  • 그냥 작업 버튼 아래에 cors 활성화 도구가 있었다 ㅋㅋㅋㅋ
  • 버튼 하나로 cors를 활성화시킬 수 있다
  • 람다 프록시 통합을 꺼야 활성화할 수 있고 막 엄청 삽질했다
  • 이때 모든 도메인에 대해 허용하니까 적절히 수정해 줄 수 있다
  • 또, cors는 활성화했지만 api 호출이 안될 때 람다 내부에서 헤더를 반환해야 줘야 한다 ㅋㅋ

보안설정

  • 인바운드 규칙에서 내가 주로 사용하는 ip를 설정하는 게 좋다

IAM

  • 자격 증명 관련 서비스다
  • 별도 비용이 들지 않는다

amplify

  • 웹앱을 배포할 때 좋다
  • 백엔드가 서버리스일 때 좋다고 한다
  • amplify 프레임워크 사용에 따른 별도 비용은 없다

sam ; serverless application model

  • AWS CloudFormation의 확장이다
  • AWS::*, Alexa::* 및 Custom::*과 같은 네임스페이스의 리소스 공급자에서 AWS CloudFormation을 사용하는 경우 추가 요금은 부과되지 않는다
  • 즉 sam 사용에 의한 별도 비용은 없다
  • 이를 통해 생성된 리소스에 대한 비용만 든다
  • 보통 생성되는 리소스로는 api gateway, lambda, s3 등이 있다
  • 프리티어 사용 동안에는 생성된 리소스가 대부분 프리티어가 적용되기 때문에 과금된 적 없다

aws credentials 여러개

  • 여러개의 자격 증명 프로필을 가질 수 있다
  • 이 경우에 aws cli, aws sam cli 등 커맨드라인을 사용할 때
  • 프로필을 지정해 줘야한다

프로필 추가

terminal
1
2
# aws configure --profile {profile name}
aws configure --profile newprofile

AWS Access Key ID [None]: new
AWS Secret Access Key [None]: newkey
Default region name [None]:
Default output format [None]:

  • aws configure --profile {profile name} 명령을 치면 위 처럼 나오는데
  • 여기에 키아이디와 키를 입력한다
%USERPROFILE%/.aws/credentials
1
2
3
4
5
6
7
[default]
aws_access_key_id = xxxxxxxxxxxxxxxxxxxx
aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

[newprofile]
aws_access_key_id = new
aws_secret_access_key = newkey
  • %USERPROFILE%/.aws/credentials 파일을 열어보면 위처럼 [default] 프로필 아래에
  • 새로운 프로필이 등록되었을 것이다

프로필 스위치

  • 나는 두 가지 방법을 써봤다

방법 1; AWS_PROFILE 환경 변수 설정

  • 환경 변수 AWS_PROFILE을 원하는 프로필명으로 설정한다
  • set AWS_PROFILE {profilename}
  • setx AWS_PROFILE {profilename}
  • 이렇게 2가지를 사용할 수 있다
  • set은 해당 터미널에서만 적용된다. 해당 터미널이 닫히면 같이 날라간다
  • setx는 모든 터미널에서 적용된다
  • setx의 경우 모든 터미널을 닫았다가 열어야 적용된다. vscode 전부 닫았다가 켜야 적용된다
1
2
3
4
5
# bash
echo $AWS_PROFILE

# cmd (windows)
echo %AWS_PROFILE%
  • 환경 변수 적용 확인을 꼭하자
  • 방법 1은 가장 자주 쓰는 프로필을 지정할 때 좋을 것 같다

방법 2; 옵션 사용

  • 환경변수 세팅 말고,
  • aws cli를 사용할 때 --profile옵션을 줄 수 있다
  • aws cli를 사용하다 보면 옵션을 주지 않아도 프로필이 한 개가 아니면 명령을 실행하다가도 어떤 프로필을 사용할지 물어본다
  • 근데 실수로 다른 계정에 배포를 할 수 있으니까.. --profile 옵션을 쓰는 게 좋을 것 같다
  • sam cli의 경우 deploy 할 때 sam deploy --profile newprofile 이런 식으로 할 수 있겠다

방법 3 (번외?); config file 사용 (aws-sdk)

  • cli에 적용되는 것은 아닌데, nodejs app에서 aws sdk 자격 증명하는데 json 파일을 쓸 수 있다
  • 로컬에서 개발하고 클라우드 환경으로 올릴 때, 그 환경마다 aws configure 하는 게 귀찮다
config.json
1
2
3
4
5
{
"accessKeyId": "xxxxxxxxxxxxxxxxxxxx",
"secretAccessKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"region": "ap-northeast-2"
}
example.js
1
2
3
import AWS from 'aws-sdk';
import path from 'path';
AWS.config.loadFromPath(path.join(__dirname, './config.json'));
  • json 파일로 자격 증명할 수 있다

참고

aws lambda에서 git쓰기

arn:aws:lambda:us-east-1:553035198032:layer:git-lambda2:8

상황

  • 람다에서 git 명령을 사용하고 싶다

레이어 추가

1
2
3
4
5
6
7
8
9
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs14.x
Layers:
- 'arn:aws:lambda:us-east-1:553035198032:layer:git-lambda2:8' # 여기를 추가!!
  • sam template.yaml에서는 위와 같이 추가한다
  • 또는 aws console로 직접 해당 람다에 가서 추가해 줄 수 있다

람다에서 깃 쓸 때 고려사항

  • 람다에서는 가급적 가벼운 일을 해야 한다
  • git clone 한다면 /tmp 디렉터리에서 한다 (clone 옵션을 살펴서 최대한 필요한 것만 가져오자)
  • 인증은 Personal access tokens을 사용했다
    • 토큰이 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 이렇게 있을 때,
    • https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@github.com/{레포 오너}/{레포 명}.git
    • 이렇게 사용할 수 있다

참고

rds 시간대 변경

  • rds는 기본적으로 utc를 사용한다
  • 한국 시간대로 바꿔보자

하는 법

새 파라미터 그룹 생성

  • rds 생성하면서 자동 생성되는 default.~ 그룹은 수정이 불가하다
  • 따라서 디폴트 파라미터 그룹을 사용한다면 새로이 파라미터 그룹을 생성한다

time zone 파라미터 수정

  • time_zone을 검색해서 시간대를 수정한다

rds 인스턴스 파라미터 그룹 수정


  • rds 인스턴스 수정에 들어가서,
  • 위에서 생성한 파라미터 그룹으로 적용시켜준다

rds 재시작

  • rds를 재시작해야 적용된다

적용 확인하기

1
SELECT curtime();

참고