0%

최근 AWS의 EC2 인스턴스가…

현재 베타 테스트로 진행 중인 AWS의 EC2 인스턴스가 자꾸 상태이상 1/2 상태로 되면서 접속이 불가능했었다.
간헐적으로 일어나는걸 보면 뭔가 문제가 좀 심각한 거 같았다.

AWS를 잘 쓰는 타입은 아니라서…
클라우드 워치인가 모니터링 툴을 봤는데 CPU 사용률이 갑자기 치솟다가 멈춰 버리는 구간이 보였다.

정확히 표현하면 내가 운영하는 서비스에 로그가 기록되는데, 일정 시간 마지막 로그를 보면 그 CPU 사용률이 튄 뒤부터 로그가 끊겼다.
그렇다고 내 서비스가 CPU 파워를 엄청 쓰는 것도 아니고…접속률은 베타라서 그렇게 많지 않다.

커널 로그인가에서 메모리 관련 에러를 찾아봤지만 없었다. (근데 메모리가 범인…)

도데체 뭐가 문제인가 하다가 이것저것 검색을 하던 도중 나랑 비슷한 증상을 가진 글 을 보게 되었다.
여기에 나온것과 같이 메모리 문제였다.

근데 나 같은 경우 위에서 나온 명령어는 동작하지 않았다.

내 환경은 Ubuntu 20.04 LTS였다. (물론 지금 베타테스트 환경은 또 다르다…)
위 운영체제를 기준으로 작성하겠다.

Swap 생성

  1. sudo fallocate -l 10G /swapfile
  2. sudo chmod 0644 /swapfile
  3. sudo mkswap /swapfile
  4. sudo swapon /swapfile
  5. free -m

위 명령어를 풀어서 설명하면…

  1. 스왑 파일을 만드는 것 (난 대략 10Gb 정도 잡았다.)
  2. 권한을 준다
  3. 스왑 생성
  4. 스왑을 실행
  5. 메모리 할당 확인 (아래 확인 -> 숫자는 임의로 적음 참고만..)
1
2
3
              total        used        free      shared  buff/cache   available
Mem: 968 485 90 0 393 330
Swap: 10239 260 9979

만약 뭔가 꼬이거나 스왑을 풀어야 할 경우 다시 아래대로 해준다.

Swap 해제

  1. sudo swapoff -v /swapfile
  2. sudo rm /swapfile
  3. free -m

보충 설명은 아래…

  1. 스왑 해체
  2. 스왑 파일 제거
  3. 스왑이 풀렸는지 확인해본다

정리

EC2가 갑자기 내려가는 경우는 다양한데, 이번처럼 CPU 파워를 막 치고 가다 다운되는게 메모리 부족때문인지는 몰랐다.
사실 내가 잘못 로직을 짠게 있나 싶었는데…
무튼 이 뒤로 한 4일 갔는데 아직 증상이 나타나진 않고 안정적으로 잘 되고 있다.

찾아보니 스왑은 아무래도 램이 아닌 하드 또는 SSD를 쓰는 거라서 퍼포먼스에서 이슈가 발생할 수 있다.
하지만 베타테스트 운영이나 개발 목적으로는 스왑을 써도 충분한거 같다.

나중에는 결국 하드웨어 스팩을 돈으로 올려야 하겠지만 말이다. ㅎㅎ

Node.js에서 request를 사용하여…

현재 베타테스트 중인 내 프로젝트의 일부 기능을 Node.js로 변환하는 중이었다.
아직 Node를 학습하면서 붙이는 거라서 좀 익숙하지 않았다.

일단 진행하면서 겪은 문제의 포인트는 아래와 같다.

  1. 특정 사이트의 크롤링을 진행한 다음 해당 내역중에 필요한 데이터를 html 파싱 처리.
  2. 테스트 환경이 Node.js로 구축한 서버의 특정 url로 접근 시 1번 기능이 호출된다.
  3. 문제는 2번에 나온 url 호출을 하면 1번의 작업이 끝나고 그 결과를 json으로 뱉어야 하는데 {} 반환.

