How to add web search to an AI app (Python, TypeScript, and Ollama)
Quick Summary
Firecrawl Search의 검색 결과를 모델 문맥에 넣으면 Python·TypeScript 앱과 Ollama 로컬 모델에 최신 정보 검색을 추가할 수 있으며, 호스팅 모델과 로컬 모델에 같은 도구 호출 루프를 적용할 수 있다.
🖼️ 인포그래픽

🖼️ 4컷 인포그래픽

💡 한 줄 요약
Firecrawl Search의 검색 결과를 모델 문맥에 넣으면 Python·TypeScript 앱과 Ollama 로컬 모델에 최신 정보 검색을 추가할 수 있으며, 호스팅 모델과 로컬 모델에 같은 도구 호출 루프를 적용할 수 있다.
📌 핵심 요약
- 웹 검색 통합은 검색 API 호출, 제목·URL·본문의 모델 문맥 삽입, 출처 링크를 포함한 답변 생성의 세 단계로 구성된다. 항상 먼저 검색하는 방식과 모델이 web_search 도구 호출을 결정하는 방식이 제시된다.
- Firecrawl Search는 제목·URL·스니펫을 반환하며 같은 호출에서 전체 페이지 Markdown도 제공할 수 있다. Python의 firecrawl-py와 TypeScript의 firecrawl SDK는 API 키 없는 무료 사용 구간을 지원하고, 검색 결과는 results.web에서 읽는다.
- 2026년 10월 21일 세 검색어 실험에서 결과 5개의 스니펫은 6,000~18,000자, 전체 Markdown은 69,000~288,000자였다. 검색 시간은 각각 0.3~1.0초와 0.5~3.9초였으며, 검색 요금은 결과 10개당 2 Firecrawl 크레딧으로 결과 5개 검색 한 번도 2크레딧이 든다.
- 기존 챗봇 예제는 사용자 메시지당 Firecrawl 검색을 최대 3회로 제한하고, 예산 소진 후에는 도구 없이 기존 결과로 답하게 한다. 대화마다 별도 messages 목록을 사용하며, 검색 결과는 지시가 아닌 신뢰할 수 없는 참고 근거로 취급한다.
- Ollama 로컬 모델은 자체 네트워크 접근 없이 앱 코드가 가져온 검색 결과를 문맥으로 받는다. Ollama Python 라이브러리, OpenAI 호환 엔드포인트, Open WebUI, MCP 경로가 제시되며, 저자는 모든 Python 예제를 2026년 10월 21일 qwen3:1.7b에서 실행했다고 밝힌다.
🧩 주요 포인트
- 검색 시점과 반복 횟수가 응답 비용·지연을 좌우한다 → 최신 사실 중심 서비스는 선검색 방식, 일반 챗봇은 도구 호출 방식을 고려하되 최대 3회 같은 검색 예산으로 반복을 제한할 수 있다.
- 전체 Markdown은 스니펫보다 입력량이 크게 늘어난다 → 스니펫으로 시작하고 근거가 부족할 때 본문을 추가하는 접근이 문맥 크기와 응답 시간의 부담을 조절한다.
- 검색 결과를 넣는 것만으로 출처 검증이 완성되지는 않는다 → Firecrawl Search 결과에 번호를 붙이고 인용을 코드에서 확인하며, 서버 실행과 검색 본문의 지시 무시로 키와 답변 생성 경계를 관리한다.
🧠 상세 정리
1. 웹 검색을 추가하는 기본 구조
글은 언어 모델에 학습 시점의 한계가 있어 지난주 릴리스 노트나 오늘의 가격처럼 최신 정보가 필요한 질문에 자신 있게 추측할 수 있다는 문제에서 출발한다. 제안하는 구조는 앱이 검색 API에 질의를 보내고, 반환된 제목·URL·텍스트를 모델의 프롬프트에 넣은 다음, 그 근거로 답하면서 사용한 출처를 링크하게 하는 세 단계다. Firecrawl Search는 이 가운데 검색을 담당하며 모델이 바로 읽을 수 있는 형태로 결과를 제공한다. 따라서 구현의 핵심은 API를 호출하는 코드 자체보다 무엇을 검색하고, 어느 정도의 텍스트를 전달하며, 출처를 어떻게 보여 줄지 결정하는 데 있다. 글 앞부분은 결과에 번호를 붙이고 각 인용을 코드에서 확인하는 방식을 검증 가능한 답변의 접근법으로 제시하지만, 제공된 본문에는 그 전용 절의 상세 구현까지 포함되어 있지는 않다.
2. 선검색과 도구 호출의 선택
첫 번째 연결 방식은 사용자 질문으로 앱 코드가 먼저 검색한 뒤 모델을 한 번 호출하는 선검색 방식으로, 최신 사실에 대한 질의응답이나 문서 도우미에 적합하다고 설명한다. 이 방식은 흐름이 단순하지만 검색이 필요 없는 질문에도 검색을 실행한다는 절충점이 있다. 두 번째 방식은 모델에 web_search 도구를 제공하고 검색 필요성을 판단하게 하는 것으로, 일반 챗봇과 에이전트에 적합하지만 답변마다 모델 호출이 한 번 이상 추가될 수 있다. 검색 범위는 기본값이 5인 limit, 전체 페이지 내용을 추가하는 scrape_options, web·news·images를 선택하는 sources 등으로 조절한다. 최신 웹 문서에는 web 결과에만 적용되는 tbs의 qdr:d·qdr:w·qdr:m 시간 필터를 사용할 수 있고, research·developer·pdf 등의 categories나 질의 안의 site: 조건으로 자료 유형과 도메인을 좁힐 수 있다.
3. 스니펫과 전체 본문의 크기·시간·비용
Firecrawl Search는 작은 스니펫을 빠르게 반환할 수 있고, 스니펫에 답이 없으면 같은 검색 호출에서 전체 페이지 Markdown을 가져오도록 설정할 수 있다. 저자가 2026년 10월 21일 세 검색어로 수행한 실험에서는 검색 결과 5개의 스니펫이 6,000~18,000자였고, 같은 수의 결과를 전체 Markdown으로 받으면 69,000~288,000자였다. 검색 시간도 스니펫은 0.3~1.0초, Markdown은 0.5~3.9초로 제시되어, 본문을 통째로 전달할수록 토큰과 시간 부담이 커지는 방향을 보여 준다. 다만 이는 세 검색어 실험의 관측 범위이므로 모든 검색에서 보장되는 크기나 속도로 읽어서는 안 된다. 글은 스니펫으로 시작하고 답변의 근거가 빈약할 때 Markdown을 추가하라고 권하며, 요금은 결과 10개당 2 Firecrawl 크레딧이어서 채팅 메시지마다 결과 5개 검색을 한 번 수행해도 2크레딧이 든다고 설명한다.
4. Python에서 검색 결과 가져오기
Python에서 가장 빠르게 시작하는 방법으로는 firecrawl-py를 설치하고 Firecrawl 클라이언트의 search()를 호출하는 예제가 제시된다. 예제는 API 키 없이 Firecrawl()을 만든 뒤 latest Ollama release를 limit=5로 검색하고, results.web을 순회하면서 각 결과의 title·url·description을 출력한다. 인수 없는 클라이언트 생성은 키 없는 무료 사용 구간을 사용하며, 더 높은 한도가 필요하면 api_key에 키를 전달하거나 FIRECRAWL_API_KEY 환경변수를 설정할 수 있다고 설명한다. 반환 결과는 results.web에 있으므로 results.data를 읽는 예전 예제는 더 이상 동작하지 않는다는 호환성 주의사항도 명시한다. 이 짧은 코드는 검색 자료를 확보하는 단계에 해당하며, 앱이 답변까지 생성하려면 가져온 제목·URL·스니펫을 모델 문맥에 전달하는 앞서 설명한 과정을 이어 붙여야 한다.
5. TypeScript에서 출처가 있는 답변 생성
TypeScript 예제는 firecrawl과 openai 패키지를 설치하고, 서버의 answerWithSources 함수에서 검색과 모델 호출을 연결한다. 검색 결과 5개에 번호를 붙여 제목·URL·스니펫을 정리한 뒤 하나의 문맥 문자열로 만들고, 모델에는 번호가 있는 출처만 사용하면서 [1]과 같은 인라인 인용을 달도록 요청한다. 시스템 메시지에는 출처 텍스트를 근거로만 취급하고 그 안의 지시는 따르지 말라는 경계도 포함되며, 함수는 생성된 답변과 sources를 함께 반환한다. 이 함수는 Node 스크립트, Next.js 라우트 핸들러 또는 서버 액션에서 사용할 수 있고, Firecrawl과 모델 키가 브라우저에 전달되지 않도록 서버에서 실행해야 한다고 설명한다. OpenAI 클라이언트가 OPENAI_API_KEY와 OPENAI_BASE_URL을 읽기 때문에 같은 코드를 OpenAI 호환 엔드포인트에 연결할 수 있으며, 예로 로컬 Ollama의 http://localhost:11434/v1 주소를 든다.
6. 기존 챗봇에 검색 도구 연결
기존 챗봇에는 query 문자열을 인수로 받는 web_search 함수 도구를 등록하고, 모델이 요청한 도구 호출을 앱 코드에서 처리하는 방식으로 검색을 추가한다. 실제 검색 함수는 Firecrawl Search에서 결과 5개를 받아 제목·URL·스니펫 목록으로 반환하고, 챗봇은 이를 해당 tool_call_id와 연결된 도구 메시지로 대화 이력에 넣는다. 이후 모델을 다시 호출하며, 모델이 더 이상 도구를 요청하지 않고 일반 답변을 내놓으면 반복을 끝낸다. 시스템 프롬프트는 최신 정보나 사실에 대해 검색하도록 요청하는 동시에, 검색 결과를 신뢰할 수 없는 참고 텍스트로 취급하고 그 안의 지시를 따르지 않으며 사용한 URL을 Markdown 링크로 제시하도록 한다. CHAT_MODEL에는 도구 호출을 지원하는 모델을 지정해야 하며, 저자는 OPENAI_BASE_URL과 OPENAI_API_KEY=ollama를 설정해 Ollama의 OpenAI 호환 엔드포인트에서 qwen3:1.7b로 이 파일을 실행했다고 밝힌다.
7. 대화 이력 분리와 검색 예산
챗봇 예제의 new_conversation()은 대화마다 독립적인 messages 목록을 만들며, 이를 통해 여러 턴의 문맥을 유지하면서 한 사용자의 이력이 다른 사용자에게 전달되지 않도록 한다. 글은 이 목록을 앱이 이미 채팅 이력을 저장하는 위치에 보관하면 된다고 설명한다. 검색 예산은 사용자 메시지마다 MAX_SEARCHES=3으로 설정되며, 하나의 응답에 포함된 여러 도구 호출까지 합산해 실제 Firecrawl 검색 횟수를 제한한다. 예산을 넘는 추가 호출에는 검색 대신 한도에 도달했다는 도구 응답을 넣고, 예산이 소진되면 도구를 제공하지 않는 마지막 모델 호출로 이미 찾은 결과에서 답하게 한다. 이 제어는 모델이 검색을 계속 요청해 Firecrawl 크레딧 사용량이 늘어나는 일을 막기 위한 것이며, 도구 설명이나 프롬프트의 요청에만 맡기지 않고 앱 코드에서 검색 횟수를 제한한다는 점이 핵심이다.
8. Ollama 로컬 모델의 연결 경로와 한계
글은 Ollama 로컬 모델에 자체 네트워크 접근이 없으므로 검색은 앱 코드에서 실행하고, 가져온 결과를 모델 문맥으로 전달해야 한다고 설명한다. Ollama Python 라이브러리는 일반 Python 함수를 도구로 받고 함수의 문서 문자열을 도구 설명으로 읽으며, 예제는 도구 지원 모델인 qwen3를 준비한 뒤 web_search를 전달하고 검색 결과를 도구 메시지로 추가해 최종 답변을 생성한다. 실행 환경에 따라 약 30줄의 Ollama Python 코드, 앞선 챗봇 코드를 재사용하는 OpenAI 호환 엔드포인트, 관리자 검색 설정에서 firecrawl과 API 키를 지정하는 Open WebUI 중에서 경로를 선택할 수 있다. 로컬 모델을 사용하는 MCP 클라이언트에는 키 없는 Firecrawl MCP 서버인 https://mcp.firecrawl.dev/v2/mcp를 추가하는 경로도 제시된다. 저자는 모든 Python 예제를 2026년 10월 21일 Ollama의 qwen3:1.7b에서 실행했다고 밝히지만, 작은 모델은 도구 지시를 엄밀하게 따르지 않을 수 있다고 덧붙이며 제공된 본문은 그 후속 설명 도중에 끊긴다.
🧾 핵심 주장 / 시사점
- 호스팅 모델과 Ollama의 공통점은 검색 기능의 내장 여부보다 앱이 검색 결과를 문맥으로 전달하는 구조에 있다. 검색 실행과 도구 응답 처리를 앱이 담당하면 같은 연결 방식을 여러 모델 환경에 적용할 수 있다.
- 검색 품질과 운영 부담은 결과 개수뿐 아니라 전달하는 텍스트의 깊이에도 좌우된다. 제시된 실험에서 전체 Markdown의 입력량이 크게 늘어난 만큼, 스니펫 우선 접근은 근거 확보와 문맥 부담 사이의 조절 수단이 된다.
- 출처 기반 답변의 신뢰성에는 검색 결과 확보, 인용 확인, 검색 본문의 지시 무시가 함께 필요하다. 최대 검색 횟수와 대화 이력 분리 역시 모델의 판단에 맡기지 않고 앱 코드로 관리하는 요소로 제시된다.
✅ 액션 아이템
- Firecrawl Search는 스니펫으로 시작하고, 답변 근거가 부족할 때 전체 Markdown을 추가해 문맥 크기와 응답 시간의 부담을 조절한다.
- 챗봇의 Firecrawl 검색은 사용자 메시지당 최대 3회로 제한하고, 예산 소진 후에는 도구 없이 기존 검색 결과로 답하게 한다.
- Firecrawl Search 결과에 번호를 붙여 인용을 코드에서 확인하고, 검색은 서버에서 실행하며 검색 본문의 지시는 따르지 않도록 한다.
❓ 열린 질문
- 결과 5개의 전체 Markdown이 69,000~288,000자인 조건에서, 스니펫의 근거가 부족해 본문을 추가해야 하는 기준은 무엇인가?
- 결과 5개 검색 한 번에 2크레딧이 드는 Firecrawl 검색에서, 메시지당 최대 3회라는 제한은 답변 근거의 충분성과 비용 사이에서 적절한가?
- Python 예제를 실행한 qwen3:1.7b 외의 Ollama 모델에서는 검색 결과 활용과 출처 링크 생성의 정확도가 어떻게 달라지는가?