나는 Colly의 어느 부분이 페이지 수나 속도만으로는 드러나지 않는지 검증하려고, 확인용 사이트를 직접 만들었다. 핵심은 콜백이 기대한 레코드를 제대로 뽑아내는지, HTTP 오류를 올바르게 분기하는지, 제한된 그래프를 따라 이동하는지, 그리고 렌더링된 HTML 바깥에서 전달되는 콘텐츠도 읽어낼 수 있는지였다. 이번 검토는 처리량 벤치마크가 아니라 정확성과 경계 조건 점검이었다.
통제된 테스트 환경에서는 기대한 정적 레코드를 모두 추출했고, 500 응답 하나를 OnError로 정상 전달했으며, 설정한 깊이 제한 그래프에서 17개의 URL을 방문했다. 반면 JavaScript 실행 후에만 요소가 나타나는 두 페이지에서는 대상 요소를 0개 반환했다. 직접 접근 가능한 JSON 엔드포인트는 브라우저 없이도 그대로 사용할 수 있었는데, 이는 클라이언트 UI를 렌더링하는 것과는 중요한 차이다.
Colly가 실제로 무엇인가

Colly는 스스로를 “Golang을 위한 우아한 스크래퍼 및 크롤러 프레임워크”라고 소개한다. 이 표현은 생각보다 많은 의미를 담고 있다. Colly는 GitHub 스타 약 25,300개, 포크 약 1,850개를 보유한 Go 라이브러리이며 Apache-2.0 라이선스를 사용한다. 다운로드해서 URL만 넣는 CLI 도구가 아니다. Go 코드를 작성하고, Colly를 import한 뒤, 몇 개의 콜백을 등록하고, 전체를 하나의 실행 파일로 컴파일하는 방식이다.
구조는 이벤트 중심으로 이해하면 쉽다. Collector에 핸들러를 붙이는 방식인데, OnHTML은 CSS 선택자와 일치하는 요소에 대해 추출 로직을 실행하고, OnResponse는 원시 응답 본문을 제공하며, OnError는 요청 실패를 처리한다. 링크 핸들러는 발견한 URL에 대해 Visit()를 호출하고, MaxDepth는 탐색 깊이를 제한한다. HTTP만 사용하는 경로라면 대상 호스트에 별도의 Go 런타임이나 브라우저가 필요 없다. 다만 실행 파일이 완전한 정적 바이너리인지 여부는 빌드 플래그와 CGO 사용 여부에 따라 달라지며, 이번 테스트에서는 그 부분을 기록하지 않았다.
핵심 기능과 내부 동작 방식

콜백 모델을 이해하는 것이 중요하다. Colly가 일반적인 요청-파싱 스크립트와 다르게 느껴지는 이유이기 때문이다. 내가 실행한 모든 테스트는 세 가지 콜백으로 충분했다.
OnHTML(selector, handler)는 가장 많이 쓰는 핵심 기능이다. .product나 article p에 등록해 두면, Colly가 DOM을 파싱하면서 일치하는 요소마다 핸들러를 한 번씩 호출한다. 구조화된 추출은 여기서 이뤄진다. 무엇을 가져올지 설명할 뿐, 파싱 루프를 직접 짤 필요가 없다.
OnResponse(handler)는 한 단계 아래에서 원시 바이트를 제공한다. 대상이 HTML 대신 JSON을 돌려줄 때는 DOM을 아예 건너뛰고 본문을 직접 unmarshal 하면 된다. 내가 테스트한 JSON API를 Colly가 별도 HTML 파싱 없이 깔끔하게 처리할 수 있었던 이유가 바로 이 콜백 하나였다.
OnError(handler)는 요청 실패를 처리하고, 호출한 코드가 응답 상태를 확인할 수 있게 해준다. 이번 테스트에서는 500 상태의 fixture 응답 하나가 등록된 콜백까지 도달했다. 다만 재시도, 타임아웃, DNS 실패, 연결 리셋, 콜백 panic, 영속화, 알림 기능은 테스트하지 않았다.
콜백 위에는 두 가지 운영 기능이 더 있다. MaxDepth는 Colly의 깊이 의미 체계에 따라 링크 탐색 범위를 제한한다. 그리고 Go로 컴파일된 실행 파일은 대상 머신에 별도의 언어 런타임 설치를 요구하지 않는다. 이번 실행에서는 빌드 플래그나 CGO 상태를 기록하지 않았기 때문에, 결과 바이너리가 모두 완전한 정적 링크라고까지 말할 수는 없다.
설치 환경: 필요한 Go 툴체인
의존성 이야기는 짧지만 실제로 중요하니, 설치 전에 먼저 짚고 넘어가겠다. 내가 테스트한 머신에는 Go가 설치되어 있지 않았다. Colly는 Go 라이브러리이므로, 첫 단계는 머신에 Go 툴체인을 올리는 일이었다(나는 Homebrew로 Go 1.26.5를 설치했다). 팀이 이미 Go 생태계에서 일하고 있지 않다면, 이건 Colly 자체의 문제가 아니라, 한 줄도 컴파일하기 전에 필요한 언어 환경이 만들어져야 한다는 점이 진짜 진입 장벽이다.
Go가 준비된 뒤 go get github.com/gocolly/colly/v2는 v2.3.0으로 해석되었다. 테스트한 경로에는 브라우저나 headless Chrome이 필요하지 않았다.
버전 표시에서 헷갈릴 만한 지점도 있다. Go 모듈은 v2.3.0(2025년 12월 배포)으로 해결되었고, 확인 당시 GitHub Releases UI에서 보이던 최신 항목은 v2.2.0(2025년 3월)이었다. 이는 모듈/저장소 버전과 GitHub Release 항목의 차이이지, 모듈과 Git 태그의 차이가 아니다. 나는 v2.3.0을 테스트했다.
실전 테스트: 추출과 운영 경계

