먹고 기도하고 코딩하라

Node.js로 카카오톡 학식 채팅봇 만들기 (3) - pm2로 데몬화, nginx 설치와 크롤링 자동화 본문

개발일지

Node.js로 카카오톡 학식 채팅봇 만들기 (3) - pm2로 데몬화, nginx 설치와 크롤링 자동화

사과먹는사람 2020. 9. 7. 13:43
728x90
728x90

이전 글 보기

 

Node.js로 카카오톡 학식 채팅봇 만들기 (2)

이전 포스팅 Node.js로 카카오톡 학식 채팅봇 만들기 (1) 원래 Python3 + Django2 조합으로 카카오톡 챗봇을 만들어 운영하고 있었는데요. (관련 튜토리얼) 이제 노드에 전념해보고자 기존에 운영하던 ��

dev-dain.tistory.com

 

저번에는 학식봇을 끝까지 만드는 스크립트를 짰습니다. 이제 남은 문제는 putty가 꺼져도 EC2 인스턴스는 계속 node 프로세스를 작동할 수 있도록 daemonize 해주는 것입니다.

이를 위해서 프로세스 매니저 모듈을 사용하게 되는데 많이 사용하는 것으로는 forever, nodemon, pm2 등이 있습니다. 그 중 저는 pm2를 사용하기 때문에 pm2를 사용해서 putty를 꺼도 EC2에서 프로세스가 계속 동작하도록 만들어 보겠습니다.

 


 

1. pm2로 프로세스 데몬화

여기서는 pm2 사용법을 자세히 다루지는 않고, 코드가 크리티컬하게 바뀔 때마다 자동으로 재시작하고 서버가 종료되었다가 다시 시작했을 때 자동으로 프로세스를 재시작하도록 하는 것만 다루겠습니다.

pm2 사용법에 대해서는 따로 좋은 글이 있기에 소개합니다. 

 

노드를 더 우아하게. pm2 이야기

이번에는 노드를 더 우아하게 사용할 수 있도록 돕는 PM2 에 대해 이야기를 해본다. PM2 는 Process Manager 의 약자로 이미 단어에서 모든게 설명 되는데 노드 프로세스를 관리해주는 역할을 한다. 아�

jybaek.tistory.com

 

일단 루트 폴더에서 pm2를 설치해줍니다. 전역으로 설치해주려면 뒤에 -g를 붙여 입력하면 됩니다.

$ npm i pm2

 

pm2를 설치한 다음에는 start 명령어로 노드 프로세스를 실행할 수 있습니다. 스크립트 이름이 'app.js'라면 다음과 같이 입력하면 됩니다. 만약 app이 아닌 다른 이름으로 관리하고 싶다면 '--name' 옵션을 줘서 관리할 수 있습니다.

$ pm2 start app.js

# haksik으로 관리하고 싶은 경우
$ pm2 start app.js --name "haksik"

 

그 후 pm2가 만든 테이블을 배시에서 확인할 수 있는데요. pm2로 어떤 프로세스들이 동작하고 있는지 확인하고 있다면 list 명령어를 사용해 확인할 수 있습니다.

$ pm2 list

 

현재 저는 fork 모드로 app 하나만을 실행 중입니다. 프로세스를 중단하고 싶다면 stop을, 아예 pm2에서 내리고 싶다면 kill 명령어를 쓰면 됩니다. 이 때는 프로세스의 이름이 아닌 id 값을 인자로 주게 됩니다. stop은 pm2 리스트에는 있지만 실행하지 않는 것이고, kill은 pm2 리스트에서 아예 프로세스를 지워버리는 것입니다.

$ pm2 stop 0
$ pm2 kill 0

 

돌고 있는 프로세스를 재시작하고 싶다면 restart 명령어를 쓸 수 있습니다. 여기서는 응용으로, 코드가 바뀌는 것을 감지하고 자동으로 재시작을 할 수 있도록 --watch 옵션도 달아보겠습니다.

$ pm2 restart app.js --name "haksik" --watch

 

이렇게만 하고 putty를 꺼도 괜찮지만, 이 때는 서버 컴퓨터가 예기치 못한 사고로 종료되었다가 재시작되었을 때 그냥 꺼진 상태로 유지됩니다. 컴퓨터가 꺼졌다가 다시 켜졌을 때 시작 프로그램처럼 자동으로 실행된다면 좋겠죠? 이럴 때는 startup 명령어를 사용합니다.

$ pm2 startup

 

pm2 startup 명령어를 입력하면 현재 pm2 리스트에 있는 프로세스들을 서버가 종료되었다가 다시 켜졌을 때 즉각 다시 실행하는 것을 보장하게 되는데요.

입력하고 나면 sudo env~ 하면서 명령어가 출력되는데 그것을 그대로 복사해서 배시에 다시 붙여넣으면 굉장히 많은 명령어가 눈앞을 스쳐 지나갑니다. save 명령어를 입력해주면 작업은 끝입니다.

$ pm2 save

 

