육군훈련소 실시간 검색어 뉴스 전송 봇 개발후기

MinuKang
7 min readJul 22, 2020

--

육군훈련소에 가 있는 불쌍한 친구를 위해 매일 뉴스를 보내주자

저는 병역의무를 산업기능요원으로 마쳤습니다. 산업기능요원은 대체 복무의 한 종류로, 34개월간 지정된 산업체에 근무하는 것으로 병역 의무를 집니다. 하지만 이들도 다른 현역, 보충역과 마찬가지로 군사교육소집을 행해야합니다. 흔히 ‘훈련소’라고 불리는 곳으로 가야하는 것이죠.

악! 내 눈!

다행인건 보충역과 마찬가지로 4주간 훈련을 받기 때문에 현역에 비하면 덜 힘들죠. 하지만 4주 동안 핸드폰도 사용 못하고, 외부와 철저히 단절되기 때문에 오로지 ‘편지’로만 바깥 세상의 소식을 들을 수 있습니다.

저는 이 과정을 겪었기 때문에, 이후에 훈련소 들어가는 친구들이 ‘그나마’ 덜 심심하도록 실시간 검색어 + 해당 뉴스를 보내주곤 했습니다. 물론 그를 통해서 나름대로 이득을 취하기도 했죠(기프티콘이라던가, 비싼 밥이라던가..)

아래의 모든 과정은 Node.js + typescript로 진행됩니다.

실시간 검색어 + 뉴스 가져오기

이벤트/할인을 끌 수 있다!

네이버 실시간 검색어는 대한민국에서 현시각 핫한 키워드들을 알 수 있습니다. 예전에는 토쓰의 행운퀴즈 이벤트 때문에 실시간 검색어의 반 이상이 해당 키워드로만 나오던 적이 있었지만(그 시기에 뉴스 보냈던 친구는 왜 뉴스의 반 이상이 쓸모없냐고 했죠) 지금은 실시간 검색어에 관심사를 설정 할 수 있도록 네이버 홈 개편과 함께 이루어졌습니다.

이를 크롤링하여 뉴스를 가져와봅시다. 네이버는 각 언론사들의 뉴스를 가져와서 자사 뉴스 서비스에 이를 등록하기 때문에 크롤링 난이도는 쉬운 편입니다.

‘네이버뉴스’ 링크를 통해 네이버 뉴스에 등록된 해당 언론사의 뉴스를 볼 수 있다.

다만, 연예 관련된 뉴스는 네이버TV연예, 그 외에는 네이버 뉴스로 가기 때문에 이를 분기하는 작업이 필요합니다. 또한 네이버 뉴스는 인코딩을 EUC-KR, 네이버 연예는 UTF-8을 사용하기 때문에 이를 또 고려하여 파싱해야 합니다.

각 도메인에 맞는 파서를 제작하여 일관된 결과를 반환한다

위와 같이 각 도메인에 맞는 파서를 만들어줘서, fetch API로 만들어진 Response의 url을 검사하여 알맞는 내용을 가져오게끔 할 수 있습니다.

Object.entires로 객체를 순환할 수 있다. 매우 애용하는 방식

본인인증을 PASS하기

데이터를 준비했으니 이제 적절하게 이를 보내주기만 하면 끝입니다. 하지만 육군 훈련소는 편지를 작성하기 위해서 ‘본인인증’ 과정을 거쳐야합니다.

귀찮은 입력이 굉장히 많은 PASS 본인인증

때문에 이 전달 봇은 완전히 자동화가 될 수는 없습니다. 한번 세션을 접속하기 위해서는 이 본인인증 과정을 거쳐야 하니까요.

그나마 다행인건 간편인증과 문자인증과 다르게 QR인증, 혹은 문자인증은 자동가입방지 문자(Captcha) 이미지가 없어서 숫자코드만 제대로 핸드폰 앱으로만 입력해주면 나름 간단하게 구현이 될 수 있습니다.

따라서 본인인증을 위해 편지 작성은 Headless Browser로 진행이 됩니다.

머리가 없는 브라우저

Headless Browser란, 말 그대로 머리(…)가 없는 브라우저로, GUI 없이Command line이나 네트워크 조작만으로 브라우저 환경의 테스트를 위해 만들어진 도구 입니다.

유명한 Node.js의 Headless Browser 도구로 Puppeteer, Cypress 등이 있지만, 이번에 Puppeteer 팀에서 단체로 마이크로소프트로 이직해서 만들어낸 화제의 Playwright을 써보았습니다.

통신사 선택 -> 동의동의동의동의 -> QR코드메뉴 진입 -> 숫자코드 얻기

위와 같이 유저가 인증과정을 진행하는 것 처럼 코드를 작성하고, 숫자코드를 가져와서 전달합니다. 우리는 이 숫자코드를 PASS앱에 들어가서 입력하면 되죠.

크롤링해온 숫자코드를 앱에다가 입력하자!

인증 과정이 마쳐지면, 글 쓰기 페이지로 가서 해당 폼을 사용할 수 있게됩니다.

그리고 저는 작성할 때 마다 “글쓰기 완료 -> 리스트 페이지로 리다이렉트 -> 글쓰기 페이지 이동” 이 과정을 줄이기 위해 꼼수를 썼습니다.

해당 페이지에서 여러번 폼을 사용할 수 있도록 꼼수를 사용한 모습이다.

바로 글이 작성되기 전 폼에다가 랜덤한 이름의 타겟을 지정하고, 해당 이름과 같은 아이프레임을 심어놔서 해당 아이프레임에다가 폼을 전송하도록 하는 것이죠. 이렇게 되면 위의 리다이렉트 과정이 사라집니다.

이제 뉴스를 적절하게 제목과 내용을 나누어서 보내면 됩니다. 참고로 육군 훈련소의 내용의 글자 제한은 최소 10자, 최대 800자입니다.

텔레그램에 연동하자

언제든지 시간과 장소에 제약하지 않고 편지를 보내주기 위해 텔레그램 봇을 설치하여 해당 봇에다가 명령을 내려주면, 인증 숫자코드를 받아오고, 숫자코드가 앱에서 입력이 완료되었다는 것을 알려주면, 현재 시각 실시간 검색어 + 뉴스를 보낼 수 있도록 만들어봅시다.

완성된 텔레그램 인터페이스

메세지를 보내는 것은 쉬웠지만, 여기서 관건은 숫자코드를 입력할 때까지 대기하고, OK 버튼을 누르면 인증 완료하고 편지를 보낼 수 있도록 해야합니다. 그래서 다음과 같은 askModel 을 정의하여 대기할 수 있도록 합니다.

질문(question)을 던진 후 대기하는 askModel

그 후 텔레그램 봇에다가 일회성 callback_query 이벤트를 지정하여, OK를 누를 때까지 대기 할 수 있도록 합니다.

reply_markup.inline_keyword 로 메세지에다가 버튼과 액션 데이터를 넣을 수 있다.

외에도 Cancel 버튼을 추가하여 리젝을 날려서 테스크를 멈출 수 있도록 합니다. 또한 Promise.race를 활용하여 MAX_WAITING_TIME 동안 무응답일 경우에도 리젝이 되도록 합니다.

결과

첫날만에 내 테스트로 인하여 200개의 편지를 받은 내 친구

친구는 저 덕분에 생활관의 인기스타가 되어 있을 겁니다.

위의 모든 코드는 https://github.com/minuukang/army-letter-bot 에서 볼 수 있습니다.

--

--