나는 Colly를 자체 제작한 fixture 서버(Go의 httptest)와 두 개의 공개 데모 사이트에 대해 실행했다. 현재 벤치마크 디렉터리와 results/colly-test-summary.json에서 산출물을 확인할 수 있지만, 두 링크 모두 변경 중인 브랜치를 따른다. 기사에는 테스트한 커밋, 정확한 명령어, 빌드 플래그, fixture 시드가 제공되지 않으므로, 아직은 그대로 재현 가능한 불변 레시피라고 보기 어렵다.
| 테스트 | 대상 | 결과 |
|---|---|---|
| 정적 카탈로그 + 페이지네이션 | 로컬 fixture | 기대한 제품 12/12개 추출 |
| 기사 추출 | 로컬 fixture | 제목 + 문단 3/3개 |
| 직접 JSON 응답 | 로컬 fixture | OnResponse로 기대 항목 8/8개 |
| HTTP 500 처리 | 로컬 fixture | OnError로 전달, 상태 500 |
크롤 그래프 (MaxDepth 2) | 로컬 fixture | 17개 페이지 |
| Books to Scrape | 공개 데모 | 제품 20개 |
| 동적 페이지(비-JS) | 로컬 fixture | 카드 0개(예상됨) |
| Quotes JS(렌더링 없음) | 공개 데모 | 0개(예상됨) |
통제된 정적 fixture에서는 설정한 선택자가 기대한 제품 레코드 12개를 모두 뽑아냈고, 기사 문단도 기대한 3개가 전부 추출됐다. 직접 JSON 응답은 HTML 파서를 전혀 거치지 않았다. OnResponse가 본문을 넘겨주면, harness가 8개 항목을 모두 디코딩한다. 500 fixture 하나는 상태와 함께 OnError로 도달했고 그 실행을 중단시키지 않았지만, 이것만으로 무인 운영의 신뢰성을 입증하는 것은 아니다. 공개 Books to Scrape 페이지에서는 셀렉터가 20개 제품을 반환해 공개 사이트 스모크 테스트를 통과했다.
탐색용으로는 harness의 시드 깊이 규칙에 맞춰 MaxDepth(2)를 설정했으며, fixture 그래프에서 17개 URL을 방문했다. 이 결과는 속도가 아니라 크롤 커버리지다. 더 넓은 일반론이 아니라 이번에 관찰한 추적 결과는 results/local_crawl_graph.json에 있다.

