웹 검색 및 스크래핑 도구
학습 후 할 수 있는 것
- web_search 도구를 구성하여 AI 어시스턴트가 Brave Search 또는 Perplexity Sonar를 사용하여 웹 검색을 수행할 수 있도록 합니다
- web_fetch 도구를 구성하여 AI 어시스턴트가 웹 페이지 콘텐츠를 스크래핑하고 추출할 수 있도록 합니다
- 두 도구의 차이점과 사용 시나리오를 이해합니다
- API 키 및 고급 매개변수(지역, 언어, 캐시 시간 등)를 구성합니다
- 일반적인 문제(API 키 오류, 스크래핑 실패, 캐시 문제 등)를 해결합니다
현재 문제
AI 어시스턴트의 지식 베이스는 정적이며 실시간 웹 정보에 액세스할 수 없습니다:
- AI는 오늘 발생한 뉴스를 알지 못합니다
- AI는 최신 API 문서나 기술 블로그를 검색할 수 없습니다
- AI는 특정 웹사이트의 최신 콘텐츠를 검색할 수 없습니다
AI 어시스턴트를 "인터넷 연결"하게 하고 싶지만 다음을 모릅니다:
- Brave와 Perplexity 중 어떤 것을 사용해야 할까요?
- API 키는 어디서 얻습니까? 어떻게 구성합니까?
- web_search와 web_fetch의 차이점은 무엇입니까?
- 동적 웹페이지나 로그인이 필요한 사이트를 어떻게 처리합니까?
언제 사용합니까
- web_search: 정보의 빠른 검색, 여러 웹사이트 검색, 실시간 데이터(뉴스, 가격, 날씨 등) 가져오기가 필요할 때
- web_fetch: 특정 웹페이지의 전체 콘텐츠 추출, 문서 페이지 읽기, 블로그 게시물 분석이 필요할 때
도구 선택 가이드
| 시나리오 | 권장 도구 | 이유 |
|---|---|---|
| 여러 소스 검색 | web_search | 하나의 쿼리로 여러 결과 반환 |
| 단일 페이지 콘텐츠 추출 | web_fetch | 전체 텍스트 가져오기, Markdown 지원 |
| 동적 페이지/로그인 필요 | browser | JavaScript 실행 필요 |
| 간단한 정적 페이지 | web_fetch | 가볍고 빠름 |
🎒 시작 전 준비
전제 조건
이 튜토리얼에서는 빠른 시작을 완료하고 Gateway가 설치되어 시작되었다고 가정합니다.
- Gateway 데몬이 실행 중
- 기본 채널 구성 완료(최소 하나의 사용 가능한 통신 채널)
- 최소 하나의 검색 제공자 API 키 준비 완료(Brave 또는 Perplexity/OpenRouter)
참고
web_search와 web_fetch는 경량 도구이며 JavaScript를 실행하지 않습니다. 로그인이 필요한 웹사이트나 복잡한 동적 페이지의 경우 browser 도구를 사용하세요.
핵심 개념
두 도구의 차이점
web_search: 웹 검색 도구
- 검색 엔진(Brave 또는 Perplexity)을 호출하여 검색 결과를 반환
- Brave: 구조화된 결과(제목, URL, 설명, 게시 시간)를 반환
- Perplexity: AI가 합성한 답변과 인용 링크를 반환
web_fetch: 웹페이지 콘텐츠 스크래핑 도구
- 지정된 URL에 HTTP GET 요청 전송
- Readability 알고리즘을 사용하여 주요 콘텐츠 추출(탐색, 광고 등 제거)
- HTML을 Markdown 또는 일반 텍스트로 변환
- JavaScript 실행하지 않음
왜 두 도구가 필요한가요?
┌─────────────────┐ web_search ┌──────────────────┐
│ 사용자가 AI에 질문 │ ──────────────────→ │ 검색 엔진 API │
│ "최신 뉴스" │ │ (Brave/Perplexity) │
└─────────────────┘ └──────────────────┘
↓ ↓
AI가 5개 결과 가져오기 검색 결과 반환
↓
┌─────────────────┐ web_fetch ┌──────────────────┐
│ AI가 결과 선택 │ ──────────────────→ │ 대상 웹페이지 │
│ "링크 1 열기" │ │ (HTTP/HTTPS) │
└─────────────────┘ └──────────────────┘
↓ ↓
AI가 전체 콘텐츠 가져오기 Markdown 추출일반적인 워크플로우:
- AI가 web_search를 사용하여 관련 정보 검색
- AI가 검색 결과에서 적절한 링크 선택
- AI가 web_fetch를 사용하여 특정 페이지 콘텐츠 스크래핑
- AI가 콘텐츠를 기반으로 사용자 질문에 답변
캐싱 메커니즘
두 도구 모두 중복 요청을 줄이기 위해 내장 캐시를 제공합니다:
| 도구 | 캐시 키 | 기본 TTL | 구성 항목 |
|---|---|---|---|
| web_search | provider:query:count:country:search_lang:ui_lang:freshness | 15분 | tools.web.search.cacheTtlMinutes |
| web_fetch | fetch:url:extractMode:maxChars | 15분 | tools.web.fetch.cacheTtlMinutes |
캐싱의 이점
- 외부 API 호출 횟수 감소(비용 절감)
- 응답 속도 향상(동일한 쿼리는 캐시에서 반환)
- 빈번한 요청으로 인한 속도 제한 방지
따라해 보세요
1단계: 검색 제공자 선택
Clawdbot은 두 가지 검색 제공자를 지원합니다:
| 제공자 | 장점 | 단점 | API 키 |
|---|---|---|---|
| Brave(기본값) | 빠름, 구조화된 결과, 무료 계층 | 기존 검색 결과 | BRAVE_API_KEY |
| Perplexity | AI 합성 답변, 인용, 실시간 | Perplexity 또는 OpenRouter 액세스 필요 | OPENROUTER_API_KEY 또는 PERPLEXITY_API_KEY |
권장 선택
- 초보자: Brave 사용 권장(무료 계층으로 일상 사용에 충분)
- AI 요약 필요: Perplexity 선택(원시 결과가 아닌 합성된 답변 반환)
2단계: Brave Search API 키 가져오기
Brave를 사용하는 이유: 관대한 무료 계층, 빠른 속도, 구조화된 결과로 구현하기 쉬움
2.1 Brave Search API 등록
- https://brave.com/search/api/ 방문
- 계정 생성 및 로그인
- Dashboard에서 "Data for Search" 계획 선택("Data for AI"가 아님)
- API 키 생성
2.2 API 키 구성
방법 A: CLI 사용(권장)
# 대화형 구성 마법사 실행
clawdbot configure --section webCLI는 API 키 입력을 요청하고 ~/.clawdbot/clawdbot.json에 저장합니다.
방법 B: 환경 변수 사용
API 키를 Gateway 프로세스의 환경 변수에 추가:
# ~/.clawdbot/.env에 추가
echo "BRAVE_API_KEY=당신의API키" >> ~/.clawdbot/.env
# Gateway 재시작으로 환경 변수 적용
clawdbot gateway restart방법 C: 구성 파일 직접 편집
~/.clawdbot/clawdbot.json 편집:
{
"tools": {
"web": {
"search": {
"apiKey": "BRAVE_API_KEY_HERE",
"provider": "brave"
}
}
}
}예상 결과:
- 구성 저장 후 Gateway 재시작
- 구성된 채널(WhatsApp 등)에서 메시지 전송: "최신 AI 뉴스 검색해줘"
- AI가 검색 결과를 반환해야 함(제목, URL, 설명)
3단계: web_search 고급 매개변수 구성
~/.clawdbot/clawdbot.json에서 더 많은 매개변수를 구성할 수 있습니다:
{
"tools": {
"web": {
"search": {
"enabled": true, // 활성화 여부(기본값 true)
"provider": "brave", // 검색 제공자
"apiKey": "BRAVE_API_KEY_HERE",
"maxResults": 5, // 반환 결과 수(1-10, 기본값 5)
"timeoutSeconds": 30, // 타임아웃 시간(기본값 30)
"cacheTtlMinutes": 15 // 캐시 시간(기본값 15분)
}
}
}
}3.1 지역 및 언어 구성
검색 결과를 더 정확하게:
{
"tools": {
"web": {
"search": {
"provider": "brave",
"apiKey": "BRAVE_API_KEY_HERE",
"maxResults": 10,
// 선택사항: AI가 호출 시 이 값을 재정의 가능
"defaultCountry": "US", // 기본 국가(2자 코드)
"defaultSearchLang": "en", // 검색 결과 언어
"defaultUiLang": "en" // UI 요소 언어
}
}
}
}일반적인 국가 코드: US(미국), DE(독일), FR(프랑스), CN(중국), JP(일본), ALL(전 세계)
일반적인 언어 코드: en(영어), zh(중국어), fr(프랑스어), de(독일어), es(스페인어)
3.2 시간 필터 구성(Brave 전용)
{
"tools": {
"web": {
"search": {
"provider": "brave",
"apiKey": "BRAVE_API_KEY_HERE",
// 선택사항: AI가 호출 시 재정의 가능
"defaultFreshness": "pw" // 지난 1주일 결과 필터링
}
}
}
}Freshness 값:
pd: 지난 24시간pw: 지난 1주일pm: 지난 1개월py: 지난 1년YYYY-MM-DDtoYYYY-MM-DD: 사용자 지정 날짜 범위(예:2024-01-01to2024-12-31)
4단계: Perplexity Sonar 구성(선택사항)
AI 합성 답변을 선호하는 경우 Perplexity를 사용할 수 있습니다.
4.1 API 키 가져오기
방법 A: Perplexity 직접 연결
- https://www.perplexity.ai/ 방문
- 계정 생성 및 구독
- Settings에서 API 키 생성(
pplx-로 시작)
방법 B: OpenRouter 통해서(신용카드 불필요)
- https://openrouter.ai/ 방문
- 계정 생성 및 충전(암호화폐 또는 선불 지원)
- API 키 생성(
sk-or-v1-로 시작)
4.2 Perplexity 구성
~/.clawdbot/clawdbot.json 편집:
{
"tools": {
"web": {
"search": {
"enabled": true,
"provider": "perplexity",
"perplexity": {
// API 키(선택사항, 환경 변수로도 설정 가능)
"apiKey": "sk-or-v1-...", // 또는 "pplx-..."
// Base URL(선택사항, Clawdbot은 API 키에 따라 자동 추론)
"baseUrl": "https://openrouter.ai/api/v1", // 또는 "https://api.perplexity.ai"
// 모델(기본값 perplexity/sonar-pro)
"model": "perplexity/sonar-pro"
}
}
}
}
}Base URL 자동 추론
baseUrl을 생략하면 Clawdbot은 API 키 접두사에 따라 자동으로 선택:
pplx-...→https://api.perplexity.aisk-or-...→https://openrouter.ai/api/v1
4.3 Perplexity 모델 선택
| 모델 | 설명 | 적용 시나리오 |
|---|---|---|
perplexity/sonar | 빠른 Q&A + 웹 검색 | 간단한 쿼리, 빠른 검색 |
perplexity/sonar-pro(기본값) | 다단계 추론 + 웹 검색 | 복잡한 문제, 추론 필요 |
perplexity/sonar-reasoning-pro | 사고 체인 분석 | 심층 연구, 추론 프로세스 필요 |
5단계: web_fetch 도구 구성
web_fetch는 기본적으로 활성화되어 있으며 추가 구성 없이 사용할 수 있습니다. 매개변수를 조정할 수 있습니다:
{
"tools": {
"web": {
"fetch": {
"enabled": true, // 활성화 여부(기본값 true)
"maxChars": 50000, // 최대 문자 수(기본값 50000)
"timeoutSeconds": 30, // 타임아웃 시간(기본값 30)
"cacheTtlMinutes": 15, // 캐시 시간(기본값 15분)
"maxRedirects": 3, // 최대 리디렉션 횟수(기본값 3)
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_7_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
"readability": true // Readability 활성화 여부(기본값 true)
}
}
}
}5.1 Firecrawl 백업 구성(선택사항)
Readability 추출이 실패한 경우 Firecrawl을 백업으로 사용할 수 있습니다(API 키 필요):
{
"tools": {
"web": {
"fetch": {
"readability": true,
"firecrawl": {
"enabled": true,
"apiKey": "FIRECRAWL_API_KEY_HERE", // 또는 FIRECRAWL_API_KEY 환경 변수 설정
"baseUrl": "https://api.firecrawl.dev",
"onlyMainContent": true, // 주요 콘텐츠만 추출
"maxAgeMs": 86400000, // 캐시 시간(밀리초, 기본값 1일)
"timeoutSeconds": 60
}
}
}
}
}Firecrawl의 이점
- JavaScript 렌더링 지원(활성화 필요)
- 더 강력한 스크래핑 회피 능력
- 복잡한 웹사이트 지원(SPA, 단일 페이지 애플리케이션)
Firecrawl API 키 가져오기:
- https://www.firecrawl.dev/ 방문
- 계정 생성 및 API 키 생성
- 구성에서 설정 또는 환경 변수
FIRECRAWL_API_KEY사용
6단계: 구성 검증
web_search 확인:
구성된 채널(WebChat 등)에서 메시지 전송:
TypeScript 5.0의 새로운 기능 검색해줘예상 결과:
- AI가 5개의 검색 결과 반환(제목, URL, 설명)
- Perplexity를 사용하는 경우 AI가 요약한 답변과 인용 링크 반환
web_fetch 확인:
메시지 전송:
https://www.typescriptlang.org/docs/handbook/intro.html 콘텐츠 가져와줘예상 결과:
- AI가 해당 페이지의 Markdown 형식 콘텐츠 반환
- 탐색, 광고 등 불필요한 요소가 제거됨
7단계: 고급 기능 테스트
지역 필터 테스트:
독일의 TypeScript 교육 과정 검색해줘AI는 country: "DE" 매개변수를 사용하여 지역별 검색을 수행할 수 있습니다.
시간 필터 테스트:
지난주 AI 분야 뉴스 검색해줘AI는 freshness: "pw" 매개변수를 사용하여 지난 1주일 결과를 필터링할 수 있습니다.
추출 모드 테스트:
https://example.com 가져와서 일반 텍스트 형식으로 반환해줘AI는 extractMode: "text" 매개변수를 사용하여 Markdown 대신 일반 텍스트를 가져올 수 있습니다.
체크포인트 ✅
다음 구성이 올바른지 확인하세요:
- [ ] Gateway 실행 중
- [ ] 최소 하나의 검색 제공자 구성 완료(Brave 또는 Perplexity)
- [ ] API 키가 올바르게 저장됨(CLI 또는 환경 변수 통해)
- [ ] web_search 테스트 성공(검색 결과 반환)
- [ ] web_fetch 테스트 성공(페이지 콘텐츠 반환)
- [ ] 캐시 구성 합리적(과도한 요청 방지)
빠른 검증 명령어
# Gateway 구성 표시
clawdbot configure --show
# Gateway 로그 표시
clawdbot gateway logs --tail 50주의할 점
일반적인 오류 1: API 키가 설정되지 않음
오류 메시지:
{
"error": "missing_brave_api_key",
"message": "web_search needs a Brave Search API key. Run `clawdbot configure --section web` to store it, or set BRAVE_API_KEY in Gateway environment."
}해결 방법:
clawdbot configure --section web실행- API 키 입력
- Gateway 재시작:
clawdbot gateway restart
일반적인 오류 2: 스크래핑 실패(동적 웹페이지)
문제: web_fetch가 JavaScript를 필요로 하는 콘텐츠를 스크래핑할 수 없음.
해결 방법:
- 웹사이트가 SPA(단일 페이지 애플리케이션)인지 확인
- 그렇다면 browser 도구 사용
- 또는 Firecrawl 백업 구성(API 키 필요)
일반적인 오류 3: 캐시로 인한 콘텐츠 만료
문제: 검색 결과 또는 스크래핑된 콘텐츠가 오래됨.
해결 방법:
cacheTtlMinutes구성 조정- 또는 AI 대화에서 명시적으로 "캐시 사용 안 함" 요청
- Gateway 재시작으로 메모리 캐시 지우기
일반적인 오류 4: 요청 타임아웃
문제: 큰 페이지 또는 느린 웹사이트 스크래핑 시 타임아웃.
해결 방법:
{
"tools": {
"web": {
"search": {
"timeoutSeconds": 60
},
"fetch": {
"timeoutSeconds": 60
}
}
}
}일반적인 오류 5: 내부 네트워크 IP가 SSRF로 차단됨
문제: 내부 네트워크 주소(예: http://localhost:8080)로 스크래핑이 차단됨.
해결 방법:
web_fetch는 기본적으로 내부 네트워크 IP를 차단하여 SSRF 공격을 방지합니다. 실제로 내부 네트워크에 액세스해야 하는 경우:
- browser 도구 사용(더 유연)
- 또는 구성 편집하여 특정 호스트 허용(소스 코드 수정 필요)
이 레슨 요약
- web_search: 웹 검색 도구, Brave(구조화된 결과) 및 Perplexity(AI 합성 답변) 지원
- web_fetch: 웹페이지 콘텐츠 스크래핑 도구, Readability를 사용하여 주요 콘텐츠 추출(HTML → Markdown/text)
- 둘 다 내장 캐시 제공(기본값 15분), 중복 요청 감소
- Brave API 키는 CLI, 환경 변수 또는 구성 파일로 설정 가능
- Perplexity는 직접 연결과 OpenRouter 두 가지 방법 지원
- JavaScript가 필요한 웹사이트의 경우 browser 도구 사용
- 구성 매개변수에는: 결과 수, 타임아웃 시간, 지역, 언어, 시간 필터 등이 포함
다음 레슨 미리보기
다음 레슨에서 **Canvas 시각화 인터페이스와 A2UI**를 학습합니다.
학습 내용:
- Canvas A2UI 푸시 메커니즘
- 시각화 인터페이스 작업
- AI 어시스턴트가 Canvas 요소를 제어하는 방법
부록: 소스 코드 참조
클릭하여 소스 코드 위치 펼치기
업데이트 날짜: 2026-01-27
| 기능 | 파일 경로 | 줄 번호 |
|---|---|---|
| web_search 도구 정의 | src/agents/tools/web-search.ts | 409-483 |
| web_fetch 도구 정의 | src/agents/tools/web-fetch.ts | 572-624 |
| Brave Search API 호출 | src/agents/tools/web-search.ts | 309-407 |
| Perplexity API 호출 | src/agents/tools/web-search.ts | 268-307 |
| Readability 콘텐츠 추출 | src/agents/tools/web-fetch-utils.ts | - |
| Firecrawl 통합 | src/agents/tools/web-fetch.ts | 257-330 |
| 캐시 구현 | src/agents/tools/web-shared.ts | - |
| SSRF 보호 | src/infra/net/ssrf.ts | - |
| 구성 Schema | src/config/zod-schema.core.ts | - |
중요한 상수:
DEFAULT_SEARCH_COUNT = 5: 기본 검색 결과 수MAX_SEARCH_COUNT = 10: 최대 검색 결과 수DEFAULT_CACHE_TTL_MINUTES = 15: 기본 캐시 시간(분)DEFAULT_TIMEOUT_SECONDS = 30: 기본 타임아웃 시간(초)DEFAULT_FETCH_MAX_CHARS = 50_000: 기본 최대 스크래핑 문자 수
중요한 함수:
createWebSearchTool(): web_search 도구 인스턴스 생성createWebFetchTool(): web_fetch 도구 인스턴스 생성runWebSearch(): 검색 실행 및 결과 반환runWebFetch(): 스크래핑 실행 및 콘텐츠 추출normalizeFreshness(): 시간 필터 매개변수 정규화extractReadableContent(): Readability를 사용하여 콘텐츠 추출