송지민

송지민님의 아티클

송지민

송지민

반복되는 크롤링 작업을 Spring Batch로 해결해보자

나는 하루에 책을 얼마나 읽었는지 기록하고 이를 그래프로 나타내는 서비스를 개발하고 있다.

따라서 책 정보가 필수인데 책 검색 API를 사용하기보다 크롤링을 통해 우리 서비스에서 필요한 정보만 저장하기로 결정, 크롤링을 통해 정보를 저장중이었다.

기존 크롤링 방법

  1. 모든 카테고리를 순회하면서 각 카테고리 별로 20권씩 크롤링

  2. 매 탐색마다 책 정보를 DB에 바로 저장

  3. 원하는 정보가 누락되어 있거나 탐색 중 에러가 발생한다면 해당 책은 스킵

딱 1000권만 크롤링 할 목적으로 코드를 작성했기 때문에 위 방법으로 진행해도 문제가 없었다.

하지만 신간도서 관련 기능이 추가되면서 반복적으로 크롤링을 해야 하는 상황이 벌어지니 문제가 발생했다.

문제

  1. 이전에 진행한 크롤링으로 저장된 책이 다음 크롤링에서 다시 저장되는 책 중복 발생

  2. 매 탐색마다 책 정보를 바로 저장하다보니 총 1000번의 쿼리 발생

  3. 크롤링이 중간에 멈추게 된다면 중단된 시점까지의 책 정보가 그대로 저장

  4. 기능 확장으로인해 Elasticsearh 추가, 데이터를 ES로도 전송해야함

크롤링으로 인한 문제와 추가된 기능들로 인해 기존 서비스 구조로는 문제를 해결할 수 없다고 생각했고 내가 필요한 기능들이 모두 갖추어진 Spring Batch를 사용해서 이 문제를 해결하기로 했다.

Spring Batch를 사용하는 이유

  1. 크롤링, DB에 저장과 같은 반복적인 작업의 자동화

  2. 대용량 데이터의 안전하고 빠른 처리

  3. 작업 실패 시 기존 상태로 복구

데이터 처리 과정

크롤링 파이프라인.png
  1. 크롤링 정보 1차 저장

    • 크롤링 한 정보를 List로 만들어 저장한다. 그 후 크롤링이 끝나면 MongoDB에 List를 저장한다.

    • 이 때 책 정보를 List에 저장하면서 동시에 책 URL을 Map에 저장한다. 이는 이후 Redis에 저장된다.

    • 1차적으로 MongoDB에 저장하는 이유

      1. 백업

      2. Monstache를 사용해서 ES에 동기화시키기 위함

      3. 크롤링 시 책 필드 변경이 용이

  1. 크롤링 정보 2차 저장

    • MongoDB에 저장한 정보를 실제 서비스에서 사용할 MySQL에 저장

    • TransactionManager를 사용해 에러 발생 시 chunk size 만큼 rollback

3,4. Collection 변경 감지, 변경된 상태 적용

  • Monstache를 사용해서 변경된 상태대로 ES 동기화

  • Spring Batch의 step으로 저장하지 않고 Monstache 사용

    • ES는 rollback, transaction을 지원하지 않기 때문

      Untitled.png
    • 굳이 step으로 처리할 필요 없이 Monstache로 관리하는 것이 좋다고 판단

  1. 중복 확인용 책 링크 저장

    • 1에서 저장한 Map을 Redis에 저장한다.

    • MongoDB보다 비교적 빠른 Redis를 사용해서 빠르게 중복된 책인지 확인

    • 가장 마지막에 Key값을 저장하기 때문에 이전 step이 실패해도 문제 x

적용 후

위 순서로 데이터를 저장하는 Spring Batch Application을 Docker image로 만들어 EC2에서 실행중이다.매주 월요일마다 크롤링을 진행하고 안전하게 저장되는 것을 보니 적용하는데 까지 오래 걸렸지만 이제 크롤링에 신경쓰지 않아도 되니 마음이 편해졌다.

10
1
송지민

송지민

테커톡 후기

데드락을 주제로 10분간 기술, 키워드, 기술 이슈 등을 소개하는 "테커톡"을 진행했습니다!

데드락에 대해 공부하면서 단편적으로만 알고 있던 내용들을 자세하게 공부해보는 시간이었고 그 내용을 정리해서 남들과 공유해보는 좋은 경험을 하게 되어 기뻤습니다.

데드락에 대해 정리한 내용 : https://jiminsong490.github.io/posts/%EB%8D%B0%EB%93%9C%EB%9D%BD/

2
0