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 등이 있다
  • 프리티어 사용 동안에는 생성된 리소스가 대부분 프리티어가 적용되기 때문에 과금된 적 없다

commander.js로 cli 도구 만들기

  • 간단한 cli 도구를 만들어보았다

TMI

cli.ts

cli.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
#!/usr/bin/env node
import { Command } from 'commander';
import { gto9 } from 'g-to-9';
import { version } from './package.json';

const program = new Command();

program.version(version);

program
.argument('<text>')
.description(
`replace all 'g' to '9'

Examples:
$ gto9 chinsung
$ gto9 gg is good game
$ gto9 'gg is good game'`
)
.action(() => {
const input = program.args.join(' ');
const result = gto9(input);
console.log(result);
});

program.parse();
  • #!/usr/bin/env node 최상단에 추가해줘야 한다

Windows Script Host
Microsoft JScript 컴파일 오류

  • 추가하지 않으면 만나는 오류이다

package.json

package.json
1
2
3
4
5
6
7
8
9
10
{
"name": "g-to-9-cli",
"version": "1.0.0",
"description": "g-to-9-cli",
"main": "cli.js",
"bin": {
"gto9": "cli.js"
}
// ...
}
  • package.json 에서 bin 필드에 값을 넣어주어 쉽게 cli 설정을 할 수 있다
  • 오브젝트를 넣어주거나 스트링을 넣어줄 수 있는데,
  • 스트링을 넣는 경우 "{cli path}" 형태로 한다. 이경우에는 프로젝트 이름으로 실행할 수 있다
  • 오브젝트의 경우 {"{command}" : "{cli path}"} 형태로 넣어준다. 이경우에는 프로젝트 이름과 다른 커맨드를 지정해 줄 수 있다
  • 참고 ; https://docs.npmjs.com/cli/v7/configuring-npm/package-json#bin

참고

jsisweird

  • JS Is Weird 풀이 (자바스크립트는 이상해~~~)
  • js 퀴즈 25문제 푸는 곳이다
  • 나는 15/25점을 맞았다

후기

  • 소름 돋는 건 문법 에러가 정답인 문제는 없다는 것이었다 ㅋㅋ
  • 혹시 문제를 풀어보지 않았다면 먼저 문제를 풀고 오는 것을 추천한다!
  • https://jsisweird.com/

오답노트

2. [,,,].length

Output: 3
You answered: 4

  • 마지막 콤마는 trailing commas로 인식된다
example
1
2
3
4
5
6
7
const arr = [
1, //
2,
3,
];

console.log(arr.length); // 3
  • arr 배열에 원소가 3개 있고, 콤마도 3개 있다

  • trailing commas 는 나중에 원소를 추가할 때 불편하지 않도록 하는 좋은 녀석이다

  • 문제에서는 마지막 콤마를 trailing commas 로 하고, undefined이 3개 있는 배열에서의 length를 물어본 것이다

  • eslint에서는 룰에 따라 trailing commas 를 사용할지 안 할지 선택할 수 있다

  • 참고 ; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas

3. [1, 2, 3] + [4, 5, 6]

Output: “1,2,34,5,6”
You answered: NaN

  • 배열 더하기를 사용해본 적이 없어서 몰랐다
  • 내 예상은 +로 넘버로 캐스팅되어서 숫자가 아니니까 NaN이고 NaN 끼리 더해서 NaN이 나올 것을 예상했는데
  • 알고 보니 문자열로 캐스팅이 되는 것이었다…
  • [1, 2, 3] + [4, 5, 6] === [1, 2, 3].toString() + [4, 5, 6].toString()

4. 0.2 + 0.1 === 0.3

Output: false
You answered: false

  • 이 문제는 맞았다!
  • 이전에 자바스크립트에 부동소수점 계산 문제가 있다는 것을 경험하고 mathjs 라이브러리를 통해 정확한 계산을 해본 적이 있다
  • 0.2 + 0.1 === 0.30000000000000004 // true

5. 10,2

Output: 2
You answered: 10

  • 이게 뭔가 싶다 ㅋㅋ
  • 이런 코드를 작성할까 싶다
  • 설명으로는 간단하게 맨 마지막 값을 반환한다고 되어있다