sudo reboot 명령어로 강제로 서버 컴퓨터를 재시작하고 나서 pm2 list를 출력해보면 종료 전 리스트에 있던 것과 같은 프로세스들이 있음을 볼 수 있을 것입니다.

만약 재시작 프로세스에서 내리고 싶다면 unstartup 명령어를 사용하면 됩니다.

 

 

 

2. 크론탭으로 크롤링, 후처리 자동화

축하합니다. 여러분의 프로세스는 이제 daemonize 되어 putty가 종료되어도 계속 챗봇과 대화할 수 있게 됐습니다.

하지만 1주일에 한 번 정도 다시 들어가서 crawl.js와 process.js를 실행해줘야 할 것입니다. 학식은 1주일에 한 번씩 새로 올라오는데 그 때마다 크롤링해주지 않으면 챗봇이 옛날 식단을 답변으로 주게 될 테니까요.

이것까지 자동화하려면 crontab을 사용하면 됩니다.

crontab에 대한 설명은 제가 과거에 써둔 포스트로 대체하겠습니다. 여기서는 구체적으로 해야 할 일들만 적어둡니다.

 

카카오톡 챗봇 서버에 크론탭 등록해서 자동 크롤링하기

전에 제가 카카오톡 i 오픈빌더를 파이썬 장고와 Amazon EC2를 이용해서 만든 튜토리얼을 올린 적이 있죠 ^^ 카카오톡 학식봇 만들기(1) - 동적 웹페이지 크롤링 방법이 정적 웹페이지와 다른 이유 ��

dev-dain.tistory.com

크론탭을 사용하기 전 유의하셔야 할 점은, 따로 타임존을 설정하지 않았다면 서버의 시간이 한국 시간보다 9시간이 느릴 거라는 점입니다. 그렇다면 먼저 배시에서 다음 명령어를 입력해 타임존을 한국으로 변경합니다.

$ sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

 

다시 재부팅을 해보면 한국 시간으로 서버 시간이 맞춰져 있을 것입니다.

부팅했을 때의 디렉토리 위치인 /home/ubuntu 위치에 autoCrawl.sh 라는 배시 쉘 스크립트를 만듭니다.

$ vi autoCrawl.sh

#!/bin/sh
cd [프로젝트 디렉토리 경로]
node crawl.js
node process.js
pm2 restart app.js --watch

 

저장하고 나온 다음 crontab을 열어 autoCrawl 스크립트를 정해진 시간마다 자동으로 실행할 수 있도록 지정해 줍시다.

$ crontab -e

#방학중
0 11 * * 1-5 bash /home/ubuntu/autoCrawl.sh >> /home/ubuntu/crawlCron.log 2>&1
#주말
0 3 * * 0 bash /home/ubuntu/autoCrawl.sh >> /home/ubuntu/crawlCron.log 2>&1
#학기중
#*/10 9-11 * * 1-5 bash /home/ubuntu/autoCrawl.sh >> /home/ubuntu/crawlCron.log 2>&1
...

 

방학 중에는 월-금 매일 오전 11시마다 실행되도록 했습니다. 사실 계절학기가 끝나고 나서 완전 학식이 필요없을 때는 저 정도까지도 필요없긴 하죠. (그리고 요즘도) 그 때는 주석 처리를 해둡니다.

주말에는 일요일에 한 번 새벽 3시에 크롤링을 해서 가져옵니다. 우리 학교 학식 페이지는 일요일이 되면 자동으로 그 다음주로 넘어가 있기 때문에 한적한 시간대에 식단을 가져옵니다.

학기 중에는 식단이 바뀌는 일이 종종 있고, 월요일에는 특히 식단이 안 올라와 있을 때도 있기 때문에 오전 9-11시 동안 10분마다 한 번씩 크롤링을 하도록 해 줬습니다.

크론탭에 대한 설명이 필요하다면 위에 링크한 포스트를 읽어 보시기 바랍니다.

 

 

 

3. nginx를 리버스 프록시 서버로 사용하기

좀 오래된 발언이긴 하지만 Node.js를 만든 라이언 달(Ryan Dahl)은 nginx를 node.js 앱 앞단에 두는 것이 좋다는 의견을 표한 적이 있습니다. node 앱의 실제 포트를 숨기는 것이 주 목적 중 하나이고, 로드밸런싱, 보안, 가속화 등 리버스 프록시 서버의 장점은 많고도 많습니다. 굳이 쓰지 않을 이유가 없습니다.

 

3000 포트로도 만족하신다면 굳이 nginx를 설치할 필요는 없습니다만 나중에 node로 큰 프로젝트를 준비하신다면 nginx를 쓸 수도 있으니 한 번 다뤄보겠습니다. 별로 하고 싶지 않으시다면, 이 부분은 건너뛰셔도 괜찮습니다.

$ sudo apt-get update
$ sudo apt-get install nginx
$ sudo service nginx start

 

nginx를 설치한 후 service 로 nginx를 시작합니다. 이제 IP 주소:80 번이나 그냥 IP 주소를 브라우저 주소창에 입력하면 nginx 페이지가 나올 겁니다.

 

