기술블로그 구독서비스 개발 후기 - 3부
작년 7월 12일부터 시작한 필자의 첫 토이프로젝트인 기술블로그 구독서비스. 오픈할 때까지만 해도 “AWS 프리티어를 사용하고 있는 1년 안에 구독자가 설마 1,000명이 넘겠어?” 라고 생각을 했었는데 오픈을 하고 220일째 되는 바로 어제 어느덧 벌써 구독자가 1,000명을 달성하게 되었다. 그 기념으로 그동안 미뤄두었던 기술블로그 구독서비스 개발 후기
시리즈의 3부를 쓰고자 한다.
혹시 전에 내용을 보고자 하면 아래 링크에서 확인할 수 있다.
그간 어떤 식으로 서비스를 운영했는가?
(한마디로 정리할 순 없는 지난 220일이었지만…) 딱 한마디로 정리하자면 엄청나게 많은 것을 배우고 경험할 수 있었으나 그만큼 힘들었던 시간들
이라고 말할 수 있을 것 같다. 2부에서 이야기한 문제 발생에 따른 Trouble Shooting
들도 있었지만 운영을 해오다 보니 사전에 생각하지도 못한 부분에서 문제가 생기는 정말 다양한 경험을 할 수 있었기 때문이다.
- 블로그 포스팅을 수집하는 과정에서의 문제 일부 블로그 RSS url에 접근을 할 때 요청에 대한 응답이 무한대로 멈춰버리는 현상이 간헐적으로 있었다. 이는 별도의 타임아웃을 설정하지 않았기 때문이다. 그래서 어느 정도의 타임아웃을 두고 시간 내에 응답이 없을 경우 다음 포스팅으로 넘어가도록 하였다. (타임아웃은 아주 기본적인 부분인데…)
requests.get(rss_url, timeout=10.0)
- 메일 발송하는 과정에서의 문제 가끔 메일이 오지 않는다고 친절하게 필자 개인 메일로 연락이 오는 경우가 있었다. 그때마다 서버의 상태를 보면 서버에 직접 접속조차 안 될 정도로 메모리 사용량이 너무 많아서 그때마다 AWS 웹 콘솔에서 강제로 서버를 재부팅을 하곤 했었다. 예전에도 이야기한 것처럼 AWS 프리티어를 사용하고 있다 보니 서버의 메모리가 1기가밖에 되지 않아서 … 제한된 시스템에서 서비스 운영을 할 수밖에 없는 상황이었다. 그래서 수집/발송 상태를 로깅으로 쉽게 볼 수 있고 스케줄링을 하기 위해 띄워둔 Jenkins(tomcat)를 중단하고 crontab으로 스케줄링을 하도록 하였고, 로깅은 별도의 파일로 로깅하도록 변경하였다.
/usr/bin/python3.6 /home/~~~/email_send.py > /home/~~~/logs/job/email_send_`date +\%Y\%m\%d\%H\%M\%S`.log 2>&1
또한 기존에는 빠르게 발송하기 위해 냅다 스레드로 돌렸는데 구독자 수가 많아지다 보니 RuntimeError: can't start new thread
라고 스레드를 만들 수 없다는 에러가 발생하기도 했다. 그래서 Pool을 사용하는 방식의 multiprocessing 을 도입하여 스레드로 발송할 때보다는 엄청나게 빠른 속도는 아닐지라도 효율적인 메모리 사용으로 2분 안에 1,000명에게 안정된 메일을 보낼 수 있게 되었다. (여담이지만 메일이 안 온다고 알려주셨던 분들께 이 자리를 빌려 감사의 인사를 전하고 싶다.)
from multiprocessing import Pool
...
pool = Pool(20)
pool.map(sendMail, email_list)
Heroku 나 Netlify 같이 서버를 직접 들어가지 않고 앱 형태로 배포하는 식으로 할 수도 있다. 하지만 초기에 이 토이프로젝트를 시작할 때 실 서비스와 최대한 동일한 시스템으로 운영해보고 싶었기 때문에 라즈베리파이에 설치하는 것까지 알아보다 결국 AWS를 사용하기로 하게 되었다. 그렇다면 AWS 프리티어를 사용하지 않고 별도의 서버를 구매하면 안 될까? 하는 생각도 해봤지만 최소한의 인프라로 최대한의 성능을 내보고 싶은 욕심(?) 때문에 1년간은 프리티어로 운영하고 그다음엔 (혹은 소프트웨어적으로 한계까지 도달한다면) 서버를 구매해서 운영하게 될 것 같다. (적어도 이후에도 이 서비스를 유지한다는 가정하에…)
아침 10시가 되면 자동으로 메일이 잘 발송되었는지, 혹 어제 수집된 것이 아니라 예전에 수집된 내용이 중복 발송된 건 아닌지, 발송은 구독한 사람 전부에게 잘 보내졌는지… 거의 매일같이 Daily-DevBlog 서비스를 살피며 지낸 것 같다. (하루라도 문제가 생기면 밤을 새워서라도 원인을 파악하고 다음 발송에는 정상적으로 발송되도록 수정하기도 했다.)
앞으로의 계획과 방향성
여력이 되는 데까지 이 서비스를 운영할 계획이다. AWS 프리티어 기간이 끝나도 라즈베리파이나 안 쓰는 노트북을 활용해서 서버를 구성하던지 (한 달에 얼마를 지불할지는 모르겠지만) AWS에서 서버를 발급받아서라도 운영하고 싶다. 그 이유는 이 토이프로젝트를 진행하면서 얻게 된 인사이트도 상당히 많았고, python과 apache 등 기존에 알고 있던 부분 이외로 알게 되는 것 또한 많았기 때문이다. 그리고 가장 중요한 공유
, 사실 이 서비스를 만들면서 필자 또한 많은 좋은 글들을 볼수있었고 그에 큰 도움도 많이 받을 수 있었다.
만들고 싶은 기능도 많다. 포스팅의 내용을 분석하여 자동으로 기술과 관련되지 않는 글을 제외하는 기능도 만들고 싶고, 자동으로 주요 키워드 (태그)를 만들어 이후에도 태그 기준으로 검색을 통해 보고싶은 글을 뉴스처럼 볼수 있는 기능도 만들고 싶고… 운영을 하다 보니 만들고 싶은 기능은 많지만 기술적인 접근이 어려운 상황이다.
하지만 가장 중요한 건 새로운 기능 추가보다 안정적으로 매일 아침 10시마다 바로 어제의 글들을 수집하여 구독자들에게 발송하는 것이 가장 중요한 게 아닐까 싶다.
구독자 1,000명 기념 추가 기능 공개!
예전부터 1,000명이 되는 시점에 뭔가 이벤트 성으로 새로운 기능을 공개하고 싶어서 준비를 해보았다.
아카이브 위에서 이야기했듯이
기술과 관련되지 않는 글들에 대한 필터링
을 기술적으로 하고 싶었으나 예로 들어 “00역 맛집리스트 자동으로 가져오기” 나 “코딩하면서 먹기에 좋은 음식” 이라는 제목이 있을 경우 과연 어떤 글이 기술에 관련된 글이고 어떤 글이 기술과는 거리가 있는 글인지 기술적으로 분석할 방법이 아직까지는 떠오르지 않는다. (물론 머신러닝이나 다른 방법이 있겠지만…) 그래서 기존에 수집한 글들을 한 곳에서 보여주면서 기술과는 거리가 있어 보이는 글들에 대해서 제외하고 볼 수 있도록 아카이빙 페이지를 만들었다. 그리고 날짜를 넘겨가며 조회할 수 있고 정렬 순서는 랜덤으로 만들었다.크롬 익스텐션 {% image fancybox center chrome_ddb.jpg “기술블로그” 라고 검색해도 나온다. %} 위에서 만들었던 아카이빙 페이지를 단순하게 익스텐션 클릭 한 번으로 접속이 되도록 만들어보았다. 점심시간 또는 여유시간에 공유된 기술 블로그 포스팅을 쉬운 접근성을 통해 읽어보자는 조금이라도 챙겨보자는 느낌으로 만들게 되었고, 크롬 알림 기능을 활용하여 PC 크롬이 켜져 있는 상황에서 아침 10시가 되면 메일이 발송되는 것처럼 아래 화면과 같이 알람을 주도록 하였다. {% image fancybox center chrome_ddb.gif 아침 10시엔 우리 모두 Daily-DevBlog를~ %}
주간 인기글 구독자들이 어떤 글에 더 관심이 갖는지 궁금하였고 많이 본 글에 대해서는 한 번 더 정리하여 메일로 발송해주는 것이 좋을 것 같다는 생각이 들었다. 그래서 메일로 발송된 글에 대해 클릭수를 기준으로 매주 월요일마다 “주간 인기글"을 발행하는 기능을 추가하였다.
단체 블로그 추가 수집 지금은 어썸 데브블로그에서 제공해주는 개인 블로거들의 피드를 수집하고 있는데 단체 블로그들 또한 추가로 수집하여 메일의 상단에 배치한다. (단체 블로그는 아무래도 검증이 된 글일 거라 생각이 든다.)
마치며
혹시 이 서비스에 대한 아이디어가 있는 분들은 아래 댓글이나 개인 메일로 알려주시면 최대한 반영해보고자 한다. 또한 나중에는 github에 공개하여 오픈소스화한다면 필자보다 더 뛰어난 python 개발자들이 보다 좋은 코드를 만들어주어 점점 해당 서비스가 좋아지지 않을까 하는 기대를 해보며 기술블로그 구독서비스 개발후기
를 마친다.
Buy me a coffee