본문 바로가기
프로젝트/슈밥

(리메이크)카카오톡 학식 챗봇을 만들어보자 - 0. 개요

by WOOSERK 2023. 3. 23.

이번 주제는 카카오톡 챗봇을 만드는 것입니다. 예전에 해당 주제로 프로젝트를 하면서 다른 블로거분들에게 많은 도움을 받았습니다. 이번에 다시 만들면서 글로 정리하며 기억을 되새겨보려고 합니다.

 

혹시나 카카오톡 챗봇을 만들고 싶으신 분이 계시다면 도움이 되었으면 좋겠습니다. 개요인 이번 글은 제 사담이니 아래 네모만 보고 가뿐히 제끼셔도 괜찮습니다.

 

요약
사용할 언어: javascript(or typescript)
사용할 기술: cheerio, AWS(lambda, DynamoDB, API Gateway, EventBridge)

문제 정의

그 당시 저는 제가 맞닥뜨리던 하나의 불편함에서 이 프로젝트를 시작했습니다.

학식 메뉴를 보기가 불편하다.

 

얼마나 불편했으면 자세를 고쳐 앉지도 않고 챗봇을 만들었던 걸까요? 저의 이야기, 지금 시작합니다...

 

 

당시 저는 학교 주변에서 자취를 했기 때문에 매일 끼니를 학식에서 해결했습니다. 하지만 학식 메뉴라는 것이 늘 그렇듯이 맛이 있을 수도, 없을 수도 있습니다.

개인적으로 기피했던 메뉴

 

그래서 식사 시간 전에 학식 메뉴를 보고 갈지 말지 결정하는 것이 일상이었습니다. 학식 메뉴를 보려면 직접 홈페이지에서 보거나, 학교 커뮤니티 어플인 '에브리타임'에서 봐야 했습니다.

 

홈페이지에서 보려면 주소를 치는 것이 번거로우니 에브리타임을 사용했는데, 이것도 완전하지 않았습니다. 에브리타임으로 학식 메뉴를 보는 데는 2가지 문제점이 있었습니다.

  1. 식단을 보기까지의 페이지 전환이 많다.
  2. 기숙사 식단을 따로 제공하지 않아, 학생이 직접 캡처해서 업로드해야 한다.(그래서 주기적으로 업로드해주는 기식요정이 존재)

 

하나하나 살펴봅시다.

 

1. 학식을 보기까지의 페이지 전환이 많다.

과연 얼마나 많은지 그 당시 캡처본을 가져왔습니다.

 

총 3번의 페이지 전환이 필요합니다. 스마트폰 홈에서 어플을 클릭하는 것까지 합치면 무려 4번;;

 

뭐가 많지?

 

그 당시 저는 쌓여있는 과제에 미쳐 에브리타임에게 억까를 시전한 것 같습니다.  하지만 낙숫물이 바위를 뚫는다고, 터치 한 번이 스마트폰을 고장낼 수도 있는 법. 터치 수는 적을수록 좋습니다.

 

사실 이 1번 이유는 2번 이유와 합쳐져서 시너지를 냅니다.

 

2. 기숙사 식단을 따로 제공하지 않아, 학생이 직접 캡처해서 업로드해야 한다.

에브리타임에는 정보 게시판이라는 공간이 존재하는데, 여기에 기숙사 식단이 올라오곤 했습니다.

 

 

성발라의 '잘 자요'에 버금가는 클로징멘트와 함께 기숙사 식단을 올려주는 요정님을 볼 수 있습니다.

 

하지만 요정님의 개인적인 사정으로 업로드가 늦어진다면 다른 학생이 요정님을 대신하거나, 홈페이지에 들어가서 볼 수밖에 없습니다.

 

 

정리하면, 모든 식단을 보려면 다음 과정을 거쳐야 했습니다.

  1. 에브리타임을 킨다.
  2. 게시판 목록으로 간다.
  3. 오늘의 학식으로 가서 학생식당 식단을 확인한다.
  4. 다시 게시판 목록으로 간다.
  5. 정보 게시판으로 간다.
  6. 기식요정의 글을 눌러 기숙사 식단을 확인한다.

 

이렇게 보면 화면 전환이 꽤 많다는 것을 알 수 있습니다. 그리고 학생이 메뉴를 올려야 하는 기형적인 구조도 이상합니다. 문제를 정의했으니, 해결해야 합니다.


해결책

문제점 2의 해결책은 간단합니다. 기숙사 식단과 학생식당 식단을 함께 제공하면 됩니다.

 

문제점 1은? 딱 떠오르지 않습니다. 에브리타임보다 편리한 게 뭐가 있을까요?

 

전용 어플을 만들 수도 있겠지만 저는 카카오톡 챗봇으로 구현하려고 했습니다. 채팅 한 번으로 식단을 알 수 있으니까요.

그래서 시장 탐색을 위해 찾아본 결과 실제로 학식 메뉴를 알려주는 챗봇이 다른 학교에 많이 존재했고, 저희 학교도 이미 있었습니다. 그것도 무려 1500명이나 사용하는 채널로.

이미 존재하던 대기업(이 채널은 후에 부활한다..)

물론 기존 서비스가 있다고 또 만들면 안 되는 건 아니지만, 그래도 이왕이면 대체할 수 없는 무언가를 만들고 싶었습니다.

 

