VM 서버 셋팅 때 있었던 그림인데 3번을 보게 되면 크롤링이라는 것이 있다. 크롤링에 대해서 살펴보자.
크롤링(crawling) 혹은 스크래이핑(scraping)이라고도 하며, 웹 페이지를 그대로 가져와서 원하는 데이터를 추출해내는 행위를 말한다. 크롤링하는 소프트웨어는 크롤러(crawler)라고 하며, 웹 크롤러(web crawler)는 world wide web(www)을 탐색하는 컴퓨터 프로그램이다.
필자의 경우 PHP로 구현을 했기 때문에 PHP로 작성된 스누피 클래스(Snoopy class)를 이용하였다.
: PHP로 작성된 외부 소켓 클래스로 웹 사이트 내용을 쉽게 크롤링해 올 수 있도록 해주는 클래스
https://sourceforge.net/projects/snoopy/files/latest/download 이 링크를 따라가면 zip파일이 다운받아진다. zip파일의 압축을 풀어보면
이런식으로 나오게 된다. 이를 그대로 서버에 넣어주면 되고 경로는 어디로 하던 상관없다. 필자의 경우 keyboard.php와 message.php가 있는 경로에 다 넣었다.

저번 포스팅에서 keyboard.php를 살펴봤으니 이번엔 message.php를 살펴보자.
이게 맨 처음 만든 message.php이다. 밑에 부분은 각 명령어에 대한 응답처리이고, 3번째 줄을 보게 되면 json방식으로 들어온 요청값이 json_decode 함수에 의해 배열 또는 객체로 변환된 후 $data 변수에 저장된다. 4번째 줄을 보면, $data변수에 저장된 배열 또는 객체에서 content 항목인 부분만 다시 $content 변수에 저장한다. 쉽게 말해, $content 변수에는 사용자가 입력한 명령어가 들어가게 된다고 생각하면 된다. 이 message.php에 크롤링 기능이랑 각 명령어 응답처리들을 추가해줄 것이다.
먼저 크롤링 기능을 추가해주기 위해 message.php에서 스누피 클래스를 이용해보자. 2,5,6번째 줄만 추가해주고 나머지는 그대로 두면 된다.
현재 snoopy클래스 파일들을 message.php와 같은 경로에 넣었기 때문에 저렇게 해준 것이지, 다른 경로에 넣어도 전혀 상관이 없다. 6번째 줄에는 크롤링할 URL을 넣어주는 부분이 있다. 지금 써져 있는 URL은 학기 중 버스 시간표가 있는 URL이다.
처음에 생각한 것은 특정 시간을 입력하면 해당 시간표만 뽑아오도록 하는 것이었다. 그래서 정규식을 통해 뽑아야겠다는 생각을 했는데, html 중에 숫자가 들어가 있는 경우 이것도 뽑아낼 거 같아 좀 더 확실하게 구별해주기 위해서 ‘:’ 까지 같이 뽑아내도록 했다. 하지만 문제가 생겼다.
처음에 버스 시간 페이지를 보고 학기 중 시간표만 나와 있어 학기 중 버스 시간들만 작성돼있을거라고 생각했는데 이런 식으로 방학 시간표들이 주석처리되어 같이 들어가 있었다. 아무래도 방학 때 시간표를 다시 작성하기 귀찮아 저런 식으로 주석처리 해놓고 방학이 되면 학기 시간표를 주석처리하고 방학 시간표의 주석처리를 없애는 식으로 운영을 하는 것 같았다. 이 때문에 크롤링할 때 방학 버스 시간도 같이 불러오게 되어 원하는 응답이 나오지 않게 되는 상황이 벌어졌다.
그래서 학기 중 시간표만 불러오도록 하기 위해 주석처리를 제외한 나머지 값들만 불러오도록 해봤지만 실패해서 어쩔 수 없이 따로 웹파일 하나를 만든 후에 주석처리를 제외한 나머지 부분들만 싹 긁어서 복사했다(실력이 부족해서…ㅠㅠ) . 그게 바로 밑에 보이는 bus.php이다. bus.php에는 학기 중 운행되는 현재 버스 시간표만이 담겨 있다.
아까 위의 그림과 비교했을 때 URL부분이 달라졌음을 확인할 수 있는데 결국 학기 중 버스시간표만 있는 bus.php를 크롤링할 것이라는 말이다. 다음 포스팅에서는 이어서 소스코드에 대한 설명을 하겠다.
,
챗봇이란 채팅과 로봇의 합성어로 인공지능(AI)을 기반으로 사람과 대화를 나누는 프로그램으로 카카오톡 챗봇의 경우, 카카오톡 자동응답 API를 통하여 사용자가 입력한 input값에 대해 json방식으로 답변을 해준다.
카카오톡 플러스 친구에서 지원해주는 API들이 있는데, 입력값을 넣었을 때 응답만 해주면 되는 챗봇이라서 keyboard와 message기능만 구현해주면 된다.