간혹 예전에 apache로 서버를 돌리던 분들 중 apache를 싹 밀고 nginx를 설치했음에도 IP 주소를 입력했을 때 apache It works! 하면서 아파치 페이지가 나오는 분도 계실 텐데요(접니다) 

apache가 삭제되었음에도 기본 html 파일이 지워지지 않아서 그렇습니다. 그럴 때는 다음 명령어를 입력해 주시면 됩니다.

$ cd /var/www/html
$ ls
index.html	index.nginx-debian.html
$ rm index.html
$ mv index.nginx-debian.html index.html

 

apache를 설치하지 않으신 분들은 아마 nginx가 바로 index.html 이 되어 있을 것입니다. 만약 비슷한 문제를 겪고 계신다면 다음과 같이 해결할 수 있으니 참고하시기 바랍니다.

 

이제 본론으로 돌아가 보겠습니다.

$ cd /etc/nginx/sites-available
$ sudo vi (app_name)

 

nginx의 sites-available 디렉토리에 가면 아직은 default 빼고 아무것도 없을 겁니다. 앱 이름을 임의로 지정해 파일을 만들어줍니다. 저는 'haksik'으로 정했습니다.

# haksik.vi

server {
	listen 80;
	server_name 탄력적 IP 주소;
	location / {
		proxy_pass http://127.0.0.1:3000;
	}
}

 

아래와 같이 작성합니다. 다른 것은 다 똑같이 적되 server_name 옆의 탄력적 IP 주소 자리는 EC2에서 받은 고정 IP 주소를 적으시면 됩니다. 포트를 따로 적거나 할 필요 없이 IP 주소만 적으면 됩니다.

proxy_pass의 포트 번호는 app.js에서 쓴 포트와 똑같은 포트를 적으시면 됩니다. 이렇게 하면 고정 IP 주소:80 번으로 들어온 요청이 실제로는 로컬의 3000번 포트로 넘어가게 된다는 것입니다. 외부에 포트 번호를 드러낼 필요가 없게 되죠.

저장하고 닫은 다음 명령어를 입력해줍니다.

$ sudo ln -s /etc/nginx/sites-available/[앱 이름] /etc/nginx/sites-enabled
$ sudo service nginx restart

 

ln 명령어는 링크 파일을 만들어 줍니다. -s 옵션은 심볼릭 링크를 만들어준다는데요. 심볼릭 링크는 윈도우 시스템의 바로가기와 비슷한 것이라고 생각하면 될 것 같습니다. 바탕화면의 바로가기 아이콘을 누르면 실제로 어떤 파일이나 프로그램이 바탕화면 위치에 있는 것이 아님에도 원래 디렉토리의 위치에 있는 파일/프로그램을 실행해 주는 것과 같은 이치라고 생각하면 되겠습니다.

그런 다음 nginx를 재시작해준 다음 브라우저 창에 IP 주소/keyboard 를 입력해보십시오. HTTP 요청은 자동으로 80번 포트이므로 굳이 포트 번호를 써줄 필요는 없습니다.

 

 

 

이렇게 나오면 성공입니다.

 

 

 

4. AWS, 카카오 i 오픈빌더 포트 설정

이제 마지막 작업이 남았는데요. 아마존 ec2 인바운드 규칙에서 3000번을 지워주는 것과 카카오 i 오픈빌더 페이지에서 포트 번호를 바꿔주는 작업입니다.

아마존 AWS에 로그인 후 EC2 대시보드로 이동합니다. '네트워크 및 보안 > 보안 그룹'으로 가서 저번에 등록했던 인바운드 규칙인 3000번 포트에 대한 TCP 규칙을 삭제합니다.

자료 화면이 필요하다면 이 포스트를 참고하십시오.

 

Node.js로 카카오톡 학식 채팅봇 만들기 (1)

원래 Python3 + Django2 조합으로 카카오톡 챗봇을 만들어 운영하고 있었는데요. (관련 튜토리얼) 이제 노드에 전념해보고자 기존에 운영하던 챗봇을 Node.js로 똑같이 구현해보기로 결심했습니다. 바�

dev-dain.tistory.com

이제 3000번 포트로 접근이 불가능합니다. 오직 80번 포트로만 HTTP 통신이 가능하게 되었습니다.

 

카카오에서도 바꿔줘야겠죠? 카카오 i 오픈빌더에서 스킬 탭으로 넘어갑니다.

URL이 현재 http://IP 주소:3000/message 로 되어 있을텐데요. 3000을 삭제하고 저장하시면 됩니다.

다시 배포하시는 것도 잊지 마세요!

 


 

지금까지 Node.js 로 카카오톡 학식 채팅봇 만들기 과정을 다뤄봤습니다.

채팅봇의 사용처는 무궁무진합니다. 굳이 학식이 아니더라도 단골 주제인 미세먼지, 날씨, 버스, 주식 등... 원하시는 주제를 잡아 만들면서 공부해보는 것도 재밌을 것 같습니다.

감사합니다. ^^

 

 

 

Reference

 

 

728x90
반응형
Comments