Browsertrix Crawler는 Webrecorder의 아카이빙 크롤러입니다. 하나의 Docker 이미지가 실제 Chromium을 Puppeteer로 구동하고, 브라우저가 가져온 모든 것을 기록한 뒤 WARC(Web Archive의 표준 포맷)에 저장합니다. 필요하면 인덱스, 페이지 목록, 로그가 포함된 WACZ 패키지로도 묶을 수 있습니다. 이 도구가 겉보기엔 비슷해 보이는 스크래핑 도구들과 결정적으로 다른 점은 목적입니다. 스크래퍼는 데이터를 가져오고 필드를 뽑아낸 뒤 페이지를 버리지만, 아카이버는 방문 자체를 남깁니다. 즉, 바이트, 헤더, 도착 순서까지 보존해 사이트가 바뀌거나 사라진 뒤에도 페이지를 다시 열 수 있게 합니다. Webrecorder는 아카이빙이 하나의 제품군처럼 보이기 훨씬 전부터 이런 웹 인프라 계층, 포맷, 재생 스택을 꾸준히 유지해 왔고, 라이브러리·언론사·연구기관이 이를 실제로 사용하고 있습니다.
저는 v1.14.0을 Docker에서 실행해, 서로 성격이 다른 4개 엔드포인트 클래스를 담은 로컬 테스트 환경에 적용했습니다. 크롤링 양쪽 모두를 계측했는데, 아카이브 내용은 WARC 레코드로, 실제 요청은 서버 측 히트 카운터로 확인했습니다. 유용한 차이는 단순히 정적이냐 동적이냐가 아니었습니다. Browsertrix는 런타임에 생성된 링크와 페이지가 직접 호출한 fetch()는 포착했지만, 호출되지 않은 JavaScript 함수 안에 들어 있던 두 개의 URL 리터럴은 요청하지 않았습니다.
연결된 app.js는 두 개의 리터럴 경로를 포함해 전체가 그대로 아카이브되었지만, 해당 엔드포인트는 응답 레코드도, 요청 레코드도, 서버 히트도 남지 않았습니다. 그 함수를 실제로 실행하지 않았기 때문입니다. 따라서 이 글은 Browsertrix를 소스 코드에 등장하는 모든 URL 목록을 수집하는 도구가 아니라, 브라우저 세션을 아카이브하는 도구로 평가합니다.
Browsertrix Crawler는 실제로 무엇인가
많은 사람들이 스크래퍼를 기대하고 왔다가 실망합니다. 기본 파이프라인 어디에도 상품 가격 CSV를 바로 뽑아주는 기능은 없고, 그걸 기대하는 건 대시캠에 교통 보고서를 써달라는 것과 비슷합니다. 출력물은 다시 재생 가능한 브라우징 세션 기록이며, 이후의 모든 설계 결정은 이 사실에서 출발합니다.
저는 2026년 7월 27일에 v1.14.0을 테스트했습니다. webrecorder/browsertrix-crawler:latest 이미지의 digest는 sha256:9d6800a8…였고, crawl --version으로 빌드를 확인했습니다. 프로젝트 라이선스는 AGPL-3.0입니다. 모든 측정은 macOS arm64의 Colima 위 Docker 환경에서, 통제된 로컬 테스트 대상에 대해 수행했으며, 서버 측 카운터는 Browsertrix 로그와 아카이브 파싱과 별개인 증거를 제공했습니다.
AGPL-3.0는 따로 짚을 가치가 있습니다. 강한 카피레프트에 네트워크 사용 조건까지 붙습니다. Browsertrix Crawler를 독립 도구가 아니라 상용 제품 안에 넣을 생각이라면, 배포 전에 반드시 라이선스를 제대로 검토해야 합니다. 이건 경고이지 법률 자문은 아닙니다.
아카이브는 소스 코드가 아니라 세션을 기록한다
제가 만든 테스트 환경은 아카이버가 완전히 다르게 취급하는 4가지 엔드포인트를 의도적으로 분리해 제공했습니다.
- Class A — HTML 안의 일반
<a href>: 4개 페이지와 3단계 깊이 체인. 세상 어떤 크롤러라도 찾아냅니다. - Class B — 실행되지 않는 함수 안의 URL 리터럴:
/api/js-endpoint-7,/api/js-endpoint-8두 경로가 링크된app.js안의 호출되지 않는loadData()내부 문자열로 존재. - Class C — 런타임에 만들어진 링크: JavaScript에서 조각을 붙여 만든
<a href>('endpoint' + (6 * 7)), DOM에 추가됨. 연속 경로/runtime-only/endpoint42는 제공된 어떤 바이트에도 그대로 존재하지 않습니다. - Class D — 페이지가 실제로 발행한
fetch(): 같은 방식으로 경로를 조립 ('runtime-xhr-' + (33 * 3))한 뒤 로드 시 실제 요청.
Class C와 D의 경우, 완성된 경로 문자열은 제공된 파일의 연속 텍스트로 존재하지 않았습니다. 따라서 서버 측 히트와 응답 레코드는 이 테스트 환경에서 런타임 구성과 요청 경로가 실제로 실행되었음을 보여주는 증거입니다.
무엇이 잡혔고, 무엇이 빠졌나

