오픈소스 크롤러 프로젝트는 범용 크롤링, 브라우저 자동화, 스케줄링과 큐, 파싱과 저장의 네 역할로 나누면 선택이 쉬워집니다. 각 역할의 목적, 조합 시 흔한 문제, 직접 확인할 수 있는 네 가지 평가 기준을 설명합니다.
GitHub에서 크롤러를 검색하면 수백 개에서 수천 개의 저장소가 나옵니다. 많은 사람이 별 개수를 보고 가장 인기 있는 프로젝트부터 선택합니다.
하지만 인기와 자신의 상황에 맞는지는 다른 문제입니다. 아무리 유명한 프로젝트라도 목적이 실제 시나리오와 맞지 않으면 오히려 사용이 더 힘들어집니다. 더 쉬운 출발점은 역할을 먼저 나누는 것입니다. 장기간 안정적으로 돌아가는 수집 시스템은 원래 서로 다른 책임을 가진 여러 구성요소를 조합해서 만듭니다. 각 부분이 무엇을 담당하는지 이해하면 구체적인 구현을 비교하기가 훨씬 쉬워집니다.

범용 크롤러 프레임워크: 구조가 안정적인 페이지용
이런 프레임워크는 요청 스케줄링, 동시 수집, 데이터 파이프라인을 담당합니다. 여러 URL을 입력으로 받고 구조화된 결과를 출력합니다. 성숙한 생태계와 미들웨어 구조 덕분에 자체 로직을 넣을 수 있고, 대규모 장기 작업도 비교적 안정적으로 운영할 수 있습니다.
JavaScript가 실행된 뒤에야 내용이 나타나는 페이지는 단독으로 처리하지 못합니다. 이 경우 처음 받은 응답은 빈 껍데기에 가깝기 때문에 별도의 렌더링 엔진을 붙여야 합니다. 목록 페이지, 상세 페이지, 공개 API처럼 구조가 안정적인 대상에 적합합니다.
브라우저 자동화 프레임워크: 렌더링과 상호작용이 필요한 페이지용
실제 렌더링이 필요하거나 로그인 상태가 필요하거나 몇 번 클릭해야 내용이 나오는 페이지는 브라우저 자동화를 사용해야 합니다. 여러 브라우저 엔진에서 실행할 수 있고, 대기 메커니즘이 성숙하며, 페이지의 요청과 응답을 직접 다룰 수 있습니다.
대신 순수 HTTP 요청보다 자원 소모가 훨씬 큽니다. 동시 실행 한도는 주로 로컬 메모리와 CPU에 의해 결정됩니다. 자동화는 감지 가능한 특징도 남기므로, 탐지가 엄격한 사이트에서는 식별될 수 있습니다.
스케줄링과 큐 구성요소: 작업이 많아졌을 때 필요
대상이 적을 때는 단순한 루프로도 충분합니다. 작업이 수천 개로 늘고 빈도 제어와 재시도까지 필요해지면 별도의 스케줄링 계층이 필요합니다. 작업을 어떻게 큐에 넣을지, 동시 실행 수를 얼마나 둘지, 실패 후 얼마 뒤에 다시 시도할지, 어떤 작업을 포기할지를 관리해야 합니다. 이런 로직을 전부 크롤링 프레임워크 안에 넣으면 코드가 빠르게 복잡해집니다.
이 계층을 직접 만들 때 흔한 실수는 프로세스 메모리 안의 큐로 버티는 것입니다. 프로세스가 재시작되면 대기 중이던 작업이 모두 사라집니다. 최소한 큐는 영속성을 가져야 하고 상태를 조회할 수 있어야 합니다.
파싱과 저장 구성요소: 데이터를 바로 쓸 수 있는지 결정
가져오는 것은 HTML이지만 실제로 필요한 것은 필드입니다. 파싱 계층은 추출 규칙 관리, 필드 검증, 중복 제거, 저장을 담당해야 합니다. 구조가 자주 바뀌는 사이트라면 고정 셀렉터 대신 페이지 특징을 바탕으로 데이터를 찾는 적응형 추출 방식을 검토하면 유지보수 부담을 줄일 수 있습니다.
저장 쪽에서는 멱등성도 중요합니다. 작업 재시도는 흔하므로, 고유 식별자를 기준으로 중복을 제거해 저장해야 합니다. 그렇지 않으면 중복 데이터가 이후 분석까지 오염시킵니다.
구성요소를 합친 뒤 자주 생기는 문제
각 부분을 따로 보면 어렵지 않습니다. 문제는 보통 연결 지점에서 발생합니다.
- 스케줄링 계층이 재시도했지만 파싱 계층이 중복 제거를 하지 않아 같은 행이 생김
- 브라우저 계층에 동시 실행 상한이 없어 로컬 자원을 모두 사용하고 전체 배치가 함께 실패함
- 파싱 규칙이 코드에 고정되어 있어 사이트가 바뀔 때마다 다시 배포해야 함
- 구성요소마다 같은 작업의 식별자가 달라 상태가 맞지 않고 중단 지점에서 이어서 실행할 수 없음
네 가지 평가 기준
필요한 범주를 정했다면 다음 네 가지 기준으로 구체적인 프로젝트를 걸러냅니다.
유지보수 활동은 전체 별 개수보다 최근 몇 달의 커밋 빈도와 issue 응답 속도를 확인해야 합니다. 유지보수가 중단된 프로젝트는 대상 사이트가 바뀐 뒤 바로 동작하지 않을 수 있습니다.
문서와 예제는 시작 비용을 좌우합니다. 설명이 모호하거나 가장 단순한 예제만 있다면 학습 시간이 예상보다 길어질 가능성이 큽니다.
확장성에서는 어떤 연결 지점을 제공하는지 봅니다. 프록시를 바꿀 수 있는지, 자체 렌더링 엔진을 연결할 수 있는지, 저장 방식을 교체할 수 있는지 확인해야 합니다. 확장 지점이 잘 마련된 프로젝트는 나중에 소스 코드를 직접 고치지 않고도 변경하기 쉽습니다.
라이선스와 컴플라이언스 위험은 쉽게 놓칩니다. 상업적으로 사용하기 전에 라이선스 유형을 확인하고 목적과 맞지 않는 제한적 라이선스는 피해야 합니다. 수집 범위, 요청 빈도, 대상 사이트의 약관도 함께 검토해야 하며, 이는 프레임워크의 기술적 품질과는 별개의 문제입니다.
환경 계층은 또 다른 수준의 문제
프레임워크는 데이터를 어떻게 가져올지를 해결하지만, 신원과 규모 문제까지 해결하지는 않습니다. 작업에 로그인, 지역 구분, 여러 계정의 병렬 실행이 필요할 때 모든 것을 같은 브라우저 환경에서 돌리면 두 가지 문제가 생깁니다. Cookie와 로컬 저장소가 겹치며 세션이 서로 영향을 주고, 대상 사이트가 사실상 관련 없는 작업을 같은 방문 집단으로 볼 수 있습니다.
성숙한 방식은 브라우저 환경을 독립된 리소스 계층으로 만드는 것입니다. 작업은 환경 풀에서 하나를 받아 사용하고 끝나면 반환합니다. 이런 아키텍처에서 PurpleMark는 이 계층에 해당하며, 일괄 생성할 수 있고 독립된 네트워크 출구에 연결할 수 있으며 상태를 조회할 수 있는 환경 리소스를 제공합니다.
컴플라이언스 경계
대상 사이트의 robots 규칙과 서비스 약관을 따르고, 개인정보를 수집하지 않으며, 기술적 보호 조치를 우회하지 않고, 상대 서비스의 정상 운영에 영향을 주지 않도록 요청 빈도를 조절해야 합니다. 프로젝트 선택은 효율성의 문제를 해결하지만, 이런 판단은 수집을 수행해도 되는지를 결정합니다.