이번에 만들어 본 챗봇이고, 원하는 시간대에 버스시간을 입력하면 해당 버스시간표를 조회해준다.
먼저 앱을 등록해야 하는데, 그러기 위해선 플러스 친구에 가입을 해야 한다. https://center-pf.kakao.com 여기로 들어가서 ‘플러스친구 만들기’를 눌러 카카오톡 아이디로 로그인을 하면 이런 화면이 나온다.
여기서 ‘새 플러스친구 만들기’를 클릭한다.
필요한 부분들을 채워넣고 확인을 누르면
왼쪽을 보면 ‘스마트채팅’ 버튼이 있다. 이를 클릭해보면
연필 아이콘 모양이 있는데, 이를 클릭하면
여기를 보면, 다른 거는 그냥 입력해주면 되는데 앱URL 부분이 문제이다. 오른쪽을 보게 되면 ‘API테스트’가 있는데 이를 통과해야만 한다. 앱 URL주소는 해당서버에 keyboard.php가 존재하는 경로이면 된다. 필자의 경우, /var/www/html/busbot/keyboard.php였기에 앱 URL에 ‘http://서버주소/busbot’를 입력해줬다.
다음은 keyboard.php의 소스이다.
하지만 해보면, 이런 오류가 발생한다.
이 오류는 서버에 설정을 해주지 않아서이다. 먼저 아파치 기본설정 파일(/etc/apache2/apache2.conf)에 들어가서 화면처럼 설정을 해준다.
그리고 mime.conf에서도 php옵션을 설정해준다.
설정을 다 해줬으면 아파치를 restart한다. -> /etc/init.d/apache2 restart
그림대로 다 해주게 되면 이런 화면이 나온다.
맨 밑으로 가면 ‘API 저장하기’가 있는데 이를 클릭한다. 이러면 API설정은 끝났다.
‘시작하기’ 버튼을 눌러주면 API가 실행된다.
이러면 잘 실행이 되는 것이다.

여기서 친구추가를 한 후에 1:1채팅을 해보자.

채팅방을 보면 ‘시작’ 버튼이 있다. 아직은 message부분이 제대로 구현돼있지 않아서 이 시작버튼을 눌러보면 완성본처럼 다양한 응답값이 나오지 않는다. 다음 포스팅에서는 message부분을 만들어보자.
챗봇의 구조를 보게 되면 서버가 필요함을 알 수 있다. 필자는 따로 서버를 가지고 있지 않아서 VM을 서버로 두었다. 하지만, VM은 설정을 해줘야만 외부에서 접속이 되기 때문에 따로 설정을 해줘야 한다. NAT방식이나 Bridge방식 둘 다 가능하지만, 필자는 Bridge 방식을 이용했다.
bridge 방식을 이용하기 위해 VM설정을 해주자. Edit -> Virtual Network Editor로 들어가보면

여기서 Change setting을 누른다.
Bridge 부분을 누르고, OK버튼을 누른다. 이번엔 VM -> Settings를 들어간다.

왼쪽의 Network Adapter에서 Bridge를 선택해준다. VM의 IP를 확인해보면

이러면 Bridge 설정은 끝났다.
그럼 이제 VM에도 IP가 할당되어 서버처럼 쓸 수가 있는데, 사용자가 메시지를 보냈을 때 VM한테만 가도록 하기 위하여 포트포워딩을 해줘야 한다.
필자는 iptime 공유기를 사용하기 때문에 iptime일때를 기준으로 설명하겠다.
URL창에 192.168.0.1을 입력하면

이런 화면이 나오는데, 여기서 로그인 하고 관리도구를 눌러준다.

여기서 다양한 정보들을 볼 수 있다. 먼저 고급설정 -> 네트워크 관리 -> 내부 네트워크 정보로 들어가보면

위 그림은 VM을 Bridge 방식으로 설정하기 전이다.
이제 포트포워딩을 해주자. 왼쪽에서 고급 설정 -> NAT/라우터 관리 -> 포트포워드 설정으로 들어가보면

‘새 규칙 추가’를 누른 후 아래쪽에 작성을 해줘야 하는데 내부 IP주소는 VM으로 포트포워딩을 해줄 것이기 때문에 VM의 주소를 입력해주면 되고 필자는 외부에서 터미널로 접속이 가능하게끔 외부 포트는 2222, 내부 포트는 22로 해주었다. 이렇게 되면 터미널에 접속할 때 공유기에서 2222번 포트로 들어가면 VM의 22번 포트로 접속이 되는 것이다.

외부 포트는 내가 지정해주고 싶은 포트번호를 입력해주면 되는데, 49152~65535번 포트는 동적 포트이기 때문에 서버 소켓 포트로 사용할 수 없고, 0~1023번은 well-known 포트라고 해서 UNIX/LINUX에서 root 권한으로면 포트를 열 수가 있어 보통은 1024~49151번 범위 내에서 외부포트 번호를 지정해준다. 다 지정해줬으면 확인 버튼을 누른다. 이러면 포트포워딩 설정이 끝난다.
다시 고급설정 -> 네트워크 관리 -> 내부 네트워크 정보로 들어가보면 pooh-virtual-machine이라는 이름으로 IP가 할당됐음을 알 수 있다. 아까 본 VM의 IP와 일치한다.

