본문 바로가기

프로그래밍/크롤링(PYTHON)

더 우아한 크롤러를 위해 / 분산 크롤러 / 크롤러 아키텍쳐

반응형
본 게시물은 다양한 외부 소스들을 종합해서 정리하고 기록하기 위한 글입니다. 일부분 필자의 의견이 섞여있으므로 정확한 내용을 알고싶으시다면 하단의 출처를 참고해주세요.

크롤러? 뭐 더 공부할게 있나..

내가 크롤러에 관심을 갖게 된 후, 주변에서의 크롤링 기술에 대한 인식이 영 긍정적이지만은 않다는 것을 안 것은 불과 몇 주전 이었다. 

대기업들한테 가서 크롤링 이야기하면 그래요, "크롤러? 그거 쉬운걸 뭐 굳이.." 

- 기업초청 세미나에서 A 빅데이터 회사 대표이사

 

  상당한 규모의 정보 수집, 분석 능력이 있는 한 회사의 대표이사가 이야기했을 정도면 얼마나 답답했을까! 모든 기술에는 기반이 필요한 법이고, 그 기반은 결국 누군가가 다져놓지 않으면 기술은 성립되지 않는다. 뭐, 이 기술이 중요하고 어떤 기술이 덜 중요하고를 논하고자 하는 것이 아니라, 분명 해당 분야에 대한 자부심을 갖는 사람들은 존재하고 이를 업신여기는 듯한 언행은 분명 잘못이다. 다분히 대기업 - 협력사의 관계만을 이야기하는 것이 아니고, 일상에서도 자주 듣게 되더라.

 

  지난 프로젝트를 진행하면서 부쩍 크롤러에 대한 관심이 늘었다. 위의 사례에서 그러하듯 나도 크롤링은 그저 던져진 URL에서 태그만 뚫어져라 쳐다보면 되는 것 인줄 알았다. 실제로 지난 크롤러도 그런 주먹구구식으로 개발했다. (ㅜㅜ) 좀 더 우아한 크롤러를 개발하고 싶어졌다. 그리고 크롤러는 다행히도 어느정도 정형화된 틀이 존재했고, 그것이 단순히 죽어라 네이버 검색순위와 영화의 평점을 긁어오는 목적성이 다분한 일회성의 프로그램이 아니라는 것이다. 크롤러에도 분명 아키텍쳐가 존재하고, 필수 요소들이 존재한다. 크롤러의 목적 (Width, Depth)에 따라서 그 구조도 분명 달라지겠다.

 

크롤러의 성능

  크롤러의 성능은 매우 중요하다. 아무리 수천페이지의 제품을 자동으로 긁어올 수 있다 한들, 시간이 1주, 1달 이상 걸린다면 크롤러로서의 의미는 전혀 없다. 그래서 크롤러의 성능에 미치는 영향을 잘 이해해야한다.

  크롤러의 성능은 지연시간과 깊은 연관이 있다. 크롤러가 동작하는 와중에 어디선가 지연이 발생한다면, 크롤러는 꼼짝없이 동작을 멈추고 이를 기다려야만 하고, 이 지연시간은 크롤러의 성능과 직결된다. 우리는 여기서 크롤러의 지연시간을 병목점(Bottleneck)과 다시 연관지을 수 있다.

 

뭐라는거야?

 

  그러니까... 구조상으로 크롤러의 동작 자체는 매우 빠르다. 요청을 보내고, URL을 파싱하고 하는 작업은 오래걸리지 않는다. 바로 "요청 후 대기시간"에 비하면 말이다.  크롤러는 왜 대기시간을 갖고 있어야할까? 그다지 어려운 질문은 아니다. 웹서버 입장에서 1초에 수백번의 요청을 보내오는 IP를 가만둘리가 없다. 그러므로 웹서버에 대한 예의를 지키고 정중하게 크롤링해야만 하는 것이다. 이를 크롤러가 가져야할 필수 요소로 Politeness 라고 한다.

  그런데 모든 크롤러가 같은 대기시간을 갖고 있을까? 또 그건 아니다. 크롤러의 목적에 따라서 이 대기시간도 천차만별이다. 2가지 상황을 가정해보자.

 

넓은 탐색 크롤러

  특정 도메인을 시작으로 관련된 모든 링크를 타고 뻗어나가는 크롤러다. 가령 A라는 웹페이지 메인으로부터 10 개의 링크가 존재한다면, 크롤러가 서버에 요청해야하는 페이지의 갯수는 10개에 불과하다. (다소 극단적이지만..) 상대적으로 크롤러의 행동에 대해서 개발자가 특별히 할 것이 없기 때문에 오히려 크롤러가 구동되는 환경과 자원을 효율적으로 이용할 방법이 성능 향상과 직결된다.

  그러므로 위에서 언급한 대기시간은 "넓은 탐색 크롤러"에게 큰 문제가 되지 않는다. 실제로 서버에 큰 부하를 주지 않기 때문에, 이보다는 크롤러의 구동환경을 효율적으로 잘 구성하는 것이 열쇠가 될 것이다.

 

좁은 탐색 크롤러

  여기서는 이야기가 조금 다르다. 어떤 목적을 갖고 탐색하는 이 크롤러는 ( e.g. 마켓페이지의 상품 목록 전체 크롤링 ) 만약 임의의 대기시간을 주지않는 다면 금새 웹서버에게 방대한 양의 트래픽을 날리게 된다. 위에서 언급한 Politeness와 직결되는 문제로 어쩔 수 없이 임의의 대기시간을 갖고 있어야만 한다. 아무리 좋은 구동환경과 스케줄링이 뒷받침해도 수 초(sec)에 해당하는 대기시간을 극복할 방법은 찾기 어렵다.

 

크롤러 아키텍쳐

크롤러 아키텍쳐

  크롤러에 아키텍쳐 같은 것이 있다고는 생각 못했다. 그냥 코드 조각에서 미리 입력해둔 URL들만 루핑해서 요청하면 되는 것으로 생각했지만, 생각보다 크롤러는 거대했고, 단단했다. (?) 물론, 위 그림이 크롤러 아키텍쳐의 스탠다드 라던가, 모든 사람들이 전부 이렇게 구현한다고 하는 것은 아니다. 대략적인 구조가 이렇고, 나도 이렇게 작성해보려고 한다. 정도로 알아두면 될 것 같다.

 

URL Frontier : 크롤링할 URL을 담고 있는 곳
DNS : URL Frontier로 부터 받아온 URL을 어떤 웹서버가 Fetch할 것 인지
Fecth : 해당 페이지에 HTML 요청
Parse : 가져온 HTML을 파싱
Dup URL Elim : 중복된 URL 검사 및 제거

 

위 요소들은 모듈로 존재하고, 개인적으로 DNS 부분은 별도의 크롤러 서버를 둘 scale 까지는 아니라고 생각해서 타겟 URL에 대한 rule을 정의하고 별도의 모듈로 동작하도록 만들 것이다.

 

+ 2020.01.02
지금 원문 링크를 확인해 봤는데, 도메인이 만료됐는지 제대로 뜨지 않네요 ㅠㅠ
http://blog.blikk.co/comparison-of-open-source-web-crawlers/

비슷하게 크롤러 아키텍쳐를 잘 설명하고 있는 문서 공유드리겠습니다.
https://nlp.stanford.edu/IR-book/pdf/20crawl.pdf

반응형