AI 에이전트가 웹사이트의 몇 번 클릭 깊이에 있는 답변이 필요할 때, 이를 얻는 일반적인 방법은 두 가지가 있습니다.
- 모든 것을 덤프(Dump everything)하기. 크롤러가 많은 페이지를 가져오고 에이전트의 LLM이 그 모든 내용을 읽습니다. 이는 느리고 토큰 비용이 많이 들며, 답변이 탐색 메뉴에 파묻히게 됩니다.
- LLM에게 모든 링크 선택을 맡기기. 이 방법도 작동하지만, 각 단계가 LLM 호출(call)입니다. 제가 측정한 벤치마크에서는 질문당 약 $0.19의 비용이 들고 1분이 소요되었습니다.
저는 두 번째 옵션의 정확도를 유지하면서 첫 번째 옵션에 가까운 가격을 원했습니다. 그래서 저는 jevcrawl이라는 오픈소스(Apache-2.0) MCP 서버 및 CLI를 구축했습니다. 여기서는 작은 스코어링 모델이 크롤링을 주도하며 크롤링 루프 안에 LLM이 존재하지 않습니다.
작동 방식
질문과 시작 URL을 제공하면 됩니다. 이 크롤러는 필요한 최소한의 페이지를 가져와 질문에 답하는 구절만 원본 그대로 복사하여 해당 출처 URL과 함께 반환합니다.
uvx jevcrawl crawl https://docs.python.org/3/ \
--goal "What does the walrus operator := do and which Python version added it?"
이 예시에서 6개의 페이지를 가져왔고, 약 80,000 토큰의 페이지 텍스트를 약 1,900 토큰의 답변으로 줄였습니다. 이는 11번의 스코어링 호출만 필요했고, 비용은 약 $0.007에 불과했으며, 8초 만에 완료되었습니다.
작동 원리
결정은 TypeSafe의 작은 모델인 Jev가 내립니다. 이 모델은 확률을 기반으로 예/아니오 질문에만 답합니다. jevcrawl은 각 페이지에 대해 다음과 같은 요청을 보냅니다:
- 모든 텍스트 블록에 대해 "이 구절이 목표와 관련성이 있습니까?"
- 모든 링크에 대해 "이 링크가 답변으로 이어집니까?"
나머지 작업은 일반 코드가 처리합니다. 높은 점수를 받은 구절을 유지하고, 링크를 우선순위에 따라 정렬하며, 마지막으로 유지된 구절들이 이미 목표에 답하는지 여부를 한 번 더 질문하여 조기에 중단할 수 있도록 합니다.
모델이 숫자만 반환하기 때문에 텍스트를 지어낼 수 없고, 페이지가 모델에게 명령을 내릴 수도 없습니다. 최악의 경우, 프롬프트 주입(prompt-injection) 시도가 점수에 편향성을 가져옵니다.
몇 가지 세부 사항들이 중요하게 작용했습니다:
- 사이트맵 시딩(Sitemap seeding). 페이지 예산이 적은 대형 사이트의 경우, jevcrawl은
robots.txt Sitemap 라인에서 사이트맵(gzip 파일 및 사이트맵 인덱스 포함)을 읽어 목표 단어와 얼마나 중복되는지에 따라 항목들의 순위를 매깁니다.
- 약한 링크를 위한 예비 공간(A reserve for weak links). 우선순위 하한선(priority floor) 미만의 링크는 버려지는 대신 예비 대기열(reserve queue)로 이동하여, 좋은 링크가 고갈될 경우 크롤러가 다시 돌아와 처리할 수 있게 합니다.
- 페이지 전반의 정형 콘텐츠 감지(Boilerplate detection across pages). 메뉴와 푸터는 링크 후보로는 유지되지만 텍스트로는 반환되지 않습니다.
벤치마크(Benchmark)
저는 실제 웹사이트에서 여러 클릭을 거쳐 깊숙이 숨겨진 질문들을 다루는 벤치마크인 WebWalkerQA (Wu 등, Alibaba Tongyi Lab, ACL 2025)를 사용했습니다. 저는 라이브 사이트에서 50개의 작업을 재검증했으며 개발 과정에서는 이 작업들을 보지 않았습니다. 모든 시스템은 동일한 답변 LLM과 동일한 심사관(judge)을 사용했습니다.
| 시스템 | 정답률 (Correct) | 답이 있는 페이지 발견율 (Found answer page) | 태스크당 비용 (Cost per task) | 태스크당 시간 (Time per task) |
|---|
| jevcrawl | 40% | 54% | $0.025 | 27.5 s |
| ... | | | | |
| 저는 또한 LLM이 없는 키워드 점수 기반의 크롤러인 Crawl4AI의 최고 우선순위 심층 크롤링(best-first deep crawl)과 비교했습니다. 다른 20개 태스크에서, 크롤러가 답 페이지를 가져왔는지 여부만을 측정했을 때, jevcrawl은 20개 중 10개에서 이를 달성했고 Crawl4AI는 20개 중 5개에서 이를 달성했습니다. 중앙값 시간은 각각 29초와 43초였습니다. | | | | |
이것들은 작은 샘플(50개 및 20개 태스크)입니다. 저는 정확도 격차보다 비용 격차를 더 신뢰하며, Crawl4AI 테스트는 최종 답변이 아닌 페이지 도달 여부를 측정합니다. 벤치마크 코드는 리포지토리의 bench/ 폴더에 있으니 실행하거나 직접 태스크를 시도해 볼 수 있습니다.
제한 사항 (Limits)
- JavaScript 렌더링 미지원. JS로만 렌더링되는 페이지는
stats.needs_js_urls에 보고되며 건너뜁니다. Crawl4AI는 실제 브라우저를 구동하여 이를 처리합니다. 선택적 렌더링은 열린 이슈(open issue)입니다.
robots.txt 강제 적용 미지원. 현재는 사이트맵 라인에 대해서만 robots.txt를 읽습니다. 열린 이슈(Open issue)가 있습니다.
- 호스팅된 모델 의존성. 점수 측정은 TypeSafe의 Jev API를 통해 이루어지므로, API 키가 필요하며 페이지 텍스트는 점수 측정을 위해 TypeSafe로 전송됩니다. 크롤링 한 번에 약 1센트의 Jev 호출 비용이 발생합니다. 크롤러 자체는 무료 오픈 소스입니다. 저는 TypeSafe와 제휴 관계가 없습니다.
사용해 보기 (Try it)
Claude Code의 경우:
claude mcp add jevcrawl -e TYPESAFE_API_KEY=<your key> -- uvx jevcrawl
표준 mcpServers 항목을 통해 Claude Desktop과 Cursor에서도 작동합니다. README에 JSON이 있습니다.
리포지토리는 github.com/RayenMlayeh/jevcrawl입니다. 현재 몇 가지 좋은 첫 이슈(good-first-issues)가 열려 있습니다: robots.txt 지원, Dockerfile, Windows 및 macOS CI 등입니다.
어떤 사이트에서 성능이 떨어지는지 알고 싶습니다. 댓글로 알려주시거나, URL과 질문을 포함하여 이슈를 열어주세요.