본문 바로가기

Dot ./개인 프로젝트

Spring, Python으로 만든 자동화 콘텐츠 구독 서비스 (루비 LOOBIE)

    1. 프로젝트 동기 

    요즘 한창 구독 경제가 대세로, 빅테크부터 시작해서 스타트업까지 자신만의 콘텐츠의 경쟁력을 높여 많은 사용자를 구독시키려고 하고 있습니다. 일명 플랫폼 시대에 흔히 쓰이는 슬로건 "일단 모아라" 전략입니다. 그렇게 구독자가 어느정도 모이면 유료화 정책을 펼치든 광고로 수익을 올리든 무엇이든 해볼 수 있는 힘이 생기게 되고 결국 그 기업의 무형자산이 됩니다. 저는 개인적으로 스타트업 위클리, ark invest, 코딩월드뉴스, The Download, TLDR, Sidebar, business insider 등 많은 구독 서비스를 애용하고 있습니다. 구독 서비스 애용자로서 데이터를 분석하여 제공하는 CryptoQuant 서비스처럼 내가 보고싶은 다양한 경제, 테크, 관심있는 주식, 종목 시황, 특정 인물의 트위터 등 원하는 정보들을 자동으로 모아 매일 새로운 뉴스를 제공해주는 서비스가 있으면 좋겠다는 생각이 들었습니다. 그래서 MVP(최소 기능 제품)버전으로 일단 주요 기능들만 한 번 구현해보았습니다.

     

    2. 프로젝트 시스템 구상 및 설계

    LOOBIE (부 프로젝트명 : Dot news)는 새로운 소식을 매일 전해주는 자동화된 콘텐츠 구독 서비스입니다. 콘텐츠 생성 방식은 직접 생성하는 것이 아닌 Python을 활용하여 웹 스크래핑으로 여기저기 데이터를 모아 전처리 과정을 거쳐 생성됩니다 . 콘텐츠를 자신이 원하는 것만 골라서 네이버, 다음, CNBC 등 이곳저곳의 뉴스를 한 곳에 모아볼 수 있습니다. 

     

    Python → AWS → Spring

    이렇게 배포까지는 처음 설계해보다보니 쉽지 않았습니다. 아이디어를 검증할 수 있는 방법은 오직 구현뿐이었기 때문에 최대한 군더더기를 줄이려고 노력했습니다. 구독형 콘텐츠 프로젝트에 대한 자료가 없기 때문에 혼자서 데이터 처리 프로세스를 설계했습니다. Jython으로 Spring에서 Python을 사용할 수 있는 방법이 있지만 자바 객체를 건들일 수 없다는 제약사항이 있었기 때문에 일단 Python으로 데이터를 스크래핑하여 DB에 저장하였습니다. 이러한 과정이 전부이지만 중간에 어떻게 바뀔지 모르고 웹 스크롤링 자체가 해당 웹 의존도가 높기 때문에 언제 오류가 발생할지 몰라서 Python → AWS → Spring 구조로 디자인하여 위험 요소를 분산시켜 주었습니다. 그리고 빠른 기능만 구현해보는 것이 목적이기 때문에 클라이언트 쪽 무게를 줄여 Spring REST API + React를 사용하지 않고 Sping MVC 구조를 사용했습니다.

     

    1. Naver, CNBC 등 웹에 접근하여 원하는 섹터 및 정보를 Python으로 데이터 스크래핑하여 CSV파일로 저장합니다.
      1. CSV파일을 사용한 이유는 JSON, XML보다 크기가 더 가볍기 때문입니다. (참고)
    2. 스크래핑한 CSV데이터 파일을 Python으로 S3에 업로드합니다.
    3. S3로부터 CSV데이터 파일을 Spring으로 가져옵니다.
    4. Spring에서 JPA가 읽을 수 있게 데이터 전처리 단계를 거쳐 DB에 저장합니다.
    5. DB에 저장된 새로운 소식을 Client(웹,이메일)에게 전송합니다.
      1. 웹 브라우저(Chrome, Safari, Firefox 등)에 뉴스를 업로드합니다.
      2. SMTP서버를 통해 유저 이메일로 뉴스를 전송합니다.

     

    프로젝트 구조 설계

    💡 전체 프로젝트 코드는 Github에서 볼 수 있습니다.

     

    기술 스택

    • Backend : Java 11, SpringBoot2.4.5, Gradle6.8.1, JUnit4
    • Frontend : Thymeleaf, Bootstrap(html+css), 
    • DB : MariaDB(RDS), h2(local)
    • Web Scraping : Python 3.8.3
    • DevOps
      • AWS EC2(Linux2), RDS, S3
      • Github

     

    3. 프로젝트 기능

    1) 클라이언트

    • 해당 웹을 통해서 당일 트렌드 뉴스를 볼 수 있습니다.
    • 날짜로 조회하여 이전에 기록된 뉴스를 검색해 볼 수 있습니다.
    • 이메일 구독을 할 경우, 매일 오전 7시 당일 트렌드 뉴스를 받아 볼 수 있습니다.

    클라이언트 기능
    메일로 뉴스 발송

     

    2) 백오피스

    • ADMIN 권한이 부여된 사용자만 로그인 후 접근이 가능합니다.
    • S3에서 당일 트렌드 뉴스를 DB로 수동으로 직접 저장할 수 있습니다.
    • S3에서 날짜로 조회하여 이전에 기록된 뉴스를 DB에 수동으로 직접 저장할 수 있습니다.
    • 이메일을 구독한 유저들에게 당일 트렌드 뉴스 수동으로 직접 전송할 수 있습니다.

     

    3) 자동화 스케줄링 기능

    Python - crontab (뉴스 웹 스크래핑 후 S3 업로드) 

    웹 스크래핑(web scraping)으로 각 사이트의 트렌드 뉴스를 S3에 저장합니다.

    • crontab -e 
    test (매 1분마다)
    */1 * * * * python3 /home/ec2-user/app/step1/loobie_alpha/python/readNews.py
    */1 * * * * python3 /home/ec2-user/app/step1/loobie_alpha/python/s3Upload.py

    real(매일 오전 6시 40분, 6시 45분)
    40 6 * * * python3 /home/ec2-user/app/step1/loobie_alpha/python/readNews.py // 웹 스크래핑
    45 6 * * * python3 /home/ec2-user/app/step1/loobie_alpha/python/s3Upload.py // s3에 업로드 

     

    Spring - @Scheduler (S3에서 뉴스 다운로드 후 유저에게 이메일로 발송)

    이메일 인증을 한 구독자들에게 매일 오전 7시 당일에 수집한 트렌드 뉴스를 전송합니다.

    test(매 30분 마다)
    @Scheduled(cron = "0 0/30 * * * *", zone="Asia/Seoul")
    @Scheduled(cron = "0 0/30 * * * *", zone="Asia/Seoul")

    real(매일 오전 6시 55분, 6시 59분)
    @Scheduled(cron = "0 55 6 * * *", zone="Asia/Seoul") // s3 뉴스 받아오기
    @Scheduled(cron = "0 59 6 * * *", zone="Asia/Seoul") // 구독 유저에게 뉴스 메일 전송 

     

    4) 클라이언트/ 백오피스 뷰

    (왼)클라이언트 뷰, (오른)백오피스 뷰

     

    4. 느낀점 및 회고

    린하게 이게 작동이 되는 설계인지 직접 확인해보자는 의도와 함께 개인 역량을 키우고자 시작했기 때문에 프로젝트 기간 중 여러 서적과 강의를 읽으며 개발을 진행하였습니다. 개발하면서 틀이 잡혀가는 과정에서 이것저것 넣어보고 뭔가 더 추가하려는 욕심이 자꾸 생겼었지만 참고 설계와 기초적인 부분만 지켜서 설계하는 데에 포커스를 두고 진행했습니다. 프로젝트를 하며 블로그에 정리한 글들은 다음과 같습니다.

     

    처음에는 굉장히 어렵고 이게 될까 했지만 어떻게 직접 생각해낸 구상을 여차저차 MVP 제품으로 만들어보니 느낀점이 많았습니다. 설계에 대한 감과 전체적인 운영 프로세스 등 얻은 부분도 많았지만 이것저것 직접 만져보니 부족한 점이 체감적으로 다가왔습니다.

     객체지향 설계, 버전 관리, 테스트 코드, 자바, 스프랑 내부 동작 과정 등 블랙박스가 너무 많이 느껴졌습니다. 버전 실수 때문에 오래 헤매기도 하고, 객체 지향 프로그래밍 설계는 테스트 코드라고 하는지(프로젝트 신뢰성 및 유지 관리, 변동성 감지 용이) 몸소 느끼게 되었습니다.  직접 만든 MVP 제품을 배포까지 하고 구동도 해봤으니 이젠 모자란 부분에 대해 열심히 학습해서 다음 프로젝트에서는 더 유연하고 확장 가능한 프로젝트를 만들어서 운영까지 해보는 게 다음 목표입니다.

    Spring, Python으로 만든 자동화 콘텐츠 구독 서비스 (루비 LOOBIE)


    ※ 프로젝트에 참고한 서적 및 강의

    객체지향의 사실과 오해
    자바 ORM 표준 JPA 프로그래밍 - 기본편
    실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
    스프링과 JPA 기반 웹 애플리케이션 개발
    스프링 부트와 AWS로 혼자 구현하는 웹 서비스
    Python으로 웹 스크래퍼 만들기
    파이썬 무료 강의 (활용편3) - 웹 스크래핑 (5시간)

     

    더보기

    Next Loobie...

    이제 설계하는 법과 EC2 배포 등 경험을 쌓고 이 설계가 먹히는 것을 확인했으니 좀 더 자율성을 높이고 기능을 업그레이드 시켜 Spring REST API + React + Python으로 개발해 볼 예정이다. 이번에 Front를 MVC로 개발하면서 html,css를 사용하는게 불편했다. 그래서 SPA인 React로 구현할 예정이며 antd, styled-components와 같은 라이브러리를 사용해 UI/UX에 더 신경써 볼 생각이다. Back은 Spring을 RSET API 서버로 Front와 분리시킬 것이고 예전 프로젝트에서 사용해봤던 Spring Security JWT와 이번에 사용해본 써드파티(카카오,네이버,구글)를 사용하여 로그인과 권한을 구현해보려 한다. 사실상 로그인 기능은 초기 Client에서는 필요가 없는 기능이라서 Admin쪽에서만 일단 해보려한다.

     

    그리고 Python으로 스크래핑하는 콘텐츠도 변경해 볼 계획이다. 저작권에 침해가 되지 않는 한 어느 특정 유니크한 콘텐츠를 전처리 과정으로 보기좋게 가공한 다음 한 곳에 모아보고 싶어졌다. 비슷한 사례로는 엑셀로 제공하는 ark Invest를 전처리과정을 통해 새로운 콘텐츠를 제공하는 lucidtracking, arktrack 과 같은 서비스가 있다. 

     

    이 업그레이드 버전은 빨리 만들고 싶지만 지금 당장은 Java, Spring에 대해 더 심도있게 다뤄보고 싶고 요즘 화제가 많은 블록체인 시스템에 대해 전반적으로 공부해보고 싶은 마음이 더욱 크다. 그래서 아마 특이사항이 없으면 눈꽃이 피는 4분기나 연말쯤 알파버전을 제대로 시작하여 클라 배포까지 진행하게 될 것 같다.