이제 외부에서 필자의 공유기로 접속을 하게 되면 포트포워딩에 의해 VM으로 접속이 된다. 즉, VM 서버 셋팅이 완료된 것이다.
member라는 테이블에 정보들이 나와 있고 각 사람들 중에 최대의 나이와 최소의 나이를 조회해보자.
mysql> select max(member_age), min(member_age) from member;
뒤에 조건을 붙여서 할 수도 있다. 사람들 중에 이메일이 있는 사람 중에 최대의 나이와 최소의 나이를 조회해보자.
mysql> select max(member_age), min(member_age) from member where member_email is not null;
똑같이 member 테이블이 있다. 이 그림만 보고도 대부분의 컬럼을 카운트했을 때 5개일 것이라고 생각할 수 있다. member_age를 카운트해보자.
mysql> select count(member_age) from member;
하지만 주의해야 될 것이 있다. COUNT함수는 NULL값을 세지 않는다.
mysql> select count(member_email) from member;
NULL을 2개 포함하면 5개라고 생각할 수 있지만 COUNT함수를 사용하면 NULL값 2개를 세지 않았음을 확인할 수 있다. 그리고 member_phone을 보게 되면 010-1111-2222이 2개 있는데, 이를 중복되지 않게 세려면 distinct를 써주면 된다.
mysql> select count(distinct member_phone) from member;
그러면 전체를 반환하는 *를 사용했을때는 어떻게 되는지 살펴보자.
mysql> select count(*) from member;
member_email에 NULL값이 있어 어떻게 나오는지 궁금했는데 다른 컬럼들에는 값들이 다 존재하므로 *를 사용했을 때는 모두 카운트한 값인 5가 반환이 됨을 확인할 수 있었다.
이번엔 각 사람들의 나이의 합을 구해보자
mysql> select sum(member_age) from member;
이거 역시 조건을 붙여서 사용할 수도 있다. 이번엔 이메일이 없는 사람들의 나이 합을 구해보자
mysql> select sum(member_age) from member where member_email is null;
이번엔 각 사람들의 나이의 평균을 구해보자. 평균을 구하는 방법은 2가지가 있다.
mysql> select avg(member_age), sum(member_age)/count(member_age) from member;
똑같은 값이 나옴을 확인할 수 있다. AVG함수 역시 뒤에 조건을 붙여서 사용이 가능하다.
member라는 테이블에 정보들이 나와 있고 이 중에서 member_email이 NULL값인 사람들의 정보들을 조회하려고 한다. 이 때 이렇게 쿼리를 입력하면, 내가 원하는 결과가 출력되지 않는다.
mysql> select * from member where member_email = NULL;
이렇게 값이 NULL인 경우를 조회하려면 ‘=’이 아닌 is를 써야 한다.
mysql> select * from member where member_email is NULL;
NOT NULL의 경우도 마찬가지이다. 이번엔 member_email이 NULL값이 아닌 사람들을 조회해보자.
mysql> select * from member where member_email != NULL;
역시 나오지 않는다. 이 경우도 is를 써주면 된다.
mysql> select * from member where member_email is NOT NULL;
정리하면
mysql> select [컬럼] from [테이블] where [컬럼] is NULL;
mysql> select [컬럼] from [테이블] where [컬럼] is NOT NULL;
–> NULL과 NOT NULL이 꼭 대문자일 필요 없다. 소문자여도 똑같은 값이 나온다.
VMware의 Bridge, NAT, Host-Only 방식에 대해 알아보자.
Bridge 방식에서는 VMware 에서 Virtual Adapter로 vmnet0 을 사용하고, 공유기가 VM도 별개의 PC로 보기 때문에 개별적으로 IP를 할당 한다. 즉 VM은 PC가 물리적 네트워크에서 동작하는 것처럼 동작한다. 그래서, PC 1, PC 2, PC 3 모두 VM에 접근할 수가 있다(통신이 가능하다).
NAT 방식에서는 VMware 에서 Virtual Adapter로 vmnet8 을 사용하고, 공유기가 각 PC에게 IP를준다. 그리고 해당 PC(PC 1)가 VM에게 IP를 주면서 VMware 가 자체적으로 내부 네트워크대역 할당 및 자체 DHCP 서버를 띄워 통신한다.
따라서, PC 1과 VM끼리통신이 가능하고 PC 1이 인터넷이 되면 자동으로 VM도인터넷이 가능하다. 하지만, PC 2와 PC 3는 VM에게 접근할 수 없다.만약 접근하고자 한다면, NAT 설정을 통해 포트 포워딩 함으로써 특정 PC에서 VM들에접근할 수 있다.
Host-Only 방식에서는 VMware 안에서 구성된 VM들끼리만 통신한다. 즉 VM은 해당PC (호스트 컴퓨터(PC1))를 넘어서 통신할 수 없다. 따라서, PC 1이 인터넷에 연결되어 있다고 해도 VMware는 인터넷이 되지 않는다.
,