Colly는 JavaScript를 실행하지 않는다. JavaScript로 렌더링되는 fixture에서는 대상 카드가 0개였고, 공개 Quotes to Scrape JS 페이지에서도 대상 인용문이 0개였다. 요소가 브라우저 실행 이후에만 나타나고, 이를 대신해 접근 가능한 백엔드 엔드포인트도 없다면, HTTP 전용 경로로는 렌더링된 DOM을 볼 수 없다. 이런 경우에는 렌더러를 붙이거나, JSON fixture가 보여주듯 직접 백엔드 엔드포인트를 호출해야 한다.
비동기 collector, rate limit 또는 예의 정책, 프록시 회전, 재시도, 큐 및 저장소 백엔드는 따로 부하를 주지 않았다. 경과 시간, 처리량, 동시성, CPU, 메모리, 대상 응답 지연, 비교 기준선도 측정하지 않았다. 따라서 이 글은 속도나 무인 안정성에 대한 주장을 하지 않는다.
fixture 결과를 어떻게 해석할 것인가
성공한 세 가지 콘텐츠 경로는 서로 다른 계약을 검증한다. 카탈로그와 기사 사례는 서버가 반환한 HTML에 대한 CSS 선택을 시험한다. 기준분모는 추출 전에 미리 작성한 fixture 기대값, 즉 제품 레코드 12개와 기사 문단 3개다. 이를 “기대 레코드 모두 추출”이라고 표현한 것은 의도적이다. 이번 실행은 fuzzy matching, 중복 처리, 일부 필드 허용, 말뭉치 전체 기준 recall 같은 지표를 정의하지 않았으므로, 이 결과를 일반적인 추출 정확도로 확대 해석하면 안 된다.
JSON 사례는 DOM 선택을 아예 건너뛴다. Colly는 OnResponse를 통해 응답 바이트를 받고, JSON 디코딩은 harness가 수행한다. 그래서 “Colly는 JavaScript를 렌더링하지 않는다”는 말이 모든 클라이언트 기반 사이트를 사용할 수 없다는 뜻은 아니다. 클라이언트가 사용하는 데이터 소스가 직접 호출 가능한 엔드포인트이고, 브라우저 밖에서도 재현 가능한 요청이라면 HTTP 크롤러만으로 충분할 수도 있다. 다만 인증, 생성 서명, 브라우저 전용 상태, 봇 방지 장치가 있으면 답이 달라질 수 있고, 이번 테스트에서는 그런 요소를 다루지 않았다.
500 경로는 복구가 아니라 분기 처리 테스트다. 등록된 OnError 콜백이 fixture 응답과 그 상태를 받았다는 사실을 보여줄 뿐이다. 운영용 크롤러라면 재시도 가능한 코드, 백오프, 종료 실패, 영속화, 알림에 대한 명시적 정책이 필요하다. 이번 테스트는 그런 선택에 대한 증거를 제공하지 않으며, “콜백이 실행됐다”는 사실을 “무인으로 믿고 돌릴 수 있다”로 읽어서는 안 된다.