example
1
2
const a = (1, 2, 3);
console.log(a); // 3

9. true == “true”

Output: false
You answered: true

  • 서로 다른 타입을 Abstract Equality Comparison하면 같은 타입으로 coercion 된다
  • 참고 ; https://262.ecma-international.org/11.0/#sec-abstract-equality-comparison
  • 참고 링크에 의하면 정해진 우선순위에 따라 결괏값을 반환하는데,
  • boolean과 string 비교는 number, string 으로 1차 변환되고,
  • number, string에서 number ,number로 변환되어 비교된다
  • 결국 true == "true" -> 1 == "true" -> 1 == NaN -> false 가 된다

11. “” - - “”

Output: 0
You answered: SyntaxError

  • - 마이너스가 2번 연속 나오는데 이게 왜 문법 에러가 아니지… 충격
  • 생각해보니까 10 - (-10) 같은 게 떠올랐다
  • -를 붙여서 --로 썼다면 SyntaxError 라고 한다
    - -“”; // -> 0
    –””; // -> SyntaxError

12. null + 0

Output: 0
You answered: NaN

  • nullundeifend, NaN이랑 다르게 0으로 변환된다
  • 참고로 false도 넘버로 캐스팅하면 0으로 변환된다

13. 0/0

Output: NaN
You answered: Infinity

  • 0/0NaN
  • 1/0Infinity

18. true + (“true” - 0)

Output: NaN
You answered: 2

  • "true"가 숫자로 캐스팅되면 1이 아니라 NaN이다
  • "true"를 1로 생각하고 문제를 풀었다 ㅠ

21. NaN === NaN

Output: false
You answered: true

  • 이건 너무…
example
1
2
3
NaN === NaN; // -> false
Object.is(NaN, NaN); // -> true
isNaN(NaN) == isNaN(NaN); // -> true
  • NaN 비교는 이런 식으로 해야 생각대로 동작한다

23. undefined + false

Output: NaN
You answered: 0

  • undefinedNaN 으로 변환된다

참고

🍌 바나나 만들기

make banana
1
('b' + 'a' + +'a' + 'a').toLocaleLowerCase();

typescript에서 jest 쓰기

Jest encountered an unexpected token
SyntaxError: Cannot use import statement outside a module

따라하기

terminal
1
2
3
4
5
6
7
# jest 설치
yarn add --dev jest
yarn add --dev @types/jest

# typescript에서 jest 돌리기 위한 추가 종속성 설치
yarn add --dev @babel/preset-typescript
yarn add --dev babel-jest @babel/core @babel/preset-env
  • 종속성을 설치한다
babel.config.js
1
2
3
4
5
6
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
'@babel/preset-typescript',
],
};
  • babel.config.js 를 추가한다

eslint를 같이 사용하고 있다면

eslintrc.json
1
2
3
4
5
6
7
{
"env": {
// ...
"jest": true
}
// ...
}
  • eslintrc 에 env.jest를 true로 해준다

참고

vscode extension rest client

  • Rest Client라는 도구가 있다
  • text 기반으로 간편하게 리퀘스트를 작성할 수 있다
example.http
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
###
GET http://localhost:3000/movies/ HTTP/1.1

###
GET http://localhost:3000/movies/1 HTTP/1.1

###
POST http://localhost:3000/movies/ HTTP/1.1
Content-Type: application/json

{
"title": "sung",
"year": 2020,
"genres": ["mind blown"]
}
  • 확장자는 http로 한다
  • 한 파일에서 여러 개의 리퀘스트를 작성할 때는 ###으로 구분하여 작성한다
  • 리퀘스트 작성할 때 메서드(get, post, put, delete,…)를 입력하면 자동완성 스니펫을 제공한다
  • 단축키로는 ctrl alt R로 리퀘스트를 보낼 수 있다

Variables

envExample.http
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@endpoint = http://localhost:3000

###

POST {{endpoint}}/login HTTP/1.1
Content-Type: application/json

{
"username": "sung",
"password": "1234"
}

###

GET {{endpoint}}/profile HTTP/1.1
  • 변수를 사용할 수 있다
  • 계속 중복해서 사용하는 문자열이나, 나중에 변경될 여지가 있는 것들을 변수로 만들 수 있다