난 거의 Java로만 개발을 많이 했던 사람이라 (물론 python도 많이 썼지만 그건 좀 과거라 패스하고…) 순차적인 흐름에 익숙한 사람이다.
일단 코드로 보자

1
2
3
4
5
6
7
8
9
10
//route에서 크롤링 처리 결과를 가져와서 json으로 응답 처리해주는 함수
router.get('',(req, res, next) => {
res.json(crawling4Test());
});

function crawling4Test() {
.....
return someValue;
}

내 개념으로는 crawling4Test() 함수의 처리 결과가 끝나고 그 반환 값을 res.json() 에 전달하여 Json 응답이 처리되는 것으로 이해하고 있었다.
근데 아니었다.
먼저 crawling4Test() 함수의 로직도 함께 보자.

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
29
30
31
32
33
34
35
36
37
function crawling4Test() {
let targetUrlReq = {
url:'https://target_url.com',
method: 'GET',
timeout: 5000,
}

let resultJson = {};

request(targetUrlReq, function(err,res,body) {
if (!err && res.statusCode === 200) {
const enc = charset(res.headers, body)
const i_result = iconv.decode(body, enc)
const resultHtml = cheerio.load(i_result);

const regex = /[^0-9]/g;
let targetA = resultHtml('div.target_a_tag).text().replace(regex, '');
let targetB = resultHtml('div.target_b_tag).text().replace(regex, '');

//체크용
console.log('targetA = ' + targetA)
console.log('targetB = ' + targetB)

resultJson['targetA'] = targetA;
resultJson['targetB'] = targetB;

resolve(resultJson);
}
else {
console.log(`error${res.statusCode}`);
resultJson['error'] = 'Some error';
reject(resultJson);
}
});

return resultJson;
}

위에서도 언급했지만 저것의 처리 결과는 {} 비어있는 딕셔너리 객체였다. (뭐 Map, Key-value 다양한 이름이지만 본문에서는 딕셔너리라 표현)
근데 또 신기한 것은 crawling4Test() 함수 안에서 console.log 를 통해 로그를 띄우면 값은 잘 들어있다.
내가 원한건 router.get() 함수에서 crawling4Test() 함수의 처리를 기다리고 응답이 완료되면 res.json() 로 결과를 내보내는 동기적 처리 방식을 기대했던 것.

그럼 원인은?

그냥 함수들이 비 동기로 실행되었다.

이 표현이 맞는지 모르겠지만 무튼 문맥상으로는 저렇게 표현했다.
내가 원하는 결과물은 동기처럼 보이는 순차적 비동기 뭐 좀 편한 표현으로 하나의 흐름으로 동작하는 비동기 였다.

그래서 찾아보니 node에서는 비동기를 하나의 흐름으로 처리하기 위해서는 promise 그리고 await, async 라는게 필요했다.


그래서 promise, await, async 이것들은 대충 감이 오는데…

Node를 공부하는 사람이라면 주요 특징점이나 문제점(?) 같은걸 많이 들었을 것이다.
그 중 하나가 콜백지옥 이다.
이거는 하도 설명이 많이 나와서 난 패스하겠다.
궁금하신 분은 검색하면 다른 블로그나 유튜브에 아주 자세히 설명되어 있으니 그곳을 참고해주시길…

무튼 promiseawait, async 이거 3가지만 잘 조합하면 깔끔하게 처리할 수 있다.
(초창기 버전에서는 엄청 복잡했다는데..시간이 지나니 점점 편해지는건 덤…)

promise에 대해 설명글 쓰면 또 엄청 길어지니까…간단하게 말하자면..

“A promise is an object that may produce a single value some time in the future”
하나의 요청 처리가 끝날때까지 기다리지 않고 다른 요청을 동시에 처리할수 있는 방식 ()

promise 소개 문구는 저렇다.
즉 비동기를 하겠단 이야기인데 콜백의 지옥을 파훼하기 위한 해법이라 하는데 얘도 사실 보면 장황하지 않을 뿐 비슷하다.
그래서 await, async 이거 두 개랑 같이 쓰면 그 때는 어느정도 파훼법이 완성된다.

이번 문제도 같다.
그럼 이걸 어떻게 해결했는지 한번 알아보도록 하자


처리한 방법

먼저 변경된 crawling4Test() 함수를 보자.

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
29
30
31
32
function crawling4Test() {
let targetUrlReq = {
url:'https://target_url.com',
method: 'GET',
timeout: 5000,
}

return new Promise((resolve, reject) => {
let resultJson = {};

request(targetUrlReq, function(err,res,body) {
if (!err && res.statusCode === 200) {
const enc = charset(res.headers, body)
const i_result = iconv.decode(body, enc)
const resultHtml = cheerio.load(i_result);

const regex = /[^0-9]/g;
let targetA = resultHtml('div.target_a_tag).text().replace(regex, '');
let targetB = resultHtml('div.target_b_tag).text().replace(regex, '');

resultJson['targetA'] = targetA;
resultJson['targetB'] = targetB;

resolve(resultJson);
}
else {
resultJson['error'] = 'Some error';
reject(resultJson);
}
});
});
}

일단 반환 값이 json 이 아닌 Promise로 바뀌었다.
그거 외에는 로직은 같지만 반환의 경우 resolve 와 reject 인데 이거는 어렵지 않다.
해당 값을 다시 또 가공하여 처리하는 함수를 호출해야 하는 경우 then() 으로 체이닝 해서 처리하면 되고, 예외가 생길 경우에도 마찬가지 이다.
이 글에서는 Promise에 대해 설명하는 공간은 아니기에 간략하게 여기까지만 알아보자.
(사실 너무 많은 자료가 많아서…다른 분들꺼 참고하자 <하단에 참고로 주렁주렁 달아 놓을 예정>)

이제는 그럼 저 함수를 호출하는 곳으로 가보자

1
2
3
router.get('',async (req, res, next) => {
res.json(await crawling4Test());
})

그냥 단어 몇 개가 사이에 박힌거 빼곤 없다.
await 키워드는 promise를 반환하는 함수 앞에 써주고, async 키워드는 await 선언이 된 곳에 써주면 된다.
이것도 여기서는 이렇게만 설명한다.
좀 더 자세한 글은…아시죠? ㅎㅎ

그래서 결국 저렇게 처리한 상태로 실행해보면 드디어 원하는 결과가 잘 나오게 된다.


결론 및 여담

Node는 뭔가 자바에서 온 사람을 당황하게(나만 그럴수 있다) 만드는 게 많은듯…
promise, async, await 에 대해 자세하게 알고 있음 좋을 것 같다.

엄청 딥하게 알면 더 좋겠지만…
사실 구현하는데 바쁘니… 어떤 식으로 동작하는지…그리고 어떻게 사용하면 ㅈ 되는지, 어떻게 사용해야 하는지만 알면 될 것 같다.

원리까지 설명하세요 이러는 건 면접에서나 하는거겠지?
근데 사실 이런거 면접에서 딥하게 묻는 것도 문제가 있는듯..

위에 언급한 대로 어떻게 사용하는지 정확한 이해도 체크만 하면 되는데 이거 동작 방법을 화이트보드에 설명해보세요 한다?
그건 면접자에게 질문을 잘못 던진 케이스 같다.

그런 질문 보다는 이걸 어떻게 썼을 때 잘못된 경우 있었냐? 이걸 어케 대처해야 하냐?
이게 옳바른 질문 아닐까? ㅎㅎ

내가 예전에 3년전인가… 면접다닐때…특히 스프링 자바는 진짜 되도 않는 면접 질문 많이 받았다.
네이버랑 카카오 전화면접에서는 GC에 대해 다 설명해보고 java8의 GC가 뭐가 틀린지 설명해보랜다…
아니 트러블슈팅 성향이나 프로젝트에서 겪은 장애 처리나 어떻게 구현했냐 질문보단 저런걸로…

아마 떨어트리려고 한거 같다는 생각이 많이 든 면접…(아님 내 정신승리일 수도…)

그냥..다시 이런거 찾아보고 공부하다가 옛날 생각나서 주절거려봤다.

참고

Hexo 설치 글을 보면…

이게 뭐 도움이 될지 모르겠지만…
나는 hexo 설치할 때 npm 이라는거 대충 알았지 자세히는 몰랐다.
그래서 거기 가이드에서 설치할 때 보면

npm install hexo -g

이렇게 글로벌로 설치하게 하는데 이건 내 생각에 좋은 방법은 아닌 것 같다. (나한테는?)

난 보통 어떤 프로젝트나 모듈이 프로젝트 내에서만 영향을 줘야지 공통으로 사용하는 곳까지 설치되어 거기서 끌어다 쓰는 형식을 안 좋아한다. (정말 싫어한다 -_-;;)

그래서 이번에 노드를 학습하면서 이렇게도 관리할 수 있겠구나 싶어서 공유한다.
뭐 다 아는 사실이겠지만…
hexo 사용할 디렉토리에서 아래의 명령어 대로 설치한다

npm install hexo

이렇게 -g 옵션만 빼면 로컬에서 사용할 수 있는데 여기서 한가지 더..
path를 등록해줘야 한다.

난 mac 에서 zsh를 사용하기에..
자신의 홈 디렉토리에 .zprofile 하나 만들어준다. (만약 있으면 맨 밑에 추가한다)

PATH=”$PATH:/Users/name/hexo_blog_path/node_modules/.bin”

당연한 이야기겠지만 위 경로는 자신에게 알맞는 곳을 찾되 node_modules 경로를 잡아주는게 포인트다.

위와 같이 추가 후 터미널에서 갱신해주면 끝

source .zprofile

참고

Hexo

Node에서 환경 변수를 사용하는 법? (설정 파일로 관리하기)

내가 Spring boot로 개발할 때는 application.yml에 설정을 넣고 개발을 했다.
그러다가 설정에 넣은 값에 변경이 필요할 경우 서버를 내렸다가 올려야 하는 문제가 생겼다.
(물론 이중화 되어 있다 하더라도 이렇게 하는건 비효율적..)

그래서 Spring config server를 사용해서 처리하였다.
Node.js는 이런 비슷한게 있나 찾아보다가…
아주 똑같지 않지만 설정 파일을 외부에 두고 사용할 수 있는 것을 찾았다.
(Node를 첨 다뤄보니 이런게 있는줄 몰랐다)

dotenv

먼저 설치를 진행한다.
(yarn 을 사용하였는데 npm도 똑같다)

yarn add dotenv

설정 내용을 선언

설정 파일을 만드는 형태는 두 가지가 있다.

여기서는 ES6 문법으로 설명한다. (CommonJS 는 간략하게만 표기..)

1. .env 파일 사용

프로젝트 내에 (보통은 자신 프로젝트 루트에) .env 파일을 생성한다
그리고 아래와 같이 설정을 기재한다.

1
2
3
4
5
#SERVER CONFIG

SERVER_PORT = 3001
SERVER_NAME = HELLO_SERVER
SERVER_DIS = 'HELLO_SERVER';

그리고 불러올 js에서는 아래와 같이 사용한다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//CommonJS
//require("dotenv").config();

//ES6
import dotenv from "dotenv";
dotenv.config(); //1 -> config 호출

const port = process.env.SERVER_PORT;

function checkTest() {
console.log('SERVER_NAME = ' + process.env.SERVER_NAME);
console.log('SERVER_DES = ' + process.env.SERVER_DES);
}
...

주의할 점은 1번 config() 호출 전에 process.env를 사용하면 에러가 난다. (ES6, CommonJS 둘다 동일)
그리고 .env 파일의 경로가 다른 곳에 있는 경우 아래와 같이 config 함수를 수정하면 된다.

1
2
3
4
5
6
//CommonJS
//require("dotenv").config({path:'/your/env/path/.env.dev'});

//ES6
import dotenv from "dotenv";
dotenv.config({path:'/your/env/path/.env.dev'});

단 .env 파일이 존재하는 경우 위 내용은 적용이 안된다. (기존 .env 파일 따라감)

참고로 SERVER_DIS 출력해보면 SERVER_DES = ‘HELLO SERVER’; 와 같이 따옴표가 같이 출력된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
console.log('SERVER_NAME = '  + typeof process.env.SERVER_NAME);
console.log('SERVER_DES = ' + typeof process.env.SERVER_DES);

console.log('SERVER_NAME = ' + process.env.SERVER_NAME);
console.log('SERVER_DES = ' + process.env.SERVER_DES);

///Output

SERVER_NAME = string
SERVER_NAME = string

SERVER_NAME = HELLO SERVER
SERVER_DES = 'HELLO SERVER';

2. config.js 등 js 파일로 사용

이건 .env 랑 비슷하지만 사용법은 약간 다른데 먼저 원하는 곳에 config.js 파일을 생성해주고 그곳에 설정을 담는다.

1
2
3
4
5
6
7
8
9
10
11
let configData;

configData = {
SERVER_PORT: 3001,
}

//ES6 방식
export default { configData };

//Common JS 방식
// module.exports = configData;

그리고 필요한 곳에서 다음과 같이 사용한다.

1
2
3
4
5
6
//ES6
import secondConfig from "./config.js"

....

console.log('process.env.PORT = ' + secondConfig.configData.SERVER_PORT)

만약 Babel을 사용한 ES6 사용을 한다면 js 확장자는 무시해도 되지만, 미 사용시 .js 확장자를 붙여줘야 한다.

그리고 저기 나온 예제에 있는 export 방식 말고도 여러 방식이 있다.
본문 하단의 링크를 참고하자.

참고

Import와 export

VSCode로 Node 개발을 진행하다가…

공부 겸 이번 프로젝트에 적용시키려고 Node를 공부하고 예제를 돌려보려던 중…
이상한 점을 발견했다.

express를 분명 yarn add express 이렇게 로컬 프로젝트 영역에 설치했음에도 VSCode에서 해당 모듈을 참고하는 곳은 엉뚱한 곳을 가리키고 있었다.

경로가 Mac OS 기준으로..

/User/YourHome/Library/Caches/typescript/YourVersion/node_modules/@types/….

이상해서 저기를 열었다가 지워도 똑같이 생성되고 계속 참조했다.
그래서 이곳저곳 찾다가…
아주 간단하게 해결하였다.

Solution

  1. VSCode의 환경설정을 들어가서 (Mac 기준 : Command + ,) 검색창에 아래의 키워드 검색
  2. disableAutomaticTypeAcquisition 이거 항목이 체크가 안되어 있을건데 체크해준다.
  3. 라이브러리 참조 영역을 삭제하고 VSCode 재시작 해본다.

참고

Let’sEncrypt 갱신이 불가능??

Let’sEncrypt를 적용하고 나서 갱신 테스트를 해보는데 이상한 에러를 마주했다.

1
2
3
4
5
Attempting to renew cert (dev.net) from /your/letsencrypt/path/renewal/dev.net.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration.

The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.'). Skipping.
All renewal attempts failed. The following certs could not be renewed:
/your/letsencrypt/path/live/dev.net/fullchain.pem (failure)

아 뭐가 이렇게 안되지? 라고 삽질했었으나…
이것저것 찾아본 결과 아래의 문제가 원인이었다

원인은 갱신을 auto 모드가 아닌 manual 모드로 진행한 문제

원인을 제공했던 명령어는 다음과 같다

1
sudo certbot certonly --manual --preferred-challenges=dns --email test@test.com --server https://acme-v02.api.letsencrypt.org/directory --agree-tos --debug --no-bootstrap -d dev.net

메뉴얼 모드로 만든 인증서는 자동으로 갱신이 불가능하다.
그래서 난…다시 오토 모드로 새로 만들었다…

이 문제를 겪으신 분은 다시 오토 모드로 빠르게 시작하는걸…추천한다..
난 어떻게 해보려다가 1시간 말아먹었다…

Let’sEncrypt 유효기간?

혹시 아직 Let’sEncrypt를 설치하지 않으신 분이라면 Let’sEncrypt 설치후 AWS에 적용하기 에 설치법을 참고하시길 바란다

Let’sEncrypt는 무료인 대신에 인증서를 주기적으로 인증해줘야 한다
그래서 보통 이것을 크론탭으로 처리해서 편하게 간다.

경각심(?)을 위해 직접 갱신하는 분(?)도 봤지만…자동으로 하는게 정신 건강에 좋다..
물론 LetsEncrypt 팀에서 메일을 주기도 한다. (만료 10일전, 당일) 이렇게?

저번에 크론탭으로 해뒀는데 뭔가 잘못 건들여서 실행이 안되어 이번에 다시 셋팅하게 되었고 내용을 정리해서 올려본다.

Let’sEncrypt Crontab 적용해보기

갱신 기간 여부 확인

LetsEncrypt 인증서는 90일 유효하며, 만료 20일 전부터 갱신이 가능하다
갱신이 가능한지 여부는 아래의 명령어를 통해 확인이 가능하다

sudo certbot certificates

1
2
3
4
5
6
7
8
9
10
11
12
13
ubuntu@:~$ sudo certbot certificates
Saving debug log to /your/letsencrypt/path/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: dev.net
Serial Number: 22233344URSerialNumber
Key Type: RSA
Domains: dev.net
Expiry Date: 2123-12-31 00:00:00+00:00 (VALID: 89 days)
Certificate Path: /your/letsencrypt/path/fullchain.pem
Private Key Path: /your/letsencrypt/path/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

인증 기간이 20일 이하면 가능하다.

갱신 여부 확인

먼저 갱신이 제대로 되는지 테스트를 해보려면 아래의 명령어를 수행해본다

sudo certbot renew –pre-hook “service nginx stop” –post-hook “service nginx start” –dry-run

미들웨어는 자신이 맞는거를 사용하면 된다 (필자는 nginx)
뒤에 –dry-run 이 테스트를 수행하게 해주는 옵션이다.

1
2
3
4
5
6
7
8
9
10
11
12
ubuntu@:~$ sudo certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start" --dry-run
Saving debug log to /your/letsencrypt/path/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /your/letsencrypt/path/renewal/dev.net.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for dev.net

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
/your/letsencrypt/path/live/dev.net/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

위와 같이 축하한다고 뜨면 인증하는데 문제가 없다는 뜻이다.

PS : 만약 인증이 안된다고 뜨고 에러에 다음과 같은 구문(produced an unexpected error The manual plugin is not working) 이 있는 경우 이곳을 참고하자.

갱신 처리 (With crontab)

먼저 크론탭을 열어 작성해주고…

crontab -e

만약 크론탭이 먼저 선등록 되어 있는지 확인하려면..

cat /etc/crontab -> 등록된 크론탭 확인

먼저 난 3개월마다 매 1일에 스크립트를 수행하게 해줬다.
크론탭 명령어는 아래와 같이 작성했다.

1 0 1 1-12/3 * sudo certbot renew –pre-hook “service nginx stop” –post-hook “service nginx start” >> /mylog/letsencrypt/log/$(date ‘+%Y%m%d’).log

그리고 마지막으로 크론탭을 재시작 해준다.

sudo service cron restart

그럼 이제 정상적으로 등록이 된 것이다.

Let’sEncrypt?

이번에 서비스를 준비하면서 EC2에서 하나씩 올려서 해보기로 했다.
사실 AWS 기반이라 로드벨런서에 인증서 물리면 되는데…
전에 해보던게 생각 나기도 했고..
일단 서비스 규모가 더 커지면 그 때 안정적으로 가고 지금은 빌드업 수준으로 해보기로 했다.

일단 뭐 Let’sEncrypt에 대한 자세한 것은 이미 알고 있다는 가정 하에 바로 설치법부터 들어간다.

그 전에 환경은..

AWS 기반 EC2 Ubuntu 20.04 LTS 기준으로 작업을 진행
Nginx 사용 <- 중요하진 않음

Part 1 설치 커맨드

아래의 커맨드로 하나씩 진행하였다

1
2
3
4
5
6
sudo apt update
sudo snap install core; sudo snap refresh core
sudo apt-get remove certbot
sudo snap install --classic certbot # 설치
sudo ln -s /snap/bin/certbot /usr/bin/certbot # 링크
sudo certbot certonly --email [인증에 사용할 이메일] --standalone -d [적용할 도메인] 실행

커맨드 설명은 아래와 같다

1번 : 설치 전 업데이트 처리
2번 : 필요한 것들 설치
3번 : 기존에 설치된 certbot이 있다면 제거
4번 : certbot 설치
5번 : 심볼릭 링크 생성
6번 인증서 만드는데 email은 인증에 대한 대표자 메일(필자는 주로 쓰는 메일 사용)을 적고 -d는 적용할 도메인을 적어준다 (elfinlas.io.xx 등)

6번 명령어 이후 아래와 같이 뜨면 정상적으로 된 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ubuntu@ip$ sudo certbot certonly --email test@test.com --standalone -d dev.net
Saving debug log to /your/some/path/letsencrypt.log
Requesting a certificate for dev.net

Successfully received certificate.
Certificate is saved at: /your/some/path/letsencrypt/live/dev.net/fullchain.pem
Key is saved at: /your/some/path/letsencrypt/live/dev.net/privkey.pem
This certificate expires on 9999-99-99. <= 여긴 인증기간은 3개월인가 줘서 사람마다 틀림
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

커맨드에 대해 좀더 설명이 필요한 분은 이곳 에서 직접 확인해보자

Part 2 AWS 작업

이렇게 진행하고 나서 AWS 콘솔로 가준다
콘솔에서는 다음과 같은 절차로 진행한다

  1. AWS 콘솔에서 Certificate Manager 이동
  2. 인증서 선택에서 각 항목에 해당 하는 값을 가져온다. (아까 생성한 pem 파일을 사용)
    1. 인증서 본문 => cert.pem
    2. 인증서 프라이빗 => privkey.pem
    3. 인증서 체인 => fullchain.pem
  3. 마무리 하면 ec2에 접속해서 콘솔에서 아랴와 같이 nginx를 재시작 해준다.
    1. sudo service nginx restart

아마 다른 블로그에서는 설치법만 나오고 보통 AWS 설명도 약간 부실했는데 직접 찾아보고 적용한 방법이다.
그리고 기반은 nginx 인데 아파치 쓰거나 다른 미들웨어 쓰시는 분들은 똑같이 서비스만 재시작 하면 된다.

인증서

처음 node를 하려다가…

이번에 진행하는 프로젝트에 노드를 적용해보려고 노드 공부를 시작했다.
노드 환경을 구축하고, npm은 문제가 많아서 페이스북에서 만든 yarn이라는걸 많이 쓰는 추세라 하여…
yarn을 사용하기로 마음먹고 실행해봤다.

그런데 역시 처음엔 고통과 배움의 시간이 필요하듯…
이상한 문제가 나에게 찾아왔다.

프로젝트를 지웠다가 다시 해도 계속 발생하고, 검색을 해도 잘 안나오거나 뭐라고 하는지 이해가 잘 안되었다.
지금 생각해보면 너무나도 간단한 문제였지만 -_-;;

내가 찾은 솔루션은 이 문서 였다.
내용을 요약하면…

너가 지금 하려는 디렉토리의 상위쪽에 package.json 또는 yarn.lock 파일이 존재한다

맨 처음엔 ‘상위에 저런게 있을리가 없지’ 라면서 그냥 넘겼는데..
도저히 못찾아서 헤매다가…

HEXO

그렇다.
이 블로그는 hexo로 만들어졌고, hexo는 node.js로 만들어졌는데, 이 hexo를 깔면서 홈 디렉토리에 뭔가를 했던 기억이 생각났다…
그리고 확인 결과….역시 있었다. (package-lock.json package.json)

그리고 두 파일을 제거하고 yarn 명령어를 사용했더니 잘 된다 -_-;

결론은 항상 안되면 솔루션의 글을 잘 읽고 확인도 잘 해보자.

iTerm2 에서 경로가 깨저서 나오는 경우

위와 같이 깨질 경우 설정에서 폰트를 바꿔주면 된다.

Preferences(command + ,) -> Profiles 탭 -> Text 항목 -> Font를 변경

위와 같이 변경한 경우 깨지는것은 사라진다.