17개 URL 그래프도 마찬가지로 범위가 좁다. 이번 fixture, 이번 시드 규칙, 그리고 MaxDepth(2)가 만들어낸 방문 집합을 확인했을 뿐이다. 초당 페이지 수, 호스트 간 공정성, 메모리 증가, 순환 구조와 중복 URL 형태에 대한 동작은 입증하지 않는다. 그런 내용은 별도의 워크로드 및 큐 테스트가 필요하다.
이번 실행에 근거한 선택 체크리스트
먼저 Colly가 실제로 받는 응답을 보아야 한다. 필요한 필드가 서버가 반환한 HTML 안에 있다면 OnHTML을 사용하고, 레코드를 받아들이기 전에 필드 수나 필수 키를 검증하라. 응답이 JSON이라면 OnResponse로 본문을 처리하고 스키마를 검증하라. HTML이 사실상 애플리케이션 껍데기라면, 브라우저를 붙이기 전에 접근 가능한 백엔드 요청에 데이터가 있는지 확인하라.
| 응답에 포함된 내용 | Colly 경로 | 수용 기준 |
|---|---|---|
| 서버가 반환한 HTML 안의 필수 필드 | OnHTML 선택자 | 필수 키와 기대 레코드 수 |
| 직접 호출 가능한 JSON 페이로드 | OnResponse + JSON 디코딩 | 스키마 및 필수 필드 검증 |
| 재현 가능한 요청으로 뒷받침되는 HTML 껍데기 | 백엔드 엔드포인트 요청 | 응답 상태, 스키마, 완전성 |
| 브라우저 실행 후에만 생성되는 데이터 | 렌더러를 추가하거나 브라우저 크롤러 사용 | 대상별 준비 상태와 완전성 |
브라우저 실행이 꼭 필요하다면, Colly의 어떤 옵션이 렌더링을 켜줄 것이라 기대하지 말고 별도 컴포넌트로 취급해야 한다. 브라우저는 준비 상태를 확립하고, 렌더링된 콘텐츠나 백엔드 응답을 노출한 뒤, 데이터를 나머지 파이프라인으로 넘겨야 한다. 이번 리뷰에서는 그런 통합을 테스트하지 않았다.
배포 단계에서는 Go 버전, 모듈 버전, 빌드 플래그, CGO 상태, 정확한 명령어, fixture 시드, 저장소 커밋을 기록해야 한다. 현재 공개 링크에는 이런 정보가 빠져 있으며, 이것이 바로 검토 가능한 산출물과 장기 재현성 사이의 차이다. 운영 측면에서는 장애 매트릭스를 추가하고, 시스템을 빠르다거나 안정적이라고 부르기 전에 실제로 중요하게 여기는 워크로드를 측정해야 한다.
장단점
장점:
OnHTML을 통해 기대한 카탈로그 제품 12/12개와 기사 문단 3/3개를 추출했다.OnResponse로 깔끔하게 JSON을 처리할 수 있었고, DOM 파싱이 필요하지 않았다 — API 항목 8/8개.- 테스트한 500 응답은 상태와 함께
OnError로 전달됐다. - 단일 collector로 깊이 제한 크롤이 17페이지에 도달했다.
- Go 실행 파일로 컴파일되므로, 테스트한 경로에서는 대상에 별도 Go 런타임 설치가 필요하지 않다.
- Apache-2.0의 관대한 라이선스를 사용한다.
단점:
- JavaScript 실행이 불가능하다 — 클라이언트 렌더링 콘텐츠는 0개로 끝난다.
- Go 툴체인이 필요하다. Go를 쓰지 않는 팀은 스크래퍼를 한 줄 쓰기도 전에 이 환경 설정 비용을 치러야 한다.
- 테스트한 모듈(
v2.3.0)이 관찰된 최신 GitHub Release 항목(v2.2.0)보다 앞서 있다. - 출력 결과는 결국 사용자가 직접 작성해야 한다 — Colly는 내장 데이터셋이나 Scrapy처럼 스키마를 바로 내보내는 feed exporter를 제공하지 않는다.
- async, rate limit, 프록시, 큐 백엔드는 존재하지만 이번에는 테스트하지 않았다. 처리량과 규모는 아직 측정되지 않았다.
누구에게 적합하고, 누가 건너뛰어야 하는가