Environments

  • ctrl alt e 로 환경을 설정해 줄 수 있는데, 먼저 환경을 만들어야 한다
.vscode/settings.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
// ...
"rest-client.environmentVariables": {
"$shared": {
"version": "v1",
"prodToken": "foo",
"nonProdToken": "bar"
},
"local": {
"version": "v2",
"host": "localhost",
"token": "{{$shared nonProdToken}}",
"secretKey": "devSecret"
},
"production": {
"host": "example.com",
"token": "{{$shared prodToken}}",
"secretKey": "prodSecret"
}
}
}
  • .vscode/settings.json 에 json으로 정의해줄 수 있다
  • 이제 ctrl alt e 명령으로 원하는 환경을 선택해 사용한다

활용

2개의 유저로 번갈아 가면서 테스트할 때 활용했다

  • .vscode/settings.json 에 user1, user2의 토큰을 적는다

  • 스위치 해가면서 같은 api를 실행한다

쿠키 지우기

참고

SSG, static site generator

  • 정적 사이트 생성기
  • react와 같은 spa 라이브러리/프레임워크로 생성한 spa를 여러 html로 쪼개 준다
  • SSR 도구 예 ; nextjs, hexo,…

같이 보기

파워셸에서 도커 명령어 파이프

linux shell
1
docker stop `docker ps -aq`
  • 모든 컨테이너를 종료하는 명령이다
  • 리눅스에서는 백틱(backtick, `)으로 묶어서 결과를 파이프할 수 있다
  • 윈도우 터미널에서 같은 명령을 사용할 수가 없다… ㅠㅠ

PowerShell

powershell
1
docker ps -aq | ForEach-Object { docker stop $_ }
  • 나는 파워셸 디폴트로 사용하는데, 파워셸에서 이전 명령의 결괏값을 어떻게 다음 명령으로 넘겨줄 수 있는지 알아보았다 (파이프)
powershell
1
2
3
4
echo 1 2 | ForEach-Object { echo "value: $_" }
# output:
# value: 1
# value: 2
  • 단일 값이 아니라 배열 값을 받는 경우 ForEach-Object을 사용해야 하는 것을 알았다

참고

typescript Partial

자주 쓰는 타입 유틸 ; Partial, Pick, Omit, Record

Partial

  • Partial을 사용해서 각 필드를 옵셔널로 만들 수 있다
example.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type Todo = {
title: string;
description: string;
};

const updateTodo = (todo: Todo, fieldsToUpdats: Partial<Todo>) => {
return { ...todo, ...fieldsToUpdats };
};

const todo1: Todo = {
title: 'be super',
description: 'power overwhelming',
};

const todo2 = updateTodo(todo1, { description: 'show me the money' });

console.log(todo2);

Pick

Pick.ts
1
2
3
4
5
6
7
type Todo = {
title: string;
description: string;
time: string;
};

type Todo2 = Pick<Todo, 'title' | 'time'>;

참고

start nestjs

node의 spring을 배워보자

nest cli 설치

terminal
1
npm i -g @nestjs/cli

commands

terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 현재 디렉터리에 nest project init
nest new .

# run (dev)
yarn start:dev

# generate service
# nest g service {newServiceName}
nest g service pusher

# build
yarn build

# run (prod)
yarn start:prod

공부한 강의들

참고

prototype function vs. method function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Person(name, nickname) {
this.name = name;
this.nickname = nickname;

// method function
this.sayHi = function () {
console.log(this.name, this.nickname, 'hello', this);
};
}

const sung = new Person('sung', 'superpower');
const sung2 = new Person('sung', 'superpower');

console.log(sung.sayHi === sung2.sayHi); // false

Person.prototype.sayHello = function () {
console.log('sayHello prototype');
console.log(this.name, this.nickname, 'hello', this);
};

console.log(sung.sayHello === sung2.sayHello); // true
  • 생성자가 실행될때마다 새로운 메서드 함수가 생성된다
  • 프로토타입으로 정의된 함수는 모든 인스턴스가 하나의 함수를 바라본다

참고