두 도구를 모든 항목에서 서로 대조했습니다. WARC 응답 레코드(아카이브 안에 무엇이 들어 있는지)와 서버 측 히트 카운터 (Host header, path)(실제로 무엇이 요청되었는지)를 비교한 결과, 전 항목에서 일치했습니다.
| 엔드포인트 클래스 | WARC의 응답 레코드 | 실제로 가져옴(서버 측) | 판정 |
|---|---|---|---|
A — HTML <a href> | 4/4 | 4/4 | 포착 |
| A — 깊이 체인(3단계) | 3/3 | 3/3 | 포착 |
| B — 실행되지 않는 JS 안의 URL 리터럴 | 0/2 | 0/2 | 미포착 |
| C — 런타임에 주입된 링크 | 예 | 예 | 포착 |
D — 런타임 fetch() | 예 | 예 | 포착 |
Class C는 실제 브라우저와 정적 크롤러를 가르는 사례입니다. 기본 링크 추출은 렌더링된 DOM(a[href]->href, common options 문서 기준)을 읽기 때문에, JavaScript 실행 후에야 생기는 링크도 큐에 들어가고, 요청되고, 아카이브됩니다. Class D는 다른 이유로 잡힙니다. 페이지 자체가 요청을 보냈고, 아카이버는 네트워크 경로 위에서 그 흐름을 기록하고 있기 때문입니다.
Class C에 대해 하나 명확히 할 점이 있습니다. 제가 주입한 링크는 페이지 로드 시 동기적으로 삽입되었습니다. Browsertrix의 behaviors 도중 나중에 나타나는 링크는 별도의 경우이며, 정확히 그 상황에 대한 오픈 이슈가 있습니다 — #723, "Links on pages that are discovered during behaviors are not extracted". 저는 그 시나리오는 테스트하지 않았으므로, 그 부분에 대해선 어떤 주장도 하지 않습니다.
파일은 아카이브됐지만, 엔드포인트는 아니었다
Class B 누락을 확인하려면 단순 집계가 아니라 WARC 레코드를 레코드 단위로 살펴봐야 했습니다.
app.js는 아카이브에 있습니다 — 응답 레코드 1개, 222바이트짜리 JavaScript 본문이며, Class B의 두 리터럴도 그 안에 그대로 들어 있습니다. 반면 /api/js-endpoint-7과 /api/js-endpoint-8은 전체 파일 어디에서도 단 한 번도 레코드의 대상 URI가 되지 않았습니다. 응답 레코드 0개, 요청 레코드 0개입니다. 두 리터럴 문자열은 아카이브 전체에서 각각 정확히 한 번씩만 등장하며, 둘 다 app.js에 저장된 본문 안에 있습니다.
이로써 흔한 설명, 즉 “app.js가 아예 받아지지 않았다”는 가설은 배제됩니다. 아카이버는 그 엔드포인트를 참조하는 파일을 저장했지만, loadData()가 호출되지 않았기 때문에 해당 엔드포인트로는 요청을 보내지 않았습니다. Browsertrix의 기본 behaviors — autoplay, autofetch, autoscroll, siteSpecific — 는 켜져 있었지만, autofetch도 이 문제를 해결하지는 못했습니다. autofetch가 하는 일을 보면 납득이 됩니다. img의 srcset, 스타일시트, data-* URL을 따라가지만 함수 본문 속 문자열 리터럴까지는 추적하지 않기 때문입니다.
같은 테스트 환경에서 비교용으로 Katana v1.6.1도 katana -u <seed> -jc -silent -nc -d 4로 실행했습니다. 그 raw discovery summary는 의도적으로 만든 두 JavaScript 클래스에 대해 반대 결과를 기록합니다.
| 찾고자 하는 것 | Browsertrix v1.14.0 | Katana v1.6.1, 표준 -jc |
|---|---|---|
| 제공된 HTML의 링크 | 발견 | 발견 |
| 런타임에 DOM에 주입된 링크 | 발견(렌더링된 DOM 추출) | headless 모드 없이는 누락 |
페이지가 실제로 호출한 fetch() | 발견(트래픽으로 기록) | 누락 — 실행 자체가 없음 |
| 실행되지 않는 JS 안의 URL 리터럴 | 누락(0/2) | 발견(이 동일한 테스트 환경에서 2/2) |
| 그 리터럴을 포함한 JS 파일 | 전체 아카이브 | 파싱만 되고 보존되지는 않음 |
두 명령은 같은 테스트 환경과 엔드포인트 이름을 사용했습니다. 이 표는 브라우저 크롤러와 정적 크롤러의 일반적 서열을 매기는 것이 아니라, 엔드포인트 인벤토리와 세션 보존이 서로 다른 범위의 테스트를 필요로 한다는 점을 보여줍니다.
“실제 브라우저니까 JavaScript가 하는 건 다 잡는다”는 표현을 흔히 볼 수 있습니다. 하지만 과장입니다. 실행된 트래픽만 잡습니다. URL을 참조만 하고 실제 호출은 하지 않는 코드는 트래픽을 만들지 않고, 트래픽이 없으면 레코드도 없습니다.
재생용 본문은 존재하지만, 제가 확인하지 않은 것 하나
런타임에서 생성된 두 엔드포인트에 대해, 저는 WARC에서 아카이브된 HTTP 응답 본문을 꺼내 확인했고, 제공된 JSON이 들어 있음을 검증했습니다. 런타임 주입 링크 대상은 206바이트, 런타임 fetch() 대상은 201바이트였습니다. 즉, 이것들은 아무것도 가리키지 않는 인덱스 더미가 아니라, 실제 콘텐츠가 아카이브에 들어 있는 경우이며, 재생 시스템이 그걸 서빙하기 위한 전제 조건은 충족됩니다.
하지만 제가 하지 않은 것은 pywb나 replayweb.page를 띄워서 실제로 아카이브를 렌더링해 보는 일이었습니다. 아카이브 안에 본문이 있다는 주장과 재생 결과가 올바르다는 주장은 다른 이야기이며, 이번 테스트는 첫 번째만 다룹니다. 재생 동작, 진본성 제어, 증거 연속성, 법정 증거로서의 적합성은 별도의 검증이 필요합니다.
운영용 캡처에는 더 넓은 수용 테스트가 필요하다
이 테스트 환경은 좁은 질문에는 명확히 답합니다. 동기적 런타임 링크와 페이지가 발행한 요청이 네트워크 트래픽과 아카이브 레코드로 남았는가? 그러나 실제 보존 작업은 유효한 WACZ를 만들어내면서도 다른 방식으로 실패할 수 있습니다.
먼저 재생을 확인해야 합니다. 수집에 실제로 사용할 재생 시스템에서 패키지를 열고, 캡처 시점의 기준 페이지와 고정된 페이지 집합을 비교하세요. 렌더링된 텍스트, 이미지, 스타일, 탐색, 기록에 중요한 상호작용까지 점검해야 합니다. 그다음 재생 브라우저의 네트워크 패널에서 누락된 하위 리소스를 확인하세요. 응답 본문은 WARC에 존재하더라도, 재작성, 인덱스, 타이밍, 원본 출처, 의존성이 맞지 않으면 재생은 실패할 수 있습니다. 이번 리뷰는 그 경계까지는 확인하지 않았습니다.
동적 동작은 별도 테스트 세트가 필요합니다. 여기서 Class C 링크는 페이지 로드 중 동기적으로 나타났습니다. 실제 애플리케이션은 타이머, 스크롤, 동의 배너 해제, 라우트 변경, 커스텀 엘리먼트, 긴 API 체인 뒤에 콘텐츠를 드러낼 수 있습니다. 의존하는 각 동작 뒤에 하나씩 알려진 타깃을 심어 두고, 서버 히트와 아카이브된 본문 둘 다 확인하세요. Browsertrix의 기본 behaviors는 그 테스트에 유용한 입력이지, 모든 지연 상태에 도달했다는 증거는 아닙니다. 링크가 초기 페이지 실행이 아니라 behaviors 도중 나타난다면 #723가 특히 중요합니다.
인증이 필요한 캡처는 세션 관련 질문이 더해집니다. 로그인 상태가 브라우저 프로필에 제대로 들어가고, 필요한 탐색을 거쳐도 유지되며, 분리되어야 할 컬렉션으로 새지 않는지 확인해야 합니다. 토큰 갱신과 로그아웃 경로도 시험해야 합니다. 아카이브에 비공개 또는 개인정보가 포함된다면, 결과 파일에 대한 접근 제어와 보존 정책도 같은 수용 계획의 일부로 테스트해야 합니다. 기술적으로 완전한 캡처라도 수집 이후에 잘못 다뤄질 수 있습니다.
서비스 워커, 스트리밍 미디어, WebSocket, 다운로드, 교차 출처 프레임, 서명된 URL은 대상에 중요하다면 각각 대표 페이지가 필요합니다. 이 11페이지짜리 테스트 환경은 그들에 대해 아무 것도 말해주지 않습니다. 또한 페이지가 몇 분 동안 활성 상태를 유지하거나, 일반적인 안정화 창 이후에 요청을 내보내거나, 사용자 제스처를 요구할 때 크롤러가 어떻게 행동하는지도 증명하지 않습니다. “실제 Chromium”을 만능 커버리지 주장으로 바꾸지 마세요. 수집이 보존해야 하는 브라우저 동작을 정의하고, 각 동작을 관찰 가능하게 만들어야 합니다.
마지막으로, 누락 원인 분석에 필요한 증거를 보관하세요. 정확한 이미지 digest와 명령, Browsertrix 로그, 페이지 목록, 인덱스, WARC/WACZ 체크섬, 가능하다면 서버 측 요청 증거, 그리고 작은 기준 진실(manifest)을 저장해야 합니다. 반복 캡처라면 시간, 설정, 환경도 아티팩트와 함께 기록하세요. 이런 기록이 법적 증거능력을 만들어주지는 않지만, 기술적 주장을 재현 가능하게 하고 나중의 차이가 대상 때문인지, 크롤러 때문인지, 재생 스택 때문인지 드러내 줍니다.
이 작은 본문 테스트 환경에 든 바이트 비용
이 테스트 환경은 페이지당 몇 백 바이트만 제공하므로, 그 오버헤드 비율을 이미지가 많은 사이트에 그대로 적용해서는 안 됩니다. 이 제한된 범위 안에서는 최종 크기만이 아니라 아카이브의 구성도 측정했습니다.
| WARC 레코드 유형 | 개수 | 콘텐츠 바이트 | 비중 |
|---|---|---|---|
request | 14 | 6,912 | 40.6% |
response(실제 페이지 페이로드) | 13 | 5,339 | 31.4% |
resource(페이지당 하나의 urn:pageinfo: JSON) | 11 | 4,527 | 26.6% |
revisit(중복 제거된 죽은 링크) | 1 | 154 | 0.9% |
warcinfo | 1 | 92 | 0.5% |
| 총 레코드 콘텐츠 | 40 | 17,024 | 100% |
유형별 개수와 바이트 총계는 공개된
capture-summary.json에 있으며, 비중은 17,024바이트의 총 레코드 콘텐츠를 분모로 계산했습니다.
이 작은 본문 테스트에서는 요청 레코드가 응답 콘텐츠보다 더 많았고, 요청+urn:pageinfo: 바이트가 응답 페이로드의 약 2.1배였습니다. 이는 이 테스트 환경의 레코드 구성일 뿐, 일반적인 WARC 비율은 아닙니다.
디스크 기준으로는 세 번의 독립 실행에서 다음과 같았습니다.
| 지표 | 최소 | 중앙값 | 최대 |
|---|---|---|---|
| 크롤링 wall time(초) | 28.22 | 29.75 | 30.27 |
| WARC.gz 바이트 | 24,174 | 24,250 | 24,262 |
| WACZ 바이트 | 53,446 | 53,523 | 53,533 |
| 캡처된 응답 페이로드(바이트) | 5,339 | 5,339 | 5,339 |
중앙값 기준으로 보면 여기서 네 가지 비율이 나옵니다.
| 파생 지표(중앙값) | 값 |
|---|---|
| 압축 WARC vs. 캡처된 응답 페이로드 | 4.5× |
| WACZ vs. 캡처된 응답 페이로드 | 10× |
| 페이지당 WARC | ~2.2 KB |
| 페이지당 WACZ | ~4.9 KB |
WACZ 내부를 보면:
| WACZ 구성 요소 | 번들 내 비중 |
|---|---|
| WARC | 45% |
| CDX 인덱스 | 16% |
| 크롤 로그 | 30% |
마지막 줄이 특히 놀라웠습니다. 작은 크롤에서는 아카이브 패키지의 거의 3분의 1이 웹이 아니라 크롤 자체의 기록입니다.
측정은 안정적이었습니다. 응답 페이로드는 세 번 모두 바이트가 완전히 동일했고(항상 5,339B), WARC.gz와 WACZ는 0.4% 미만으로만 변동했습니다.
이 비율을 실제 이미지, 폰트, 대형 스크립트 번들이 있는 페이지에 그대로 적용할 수는 없습니다. 그러나 구조적 의미는 분명합니다. 요청 레코드와 page-info 레코드는 페이로드 크기와 무관한 오버헤드를 만듭니다. 운영용 저장소를 계획하기 전에 대표 샘플을 먼저 측정해야지, 이 테스트 환경의 10배 비율에 코퍼스 추정치를 곱해서는 안 됩니다.
설정과, 미리 잡아야 할 디스크 용량
Docker나 Colima가 설치되어 실행 중이라면, Browsertrix 관련 설정은 docker pull webrecorder/browsertrix-crawler:latest 다음 docker run … crawl --url … --generateWACZ 정도로 끝납니다. 이미지 안에 Chromium이 들어 있으므로 별도의 브라우저나 Python 환경은 필요하지 않았습니다.
이 편의성의 비용은 이번 측정에서 다음과 같았습니다.
| 예산을 잡아야 하는 항목 | 측정값 |
|---|---|
| 이미지 다운로드 | 약 1 GB |
| 디스크 압축 해제 후 이미지 크기 | 3.51 GB |
몇 KB 규모 콘텐츠를 제공하는 테스트 환경에서 11페이지 실행을 몇 차례 돌린 뒤의 crawls/ 트리(WARC, WACZ, 브라우저 프로필 데이터) | 약 116 MB |
| 11페이지 테스트 환경 크롤링 wall clock | 28–30초 |
컨테이너가 실제 부담을 지는 곳이고, 다운로드 후 압축 해제 크기가 브라우저 번들링의 대가입니다. 저는 --shm-size 1g로 실행했고, 테스트 환경은 호스트에 있었지만 크롤은 컨테이너 안에서 돌아갔기 때문에 --add-host=host.docker.internal:host-gateway와 0.0.0.0 바인딩이 필요했습니다. 공개 인터넷을 크롤링한다면 이 네트워킹 단계는 필요 없겠지만, 로컬 머신이나 내부 스테이징 호스트를 아카이브한다면 반나절은 잡아야 합니다.
출력 디렉터리는 가장 과소평가하기 쉬운 항목입니다. 실제 크롤에 이 증가분을 그대로 적용해, 새벽 3시에 디스크가 꽉 차고 나서가 아니라 시작하기 전에 저장 공간을 계획하세요.
11페이지짜리 크롤에 28~30초가 걸린 데는 브라우저 시작 시간이 적지 않게 기여했을 가능성이 큽니다. 다만 저는 시작 시간과 탐색·패키징 시간을 분리하지 않았습니다. 이 실행만으로 페이지당 처리량에 관한 결론은 낼 수 없습니다.
테스트 환경 비율을 남용하지 않고 저장 공간 계획하기
컬렉션 크기를 잡는 올바른 방법은 경험적 측정입니다. 대상의 실제 분포를 대표하는 페이지를 골라야 합니다. 예를 들면 얇은 앱 셸, 이미지가 많은 랜딩 페이지, 문서 다운로드, 긴 기사, 인증이 필요한 뷰 등을 포함할 수 있습니다. 범위에 들어간다면 각 유형을 의도한 behaviors와 패키징 설정으로 캡처하세요. 응답 페이로드, WARC, WACZ, 인덱스, 로그, 브라우저 프로필 찌꺼기, 실행 중 남는 임시 작업 공간을 측정해야 합니다. 패키징이 잠깐 여러 복사본을 유지한다면 최종 번들만큼이나 최대 디스크 사용량도 중요합니다.
고정 요소와 가변 요소를 분리하세요. 3.51GB의 컨테이너 이미지는 배포 오버헤드이며, 한 워커에서 여러 캡처가 공유할 수 있습니다. 요청 레코드, page-info 레코드, 인덱스, 페이지 목록은 크롤 활동에 따라 늘어납니다. 응답 본문은 대상에 크게 좌우되고, 로그는 실행 시간과 상세도에 따라 달라집니다. 그다음 보존과 복제는 크롤 동작과 별개로 최종 컬렉션을 다시 곱합니다. 이 모든 것을 “페이지당 바이트” 하나로 묶은 용량 모델은 쉽게 깨집니다.
압축과 중복 제거 역시 대표성 있는 콘텐츠가 필요합니다. 이 테스트 환경의 응답 페이로드는 세 번 모두 바이트가 완전히 같았지만, 광고·타임스탬프·개인화 응답·캐시 무효화 자산 URL이 바뀌는 페이지를 설명해주지는 않습니다. 반복 캡처가 프로그램의 일부라면 같은 페이지를 연속으로 캡처해 revisit 레코드를 확인해야지, 겉보기만 같은 페이지가 잘 중복 제거된다고 가정하면 안 됩니다. 마찬가지로 로그와 인덱스가 보존 페이로드와 같은 복제 수준으로 유지되는지도 확인해야 합니다.
운영 관점에서는 컬렉션 시작 전에 경고 임계값을 정하세요. 남은 디스크 공간, 컬렉션별 성장률, 패키징 실패, 브라우저 프로필이나 임시 디렉터리 크기를 모니터링해야 합니다. 체크섬 확인만 하지 말고 저장된 WACZ에서 복원 테스트도 수행하세요. 위 비율이 유용한 이유는 어떤 구성 요소가 존재하는지 보여주기 때문이고, 실제 크기는 대표 샘플이 알려줍니다.
이런 가정들을 용량 추정 옆에 문서화하고, 파일럿 크롤 후 다시 검토하세요.
두 개의 제어군으로 확인한 스코프 규율
범위를 벗어나 돌아다니는 아카이빙 크롤러는 실제 운영상 위험입니다. 법적 문제와 저장 비용이 동시에 생길 수 있습니다. 제 홈 페이지는 http://outofscope.test:<port>/page/out 링크를 포함하고 있었는데, 이는 같은 테스트 환경을 가리키는 다른 호스트명입니다. 따라서 그 Host header로 히트가 잡히면, 실제 인터넷 트래픽 없이도 범위를 벗어난 fetch가 발생했다는 뜻입니다.
| 설정 | 범위 밖 호스트를 fetch했는가? | 서버 측 히트 |
|---|---|---|
--scopeType prefix(기본) | 아니오 | 0 |
--scopeType any | 예 | 2 |
두 번째 줄이 있어야 첫 번째 줄이 의미를 가집니다. any에서는 링크가 두 번 도달되었으므로 실제로 접근 가능했고, 기본 prefix 스코프에서 0이 나온 것은 크롤러가 링크를 못 본 게 아니라 진짜 규율이 적용된 결과입니다. 다른 설정에서 범위 밖 방문이 발생했다는 오픈 리포트 #788가 있지만, 저는 이 테스트 환경의 기본 prefix 스코프에서는 재현하지 못했습니다. 존재한다는 점은 알 만하지만, 제가 봤다고 주장할 정도는 아닙니다.
안정성은 좋은 의미로 특이할 게 없었습니다. HTTP 500을 반환하는 경로와 죽은 링크가 모두 요청되었고, 크롤은 유효한 WARC와 WACZ를 남긴 채 깔끔하게 종료됐으며, 죽은 링크는 아무 것도 망가뜨리지 않고 중복 제거된 revisit 레코드로 저장되었습니다.
장점과 단점
장점
- 런타임에 주입된 DOM 링크와 페이지가 발행한
fetch()를 포착함 — 둘 다 아카이브와 서버 측에서 모두 확인됐고, 해당 경로는 어떤 리터럴로도 존재하지 않음. - 정적 HTML과 깊이 탐색은 완전함: 링크 4/4, 깊이 체인 3/3, 누락 없음.
- Docker/Colima가 돌아가면
docker run한 번으로 WARC와 WACZ가 생성되며, Chromium은 이미지 안에 포함됨. - 기본
prefix스코프는 범위 밖 fetch 0건으로 유지되었고,any는 문서대로 범위를 넓혔으므로 설정이 설명대로 동작함. - 출력물이 WARC, CDX 인덱스, 페이지 목록을 포함한 표준 기반 아카이브(WACZ로 묶임)이지, 독점 바이너리가 아님.
- 아카이브가 거의 결정론적임: 세 번 실행해도 페이로드 바이트는 동일했고, 디스크 크기 변동은 0.4% 미만.
- 실패 처리도 깔끔함: 500 경로와 깨진 링크가 크롤을 중단시키지 않음.
단점
- 실행되지 않은 JavaScript 안의 URL 리터럴은 아예 발견하지 못함(0/2). 그 리터럴이 들어 있는 파일이 아카이브되더라도 마찬가지입니다. 설계상 맞는 동작이지만, 엔드포인트 발견이 목적이라면 실제 커버리지 공백입니다.
- 무거운 풋프린트: 약 1GB 다운로드, 3.51GB 디스크 사용, 그리고 빠르게 커지는 출력 디렉터리.
- 작은 페이지에서는 바이트 오버헤드가 꽤 큼 — 요청과 pageinfo 레코드가 실제 페이로드보다 많았고, WACZ의 약 30%가 크롤 로그였음.
- AGPL-3.0는 상용 내장 시 실질적인 컴플라이언스 작업을 요구함.
- 구조화 데이터 도구가 아님. 스키마도 없고, 필드 매핑도 없고, 끝에 깔끔한 행도 없음.
- 모든 페이지가 실제 브라우저를 통과하므로 페이지당 처리량은 설계상 제한적임.
누가 써야 하고, 누가 쓰지 말아야 하나
Browsertrix는 필요한 산출물이 추출된 행이 아니라 브라우저가 가져온 리소스의 아카이브인 팀을 위한 도구입니다. 이 테스트 환경에서는 런타임 fetch 응답 본문이 WARC에 들어 있고 WACZ로 패키징되었습니다. 라이브러리, 언론사, 연구자는 충분히 가능한 사용자이지만, 실제 도입 전에는 렌더링 재생, 인증, 서비스 워커, 동의 플로우, 지연 동작, 스트리밍 자산, 보존 제어, 그리고 증거 처리 요구사항을 별도로 테스트해야 합니다.
실제로 필요한 것이 데이터라면 건너뛰세요. 목표가 “이 400개 페이지에서 상품과 가격을 전부 스프레드시트로 뽑아 달라”라면 아카이버는 이상한 우회로입니다. 수 GB를 아카이브한 뒤에도 결국 WARC 파일을 대상으로 추출 코드를 다시 짜야 할 수 있습니다. 애플리케이션의 API 표면을 매핑하려는 경우도 마찬가지입니다. 앞선 Class B 결과가 보여주듯, 정적 JavaScript 파서는 Browsertrix가 건드리지 않는 엔드포인트를 찾아낼 수 있습니다. 그리고 Docker를 싫어하거나 3.5GB 이미지가 부담되는 환경이라면, 이 도구는 당신 쪽에 맞춰 휘어지지 않습니다.
승인과 보존
스코프 제어는 승인을 대신하지 않습니다. 크롤링 전에 허용된 호스트, 보존 기간, 아카이브 접근 권한을 정의하세요. 특히 영속적 캡처에 개인정보가 포함될 수 있다면 더 중요합니다. prefix/any 테스트는 설정이 네트워크 도달 범위를 바꾼다는 점만 보여줄 뿐, 특정 컬렉션에서 어떤 도달 범위가 합법인지 말해주지는 않습니다.
관련 리뷰: 웹 스크래핑과 아카이빙의 법적 쟁점.
필요한 출력물 기준의 대안
산출물 기준으로 고르세요. Browsertrix는 WARC/WACZ 보존을 목표로 합니다. Playwright 같은 브라우저 자동화 라이브러리는 프로그램으로 제어되는 페이지를 제공하지만 캡처 패키징은 직접 해야 합니다. 엔드포인트 발견 크롤러는 URL을 열거하고, 추출 도구는 텍스트나 구조화된 레코드를 반환합니다. 이 범주들은 같은 브라우저를 공유할 수 있어도 해결하는 일은 서로 다릅니다.
관련 리뷰: Heritrix 리뷰.
공개 고지: Thunderbit는 발행사의 제품이며, 이 Browsertrix 테스트 환경에서는 평가하지 않았습니다. Thunderbit은 관리형 추출 범주에 속하며, 표준 기반 아카이브가 아니라 페이지 텍스트 또는 구조화 데이터를 생성합니다. 이 리뷰는 출력 경계만 다루며, 성능이나 기능 비교 주장은 포함하지 않습니다.
결론
필요한 결과물이 WARC/WACZ 캡처이고, 컨테이너화된 Chromium이 배포 방식에 맞는다면 Browsertrix Crawler를 사용하세요. 이번 테스트 환경에서는 동기적 런타임 DOM과 페이지 발행 fetch에 대해 아카이브 레코드와 서버 히트가 일치했고, 기본 prefix 스코프는 두 번째 호스트를 제외했으며, 실패 경로가 유효한 아카이브 생성을 막지 않았습니다.
실제 도입 전에 재생, 지연 동작, 인증 세션, 서비스 워커, 대표 페이지의 저장 구성, 라이선스 의무를 검증해야 합니다. 이번 테스트로 확인한 범위는 더 좁습니다. 실행되지 않는 코드 참조는 대상에 대한 요청도, 아카이브 레코드도 만들지 않았습니다. 해당 스크립트 자체는 보존되었지만 말입니다.
웹 데이터 추출용 Thunderbit 사용해 보기 Get Started Free
FAQ
여기서 WARC와 WACZ의 차이는 무엇인가요?
WARC에는 캡처된 요청, 응답, 관련 레코드가 들어 있습니다. WACZ는 배포와 재생 도구를 위해 WARC에 인덱스, 페이지 목록, 메타데이터, 로그를 함께 묶은 패키지입니다. 이 리뷰는 두 패키지 모두 살펴봤지만, 실제 재생 렌더링은 하지 않았습니다.
저장 공간은 어떻게 추정해야 하나요?
대표적인 페이지를 측정하고, 샘플에는 로그와 인덱스를 포함한 전체 WACZ 구성을 그대로 반영하세요. 이 글의 비율은 매우 작은 응답 본문을 기준으로 한 것이므로, 운영 URL 개수에 단순 곱하기에는 적합하지 않습니다.
제가 가리킨 사이트 밖으로 벗어나 돌아다니나요?
제 테스트에서는 기본 설정에서는 그렇지 않았습니다. --scopeType prefix에서는 다른 호스트의 링크가 한 번도 fetch되지 않았고, --scopeType any로 바꾸자 두 번 fetch되어 링크가 실제로 도달 가능했음이 확인됐습니다. 따라서 기본값에서 0이 나온 것은 진짜 스코프 규율입니다. 다만 다른 설정에서 범위 밖 방문이 있었다는 상위 이슈가 공개되어 있으므로, 자신의 스코프 설정을 직접 확인해야 합니다.
재생 fidelity를 주장하기 전에 무엇을 테스트해야 하나요?
WACZ를 실제 사용할 재생 시스템에 올리고, 렌더링된 페이지, 상호작용, 필요한 하위 리소스를 라이브 또는 기준 캡처와 비교하세요. WARC에 본문이 존재하는 것은 필요조건이지만, 그것만으로 재생이 올바르다고 증명되지는 않습니다.
Browsertrix가 아카이브된 페이지를 구조화된 행으로 바꿔 주나요?
아니요. 출력은 아카이브 패키지이지, 선택한 필드의 표가 아닙니다. 결과물이 상품, 가격, 연락처, 또는 다른 스키마라면 캡처 후에도 추출 단계를 추가해야 하거나, 처음부터 구조화 데이터를 주요 출력으로 삼는 다른 도구를 써야 합니다.