Colly는 이미 Go로 개발하고 있고, 서버 렌더링 HTML이나 직접 접근 가능한 JSON을 대상으로 삼는다면 잘 맞는다. 콜백 모델은 구조화된 매치, 원시 payload, 요청 실패를 분리해 준다. 컴파일된 실행 파일은 대상 머신에 별도 언어 환경 설치를 피할 수 있다는 장점도 있다. 다만 여기서 완전한 정적 링크 여부는 확인하지 않았다.
필요한 대상 요소가 브라우저 실행 후에만 나타나고, 사용할 만한 백엔드 엔드포인트도 없다면 렌더러를 추가해야 한다. 직접 호출 가능한 JSON 엔드포인트라면 렌더링 없이도 요청 가능하다. 또한 Go 툴체인을 원하지 않거나, 추출 서비스가 스키마 구성과 셀렉터 유지보수까지 대신해주길 원하는 팀에는 Colly가 덜 적합하다.
대안, 그리고 Thunderbit가 들어가는 위치
Colly는 직접 운영하는 오픈소스 소프트웨어다. 벤더 사용료는 없지만, 컴퓨팅, 대역폭, 프록시, 저장소, 관측성, 엔지니어링 비용은 여전히 사용자가 부담한다. 대상이 렌더링을 요구한다면 요청 동작, 파싱 콜백, 크롤 로직, 브라우저 통합까지 모두 직접 관리해야 한다.
관리형 추출 서비스는 이런 책임 일부를 벤더에게 넘긴다. 우리는 Thunderbit를 만들고 있지만, 이번 fixture에 대해 테스트하지는 않았으므로 렌더링, 봇 방지, 품질, 지연 시간, 비용 비교에 대한 주장은 하지 않는다. 구분되는 핵심은 책임 소재다. Colly는 HTTP 응답과 콜백을 사용자의 Go 프로세스 안에 노출하는 반면, 관리형 서비스는 호출당 비용으로 데이터 수집과 스키마 구성을 책임질 수 있다.
관련 벤치마크 리뷰: 전체 오픈소스 스크래퍼 비교, Scrapy의 Python 크롤러 리뷰, Scrapling의 적응형 셀렉터 리뷰.
웹 데이터 추출을 위해 Thunderbit 사용해 보기
결론
Colly는 서버 렌더링 HTML 또는 직접 JSON을 대상으로 하고, 추출 코드를 직접 관리할 의향이 있는 Go 팀에 강력한 후보다. 이번 fixture는 기대한 레코드 추출, 하나의 제한된 크롤 추적, 그리고 하나의 500 콜백을 확인해 주었지만, 속도, 규모, 무인 안정성까지는 보여주지 않았다. 브라우저 렌더링 DOM은 별도 경로가 필요하며, 단 underlying 데이터 엔드포인트를 직접 호출할 수 있는 경우는 예외다.
웹 데이터 추출을 위해 Thunderbit 사용해 보기 Get Started Free
자주 묻는 질문
이번 리뷰에서 Colly의 속도를 측정했나요?
아니요. 기대 레코드 추출, 직접 JSON 처리, 하나의 에러 콜백, 그리고 fixture 크롤 그래프의 커버리지만 측정했습니다. 경과 시간, 처리량, 동시성, CPU, 메모리, 비교 기준선은 측정하지 않았습니다.
Colly로 JavaScript 렌더링 페이지를 스크래핑할 수 있나요?
Colly는 페이지의 JavaScript를 실행하지 않습니다. 따라서 이번에 테스트한 HTTP 경로에서는 렌더링된 DOM에서만 나타나는 대상 요소를 찾지 못했습니다. 다만 JSON fixture가 보여주듯, 접근 가능한 백엔드 JSON 엔드포인트는 직접 요청할 수 있습니다. 실행이 필요하고 재현 가능한 백엔드 요청으로 데이터를 얻을 수 없다면 렌더러를 사용해야 합니다.
Colly를 쓰려면 Go를 알아야 하나요?
네. Colly는 독립 실행형 CLI가 아니라 Go 라이브러리입니다. import하고, 콜백(OnHTML, OnResponse, OnError)을 등록한 뒤 컴파일해야 합니다. 내가 테스트한 머신에는 Go가 없었기 때문에, 설정은 Go 툴체인(1.26.5) 설치부터 시작했다. 팀이 이미 Go를 쓰고 있지 않다면, 그 환경이 실제 설정 비용이다.
내가 설치한 버전이 Colly의 최신 GitHub release와 왜 다르죠?
Go 모듈은 v2.3.0(2025년 12월)으로 해석되었지만, 확인 당시 최신 GitHub Release 항목은 v2.2.0(2025년 3월)이었다. 내가 테스트한 것은 v2.3.0이며, 이는 버전 표시 체계의 차이이지 설치 실패의 증거가 아니다.
Colly는 상업적으로 무료인가요?
네. Apache-2.0 라이선스이므로 관대한 편이고 상업적 사용에도 유리하다. 다만 실제로 사용하기 전에 항상 repo의 현재 라이선스를 확인하라.
프로덕션에 도입하기 전에는, fixture 결과를 단순 비유로 확장하지 말고 운영 리스크에 맞는 테스트를 추가해야 한다. 대표 대상에서 반복 크롤의 시간을 재고, CPU와 최대 메모리를 기록하고, 재시도 가능한 실패와 종료 실패를 모두 실행해 보며, 동시성 하에서 예의 정책이 지켜지는지 확인하라. 저장이 중요하다면 중복 처리와 큐 상태를 보면서 크롤을 중단하고 다시 시작해 보라. 배포 단순성이 중요하다면 정확한 컴파일러와 링커 설정을 기록하고 생성된 실행 파일의 런타임 의존성을 확인하라. 이런 점검은 현재 fixture가 보여준 사실을 바꾸지 않는다. 다만 같은 라이브러리 구성이 특정 프로덕션 작업에 맞는지 판단하게 해줄 뿐이다.