그래서 어플로 구현해야 할지 고민하고 있었는데, 마침 이때 카카오톡이 챗봇 API를 개편하면서 기존 서비스와 호환이 되지 않아 대부분의 학식 챗봇이 동작하지 않았고 저희 학교 챗봇도 그중 하나였습니다.

 

그래서 저는 챗봇으로 확정을 지었습니다. 땅땅땅.


도구 선정

문제와 해결을 마쳤으니 이제 도구를 정해봅시다.

 

이번에는 자바스크립트로 만들 거지만, 저는 기존에 학식 알림 챗봇을 파이썬으로 만들었습니다. 그 당시 저의 주언어는 자바였는데 파이썬으로 구현했던 이유는 2가지였습니다.

 

  1. AWS lambda의 실행 속도
  2. 스크래핑의 용이함

 

1. AWS lambda의 실행 속도

실행 속도는 구현에 앞서 아래 자료를 참고했었습니다.(2021년)

출처 : https://filia-aleks.medium.com/aws-lambda-battle-2021-performance-comparison-for-all-languages-c1b441005fd1

 

AWS Lambda battle 2021: performance comparison for all languages (cold and warm start)

Let’s compare the performance of all supported runtimes + 2 custom runtimes (Rust and GraalVM).

filia-aleks.medium.com

 

위 자료는 언어에 따른 AWS lambda의 cold start 속도를 비교한 것인데, cold start는 컨테이너를 띄워 lambda 함수를 실행하는데 소요되는 시간을 의미합니다.

 

추가로 warm start는 한 번 cold start를 하면 일정 시간(약 5분)동안 컨테이너가 띄워져 있어 이때는 lambda 함수만 실행하면 되는데, 이에 소요되는 시간을 의미합니다.

 

따라서 익숙했던 자바는 아예 배제하고, 러닝커브까지 고려했을 때 파이썬으로 구현하는 것이 가장 적합하다고 판단했습니다.

 

2. 스크래핑의 용이함

또한 파이썬은 웹 스크래핑에 많이 씁니다. 

 

파이썬의 스크래핑 도구는 굉장히 많고, 저는 beautifulsoup, selenium, scrapy 3가지 중에 고민했습니다.

 

결국 저는 scrapy를 선택했었는데 가장 큰 이유는 학교 도서관에 관련 도서가 있기 때문이었습니다.

 

scrapy가 초보자들에게 기피되는 이유가 참고 자료가 적어 러닝커브가 높기 때문인데, 책을 한 번 훑어봤을 때 꽤 괜찮은 결과물이 나올 것 같아서 선택했습니다. 그리고 확장하기 쉽고 성능이 좋은 것도 있습니다.

 

혹시나 책이 궁금하신 분은 아래 링크를 참고해 주세요. 2018년 책이라 지금 보기엔 적절하지 않을 수도 있습니다.

https://product.kyobobook.co.kr/detail/S000001766325

 

웹 크롤링과 스크레이핑 | 카토 코타 - 교보문고

웹 크롤링과 스크레이핑 | 《파이썬을 이용한 웹 크롤링과 스크레이핑》은 파이썬을 이용한 데이터 수집과 분석을 위해 입문에서 실전까지 상세하게 설명한 책입니다. 기본적인 크롤링과 API를

product.kyobobook.co.kr

 

+) 자바스크립트는

이미 만들었는데 왜 자바스크립트로 다시 구현하느냐고 반문하실 수도 있습니다.

 

저의 경우 잘 모르는 파이썬으로 구현했더니 유지보수할 때마다 코드를 이해하는데 시간이 많이 들었습니다. 버그 수정하러 학교 도서관에 가면 1~2시간은 코드 해석에 시간을 썼습니다. scrapy 구조가 복잡한 것도 한몫했습니다.

 

주석을 아무리 많이 달아도 학교 사이트의 양식이 계속 바뀌어서 로직을 변경하는데 한세월이었습니다.

 

그래서 자바스크립트 공부도 할 겸 다시 만들어보려고 합니다. 그렇다면 자바스크립트에서 어떤 도구로 스크래핑을 구현해야 할지 알아봅시다.

 

검색해 보니 puppeteer, playwright, cheerio, axios, selenium 정도가 있는 것 같습니다.

 

앞의 두 녀석은 동적인 데이터를 스크래핑할 수 있지만 저의 경우 필요 없고, 헤드리스 브라우저를 구동하는 방식이라 자원이 꽤 들기 때문에 제외하겠습니다.

 

동적인 데이터는 클릭, 이동, 로그인 등의 추가적인 자바스크립트 실행 이후에 나오는 데이터를 의미합니다.

 

selenium은 느리고 원래 목적은 테스트용이라고 하니, 많이들 사용하는 axios + cheerio 방식으로 구현하겠습니다. axios로 페이지 데이터를 가져와서 cheerio로 DOM을 조작하는 방식으로 진행하려고 합니다.

 

만약 학교 홈페이지가 동적으로 구현되어 있다면 puppeteer을 쓰시는 것을 추천드립니다.


긴 개요가 끝이 났습니다. 이제 구현만 남았습니다.

 

최근 책을 몇 권 구매했는데, 안 읽었더니 점점 쌓이고 있습니다.

 

책 좀 읽고 오겠습니다. 다음 글은 늦어질 것 같습니다.