# Firecrawl 프로젝트 분석 및 기능명세 분석 대상: `C:\Users\lasta\MyProject\AI\참고\firecrawl-main` 분석일: 2026-05-13 목적: 범용 온톨로지 구축 플랫폼의 웹 수집/정제/구조화 기반 소스로 Firecrawl을 거의 원형에 가깝게 재사용할 수 있는지 판단하고, 향후 구현 기준이 될 기능 명세를 정리한다. ## 1. 결론 요약 Firecrawl은 단순 크롤러가 아니라 `검색 -> URL 발견 -> 페이지 수집 -> 동적 브라우저 실행 -> Markdown/HTML/JSON/스크린샷/파일 파싱 -> 비동기 작업 관리 -> SDK 제공`까지 포함하는 웹 데이터 수집 API 플랫폼이다. 현재 프로젝트의 범용 온톨로지 구축 플랫폼에는 다음 영역이 특히 직접 재사용 가치가 높다. - `apps/api/src/scraper/scrapeURL`: 단일 URL 수집의 핵심. Fetch, Playwright, PDF, 문서, 인덱스, Fire-engine 계열 엔진을 fallback 방식으로 선택한다. - `apps/api/src/scraper/WebScraper/crawler.ts`: 사이트 내부 URL 탐색, sitemap, robots.txt, include/exclude path, depth, subdomain/external link 제어. - `apps/api/src/controllers/v2/types.ts`: API 입력/출력 스키마. 특히 scrape/crawl/map/search 옵션 체계가 잘 정리되어 있다. - `apps/api/src/controllers/v2/*`: 외부 API 기능 명세의 실제 기준. `scrape`, `crawl`, `map`, `search`, `batch scrape`, `parse`, `monitor`, `browser`, `agent`로 분리되어 있다. - `apps/api/src/services/worker/scrape-worker.ts`, `queue-*`: 대량 수집, 크롤 작업, billing/logging/webhook/상태 관리의 운영 흐름. - `apps/python-sdk`, `apps/js-sdk/firecrawl`: 우리 플랫폼 API 클라이언트 설계 시 참고할 수 있는 SDK 표면. 다만 Firecrawl은 Node.js/TypeScript 기반의 API 서버, Redis/BullMQ 또는 NuQ/RabbitMQ/Postgres, Playwright microservice, Supabase/Autumn/Stripe/GCS/Sentry 등 SaaS 운영 요소가 섞여 있다. 현재 Python/FastAPI/SQLAlchemy 기반 프로젝트에 그대로 병합하기보다는, Firecrawl을 별도 수집 서비스로 두고 Python 온톨로지 파이프라인이 Firecrawl API를 호출하는 구조가 가장 안전하다. ## 2. 프로젝트 성격 Firecrawl의 제품 목표는 웹 페이지를 LLM/RAG/Agent가 바로 사용할 수 있는 깨끗한 데이터로 변환하는 것이다. 제공 기능은 다음 세 가지 축으로 요약된다. - 단일 페이지 변환: URL을 Markdown, HTML, raw HTML, link/image 목록, screenshot, structured JSON 등으로 변환한다. - 사이트 단위 수집: seed URL에서 sitemap과 링크 그래프를 따라가며 여러 페이지를 비동기로 수집한다. - 지능형 데이터 추출: JSON Schema, LLM prompt, browser action, search result scraping, file parsing을 결합한다. 온톨로지 구축 플랫폼 관점에서는 Firecrawl이 `웹 수집 계층`과 `텍스트/문서 정제 계층`을 맡고, 현재 프로젝트의 Python 코드는 `도메인 어댑터`, `엔티티/관계 추출`, `Claim/Evidence 저장`, `추천/검증 UI`를 맡는 분업이 적합하다. ## 3. 최상위 구조 ```text firecrawl-main/ apps/ api/ # 핵심 API 서버, 스크래퍼, 크롤러, 큐/워커 playwright-service-ts/ # Playwright 브라우저 마이크로서비스 python-sdk/ # Python SDK js-sdk/firecrawl/ # JS/TS SDK php-sdk, ruby-sdk, rust-sdk, elixir-sdk # 다언어 SDK ui/ingestion-ui/ # ingestion UI test-suite/ # API/load 테스트 test-site/ # 테스트용 사이트 go-html-to-md-service/ # HTML -> Markdown 변환 보조 서비스 nuq-postgres/ # NuQ 큐용 Postgres 구성 examples/ # LLM/agent/추출 예제 다수 docker-compose.yaml # self-host 전체 구성 SELF_HOST.md # 자체 호스팅 안내 README.md # 제품/SDK/API 개요 ``` 핵심은 `apps/api`이다. 나머지는 SDK, 배포, 예제, 테스트, UI 보조 레이어다. ## 4. 기술 스택 - 언어: TypeScript/Node.js, 일부 Rust native package, 일부 Go service - API: Express, express-ws, Zod validation, multer multipart - 브라우저: 별도 `playwright-service-ts`, Fire-engine CDP/TLS client 연동 가능 - HTML 처리: Cheerio, JSDOM, Turndown, joplin-turndown-plugin-gfm, Rust 기반 link filtering/extraction - 문서 처리: PDF, DOC/DOCX/ODT/RTF/XLS/XLSX 계열 파일 처리 모듈 - 큐/상태: BullMQ, Redis, NuQ, RabbitMQ, Postgres - 검색: Google 기본, SearXNG 대체, DuckDuckGo/v2 검색 코드 - LLM: OpenAI, Anthropic, Google, Groq, xAI, OpenRouter, Ollama/OpenAI-compatible - 운영: Docker Compose, Kubernetes/Helm 예제, Sentry, Prometheus, logging, billing ## 5. 런타임 아키텍처 ```mermaid flowchart TD A["Client / SDK / API"] --> B["Express v2 Router"] B --> C["Auth / rate limit / credit / blocklist"] C --> D{"Endpoint"} D --> E["Scrape Controller"] D --> F["Crawl Controller"] D --> G["Map Controller"] D --> H["Search Controller"] E --> I["scrapeURL engine fallback"] F --> J["WebCrawler URL discovery"] J --> K["Queue scrape jobs"] G --> J H --> L["Search provider"] H --> I K --> M["Scrape Worker"] M --> I I --> N["Fetch / Playwright / PDF / Document / Index / Fire-engine"] N --> O["Markdown / metadata / formats / actions"] O --> P["Result / status / webhook / logs"] ``` ### 핵심 흐름 1. API 요청은 `apps/api/src/routes/v2.ts`에서 endpoint별 controller로 라우팅된다. 2. Zod 스키마가 URL, 옵션, format, crawler option을 strict하게 검증한다. 3. 단일 scrape는 동기적으로 처리하되 내부적으로 semaphore와 worker 공통 함수를 사용한다. 4. crawl/batch scrape는 작업 ID를 반환하고 큐에 개별 scrape job을 넣는다. 5. worker는 URL별로 `scrapeURL`을 실행하고 성공/실패/robots 차단/비용/로그/웹훅을 기록한다. 6. 결과는 status endpoint, websocket, webhook, SDK polling을 통해 조회된다. ## 6. 핵심 모듈 분석 ### 6.1 API 라우터 파일: `apps/api/src/routes/v2.ts` 주요 endpoint: - `POST /v2/search` - `POST /v2/parse` - `POST /v2/scrape` - `GET /v2/scrape/:jobId` - `POST /v2/scrape/:jobId/interact` - `DELETE /v2/scrape/:jobId/interact` - `POST /v2/batch/scrape` - `GET /v2/batch/scrape/:jobId` - `DELETE /v2/batch/scrape/:jobId` - `GET /v2/batch/scrape/:jobId/errors` - `POST /v2/map` - `POST /v2/crawl` - `POST /v2/crawl/params-preview` - `GET /v2/crawl/ongoing` - `GET /v2/crawl/:jobId` - `DELETE /v2/crawl/:jobId` - `WS /v2/crawl/:jobId` - `GET /v2/crawl/:jobId/errors` - `POST /v2/extract` - `GET /v2/extract/:jobId` - `POST /v2/agent` - `GET /v2/agent/:jobId` - `DELETE /v2/agent/:jobId` - `POST /v2/monitor` - `GET /v2/monitor` - `GET /v2/monitor/:monitorId` - `PATCH /v2/monitor/:monitorId` - `DELETE /v2/monitor/:monitorId` - `POST /v2/monitor/:monitorId/run` - `GET /v2/monitor/:monitorId/checks` - `GET /v2/monitor/:monitorId/checks/:checkId` - `POST /v2/browser` - `GET /v2/browser` - `POST /v2/browser/:sessionId/execute` - `DELETE /v2/browser/:sessionId` - `GET /v2/team/credit-usage` - `GET /v2/team/token-usage` - `GET /v2/concurrency-check` - `GET /v2/team/queue-status` - `GET /v2/team/activity` 우리 프로젝트에서 우선 필요한 것은 `scrape`, `crawl`, `map`, `batch scrape`, `parse`, `search`다. `billing`, `credit`, `team`, `x402`, `agent signup`, `support proxy`는 초기에는 제외 가능하다. ### 6.2 스키마와 옵션 체계 파일: `apps/api/src/controllers/v2/types.ts` Firecrawl은 입력 옵션을 Zod로 strict validation한다. 알 수 없는 key는 거부하는 방식이라 API 안정성이 높다. #### 공통 Scrape 옵션 - `formats`: 기본 `markdown`. 지원 format은 `markdown`, `html`, `rawHtml`, `links`, `images`, `summary`, `json`, `changeTracking`, `screenshot`, `attributes`, `branding`, `question`, `highlights`, `query`, `audio`. - `headers`: 요청 header. - `includeTags`, `excludeTags`: 특정 selector 포함/제외. iframe selector 변환도 처리한다. - `onlyMainContent`: 기본 true. 본문 중심 추출. - `onlyCleanContent`: 기본 false. - `timeout`: 최소 1000ms. - `waitFor`: 기본 0, 최대 60000ms, timeout의 절반 이하. - `mobile`: 모바일 viewport 사용. - `parsers`: PDF/문서 parser 옵션. - `actions`: wait/click/write/press/scroll/scrape/screenshot 등 브라우저 액션. - `location`: country/languages. 기본 country는 `us-generic`. - `skipTlsVerification`: TLS 검증 skip. - `removeBase64Images`: 기본 true. - `fastMode`: 빠른 수집 모드. - `blockAds`: 기본 true. - `proxy`: `basic`, `stealth`, `enhanced`, `auto`. 기본 `auto`. - `maxAge`, `minAge`, `storeInCache`: 캐시 사용 기준. - `lockdown`: 캐시/index 기반 제한 모드. - `profile`: 브라우저 profile 이름과 저장 여부. 중요 transform: - JSON format이 있고 기본 timeout 30000ms이면 60000ms로 늘린다. - stealth/enhanced/auto proxy이며 기본 timeout이면 120000ms로 늘린다. - changeTracking은 markdown format을 요구하고 waitFor/timeout을 늘린다. - actions + waitFor 총 대기 시간은 60초를 넘지 못한다. #### Crawler 옵션 - `includePaths`: 포함할 path regex. - `excludePaths`: 제외할 path regex. - `maxDiscoveryDepth`: 발견 깊이 제한. - `limit`: 기본 10000. - `crawlEntireDomain`: 전체 domain 허용. - `allowExternalLinks`: 기본 false. - `allowSubdomains`: 기본 false. - `ignoreRobotsTxt`: 기본 false. - `robotsUserAgent`: robots.txt 확인 user-agent. - `sitemap`: `skip`, `include`, `only`. 기본 `include`. - `deduplicateSimilarURLs`: 기본 true. - `ignoreQueryParameters`: 기본 false. - `regexOnFullURL`: 기본 false. - `delay`: URL 간 delay. #### Map 옵션 Map은 URL 목록 발견용이다. 기본 `includeSubdomains=true`, `ignoreQueryParameters=true`, `limit=5000`, 최대 `100000`이다. `search`, `sitemap`, `filterByPath`, `useIndex`, `ignoreCache`, `location`, `headers`를 지원한다. #### Search 옵션 - `query`: 검색어. - `limit`: 기본 10, 최대 100. - `sources`: `web`, `images`, `news`. - `categories`: `github`, `research`, `pdf`. - `includeDomains`, `excludeDomains`: 동시에 지정 불가. - `lang`: 기본 en. - `country`/`location`. - `timeout`: 기본 60000ms. - `asyncScraping`: 검색 결과 scraping을 비동기 job으로 반환 가능. - `scrapeOptions`: 검색 결과 페이지를 바로 scrape할 때 사용하는 제한된 scrape 옵션. ### 6.3 단일 URL 수집 엔진 파일: `apps/api/src/scraper/scrapeURL/index.ts`, `apps/api/src/scraper/scrapeURL/engines/index.ts` Firecrawl의 핵심은 URL과 요청 feature를 보고 엔진 후보를 만든 뒤 fallback 순서로 시도하는 구조다. 지원 엔진: - `index`: 기존 index/cache에서 문서 조회. - `index;documents`: 문서 index 조회. - `fire-engine;chrome-cdp`: 고급 브라우저 엔진. - `fire-engine;chrome-cdp;stealth`: stealth proxy 브라우저 엔진. - `fire-engine;tlsclient`: TLS client 기반 수집. - `fire-engine;tlsclient;stealth`: stealth TLS client. - `playwright`: 자체 Playwright microservice. - `fetch`: HTTP fetch 기반 빠른 수집. - `pdf`: PDF 전용 처리. - `document`: DOCX/ODT/RTF/XLS/XLSX 등 문서 처리. - `wikipedia`: Wikimedia 전용 엔진. - `x-twitter`: X/Twitter 전용 엔진. Feature flag: - `actions`, `waitFor`, `screenshot`, `screenshot@fullScreen`, `pdf`, `document`, `audio`, `atsv`, `location`, `mobile`, `skipTlsVerification`, `useFastMode`, `stealthProxy`, `branding`, `disableAdblock`. 선택 방식: 1. URL 확장자, option, format을 보고 필요한 feature flag를 계산한다. 2. 각 엔진이 feature를 지원하는지 확인한다. 3. quality와 feature priority를 기준으로 fallback list를 만든다. 4. 엔진별 max reasonable time을 계산하고 timeout/abort manager와 함께 실행한다. 5. HTML을 Markdown으로 변환하고 metadata, links, images, screenshot, extract 결과 등을 조립한다. 6. 실패 시 `NoEnginesLeftError`, `DNSResolutionError`, `SSLError`, `PDFOCRRequiredError`, `ActionError`, `CrawlDenialError` 등 typed error로 전달한다. 온톨로지 플랫폼에는 이 구조가 매우 유용하다. 특정 쇼핑몰/공식몰/문서/PDF마다 직접 fetcher를 분기하지 않고, Firecrawl이 feature 기반 fallback을 담당하게 할 수 있다. ### 6.4 URL 발견과 사이트 크롤링 파일: `apps/api/src/scraper/WebScraper/crawler.ts` `WebCrawler`는 seed URL에서 사이트 내부 링크를 발견하고 filtering한다. 주요 기능: - sitemap 로드와 sitemap 링크 제한. - robots.txt 로드와 robots parser. - max depth, max discovery depth 적용. - include/exclude regex path filtering. - backward crawling 차단. - external link/subdomain 허용 여부 판단. - query parameter 무시/중복 제거. - 비웹 프로토콜, social/mailto, section anchor, 비문서 file type 제거. - URL별 denial reason 생성. 현재 프로젝트의 `crawler_platform.app.core.crawler.discovery`, `site_crawler`, `content_zone`, `fetchers`를 Firecrawl 방식으로 강화할 수 있다. 단, Python 코드에 직접 포팅하기보다는 `POST /v2/map` 또는 `POST /v2/crawl`을 호출해 URL discovery를 위임하는 것이 빠르다. ### 6.5 Crawl 작업 처리 파일: `apps/api/src/controllers/v2/crawl.ts`, `apps/api/src/services/worker/scrape-worker.ts` Crawl은 단일 요청에서 모든 페이지를 즉시 반환하지 않는다. 처리 절차: 1. `crawlRequestSchema`로 URL, crawler option, scrape option 검증. 2. 자연어 `prompt`가 있으면 site structure를 일부 map한 뒤 LLM으로 crawler option 생성. 3. include/exclude regex 유효성 확인. 4. credit 또는 self-host 설정에 따라 limit 조정. 5. Redis/queue에 `StoredCrawl` 저장. 6. kickoff job을 큐에 넣고 `id`, status URL을 반환. 7. worker가 URL을 발견하고 개별 scrape job으로 확장한다. 8. `GET /v2/crawl/:jobId` 또는 websocket으로 진행률과 결과를 조회한다. 응답 status: - `scraping` - `completed` - `failed` - `cancelled` status 응답은 `completed`, `total`, `creditsUsed`, `expiresAt`, `next`, `data: Document[]`를 포함한다. ### 6.6 Search 파일: `apps/api/src/controllers/v2/search.ts`, `apps/api/src/search/*` Search는 검색 결과를 반환하고, 옵션에 따라 각 결과 페이지를 scrape해서 markdown까지 포함한다. 온톨로지 플랫폼 활용: - 브랜드/상품/성분/카테고리 후보 URL 발견. - 공식 문서, PDF, research 자료 검색. - seed URL이 부족한 신규 도메인 bootstrap. - `includeDomains`/`excludeDomains`로 신뢰 출처 제한. 초기 MVP에서는 외부 검색 품질보다 `검색 결과 -> 후보 Source/Page -> 검토 큐` 흐름을 만드는 것이 중요하다. ### 6.7 Parse `POST /v2/parse`는 multipart file upload를 받아 HTML/PDF/document를 scrape-like document로 변환한다. 파일 크기 제한은 50MB다. 온톨로지 플랫폼 활용: - 로컬 PDF catalog, 제품 설명서, 성분표 문서 ingest. - HTML fixture나 저장된 페이지 snapshot ingest. - URL이 아닌 파일 기반 evidence 확보. ### 6.8 Browser / Interact / Actions Firecrawl은 두 종류의 상호작용을 제공한다. - scrape request의 `actions`: scrape 전에 wait, click, write, press, scroll, screenshot, scrape 등을 수행한다. - `POST /v2/scrape/:jobId/interact`: scrape job에 연결된 browser session에 code 또는 prompt 기반 조작을 수행한다. 온톨로지 플랫폼 활용: - 쿠키 배너 닫기. - 검색/필터/더보기 버튼 클릭. - pagination 또는 lazy-loaded product list 수집. - 특정 selector 대기 후 수집. 주의: action 기반 수집은 재현성과 비용이 낮아질 수 있으므로, Source 단위 설정으로 제한하고 audit log를 남기는 것이 좋다. ### 6.9 Monitor Monitor는 특정 URL/옵션을 주기적으로 실행하고 check 결과/diff를 관리하는 기능이다. 온톨로지 플랫폼 활용: - 공식 상품 페이지 변경 감지. - 성분/가격/품절/리뉴얼 페이지 모니터링. - Claim evidence의 stale 여부 판단. 초기 버전에서는 Firecrawl Monitor 전체를 들여오기보다, 현재 프로젝트의 `scheduler/update_policy.py`에서 Firecrawl scrape를 주기 호출하고 content hash/changeTracking을 저장하는 방식이 단순하다. ### 6.10 SDK Python SDK는 `apps/python-sdk/firecrawl` 아래에 있으며, v2 메서드가 `/v2/scrape`, `/v2/crawl`, `/v2/map`, `/v2/search`, `/v2/batch/scrape`, `/v2/parse`, browser interaction을 감싼다. 우리 프로젝트가 Firecrawl을 별도 서비스로 사용할 경우 Python SDK를 직접 사용하거나, 현재 FastAPI 서비스 내부에 얇은 adapter를 만드는 방식이 적합하다. ## 7. 기능명세 ### 7.1 Document 모델 Firecrawl의 핵심 결과 단위는 `Document`다. 필드: - `title`, `description`, `url` - `markdown`, `html`, `rawHtml` - `links`, `images` - `screenshot`, `audio` - `json`, `extract`, `summary`, `answer`, `highlights`, `branding` - `attributes`: selector/attribute/value 목록 - `actions`: action 중 생성된 screenshot/scrape/javascript return/pdf - `changeTracking`: 이전 scrape 대비 상태와 diff - `metadata`: title, description, language, keywords, robots, OpenGraph, favicon, sourceURL, statusCode, scrapeId, contentType, proxyUsed, cacheState, cachedAt, creditsUsed 등 - `serpResults`: search result title/description/url 온톨로지 플랫폼 매핑: - `Document.url` -> `Page.url` - `Document.markdown` -> `Page.cleaned_text` 또는 `Page.markdown` - `Document.html/rawHtml` -> 저장 여부 선택. 기본은 저장하지 않고 hash만 저장 권장. - `Document.metadata.sourceURL/statusCode/contentType` -> `Page.fetch_status`, `Page.metadata` - `Document.links/images` -> discovery 후보와 media evidence - `Document.json/extract` -> 도메인 extractor 입력 또는 사전 추출값 - `Document.changeTracking` -> claim freshness/update scheduling ### 7.2 Scrape API 명세 Endpoint: `POST /v2/scrape` 목적: 단일 URL을 LLM-ready document로 변환한다. 필수 입력: - `url`: HTTP/HTTPS URL. protocol이 없으면 `http://`를 보정한다. 선택 입력: - 공통 Scrape 옵션 전체. - `origin`: 요청 출처 tag. 기본 `api`. - `integration`: 외부 통합 정보. - `zeroDataRetention`: 데이터 보존 제한. 정상 응답: ```json { "success": true, "data": { "markdown": "...", "metadata": { "sourceURL": "https://example.com", "statusCode": 200, "proxyUsed": "basic" } } } ``` 실패 응답: ```json { "success": false, "code": "ERROR_CODE", "error": "message" } ``` 우리 플랫폼 수용 기준: - URL 단위 수집의 기본 provider는 Firecrawl scrape로 한다. - 기본 format은 `markdown`, 필요 시 `html`, `links`, `images`, `screenshot`, `json`을 Source config에서 켠다. - extractor는 Firecrawl JSON을 그대로 신뢰하기보다, `markdown + metadata + sourceURL`을 현재 ontology extractor에 넣어 Claim/Evidence를 만든다. ### 7.3 Crawl API 명세 Endpoint: `POST /v2/crawl` 목적: seed URL에서 여러 URL을 발견하고 각 페이지를 scrape한다. 필수 입력: - `url` 선택 입력: - Crawler 옵션: `includePaths`, `excludePaths`, `limit`, `maxDiscoveryDepth`, `allowExternalLinks`, `allowSubdomains`, `ignoreRobotsTxt`, `sitemap`, `delay` 등. - `scrapeOptions`: 각 페이지에 적용할 scrape 옵션. - `webhook`: 상태 통지. - `maxConcurrency` - `prompt`: 자연어로 crawler option 생성. 정상 응답: ```json { "success": true, "id": "job-id", "url": "http://host/v2/crawl/job-id" } ``` Status 조회: ```json { "success": true, "status": "scraping", "completed": 12, "total": 100, "creditsUsed": 12, "expiresAt": "...", "data": [] } ``` 우리 플랫폼 수용 기준: - 사이트 전체 수집은 `crawl-site` 내부 구현을 Firecrawl crawl 호출로 대체 또는 선택 가능하게 한다. - 결과 Document[]는 Page 단위로 upsert하고, 각 Page를 ontology extraction queue로 넘긴다. - `includePaths/excludePaths`는 Source config의 `url_patterns`로 매핑한다. ### 7.4 Map API 명세 Endpoint: `POST /v2/map` 목적: scrape 없이 URL 후보 목록만 빠르게 발견한다. 입력: - `url` - `search`: path/title 검색 조건. - `sitemap`: `only`, `include`, `skip` - `limit`: 기본 5000, 최대 100000 - `includeSubdomains`, `allowExternalLinks`, `ignoreQueryParameters`, `filterByPath` - `useIndex`, `ignoreCache` 응답: ```json { "success": true, "links": [ { "url": "https://example.com/a", "title": "...", "description": "..." } ] } ``` 우리 플랫폼 수용 기준: - 신규 Source 등록 시 먼저 Map을 실행해 수집 범위 preview를 보여준다. - 사용자가 선택한 URL 패턴을 config로 저장한다. - 대규모 크롤 전에 Map 결과로 예상 page 수와 domain/path 분포를 산출한다. ### 7.5 Batch Scrape API 명세 Endpoint: `POST /v2/batch/scrape` 목적: URL 배열을 비동기 scrape job으로 처리한다. 입력: - `urls`: 1개 이상 URL 배열. - 공통 Scrape 옵션. - `webhook`, `appendToId`, `ignoreInvalidURLs`, `maxConcurrency`, `zeroDataRetention`. 응답: ```json { "success": true, "id": "job-id", "url": "http://host/v2/batch/scrape/job-id", "invalidURLs": [] } ``` 우리 플랫폼 수용 기준: - Map으로 발견한 URL 중 우선순위가 높은 URL 묶음을 batch scrape로 실행한다. - 실패 URL은 `crawl_errors` 또는 Page status로 저장하고 재시도 정책에 연결한다. ### 7.6 Search API 명세 Endpoint: `POST /v2/search` 목적: query 기반으로 web/news/images 결과를 얻고, 필요하면 결과 페이지 내용까지 scrape한다. 입력: - `query` - `limit`, `sources`, `categories`, `includeDomains`, `excludeDomains` - `lang`, `country`, `location` - `timeout` - `asyncScraping` - `scrapeOptions` 응답: ```json { "success": true, "id": "job-id", "creditsUsed": 3, "data": { "web": [ { "url": "https://example.com", "title": "Example", "description": "...", "markdown": "..." } ] } } ``` 우리 플랫폼 수용 기준: - 자동 Source 후보 발굴 기능에 사용한다. - `includeDomains`를 우선 사용해 공식몰/공식 문서/신뢰 출처 탐색을 제한한다. - 검색 결과는 즉시 Claim으로 넣지 않고 Source/Page 후보 검토 큐로 넣는다. ### 7.7 Parse API 명세 Endpoint: `POST /v2/parse` 목적: 업로드 파일을 Document로 변환한다. 입력: - multipart field `file` - 공통 Scrape 옵션. - 파일 최대 50MB. - kind: `html`, `pdf`, `document`. 우리 플랫폼 수용 기준: - 로컬 catalog/PDF/manual ingest에 사용한다. - parse 결과는 URL source가 없을 수 있으므로 `Source.type=file`, `Page.url=file://...` 또는 별도 `documents` 테이블 정책을 정한다. ### 7.8 Monitor API 명세 Endpoint 집합: - `POST /v2/monitor` - `GET /v2/monitor` - `GET /v2/monitor/:monitorId` - `PATCH /v2/monitor/:monitorId` - `DELETE /v2/monitor/:monitorId` - `POST /v2/monitor/:monitorId/run` - `GET /v2/monitor/:monitorId/checks` - `GET /v2/monitor/:monitorId/checks/:checkId` 목적: 특정 수집 대상의 변경을 주기적으로 감시한다. 우리 플랫폼 수용 기준: - MVP에서는 직접 도입하지 않고, Firecrawl `changeTracking` 또는 주기 scrape 결과의 content hash 비교로 대체한다. - 장기적으로 Claim freshness, 상품 리뉴얼, 가격/품절 변경에 연결한다. ### 7.9 Browser Session API 명세 Endpoint: - `POST /v2/browser` - `GET /v2/browser` - `POST /v2/browser/:sessionId/execute` - `DELETE /v2/browser/:sessionId` - `POST /v2/scrape/:jobId/interact` - `DELETE /v2/scrape/:jobId/interact` 목적: 브라우저 세션을 생성하고 code/prompt 기반으로 조작한다. 우리 플랫폼 수용 기준: - Source config에 `actions`를 저장하는 형태를 우선한다. - 자유로운 browser execute는 보안/재현성 위험이 있으므로 관리자 전용 디버깅 기능으로 제한한다. ## 8. Self-host 구성 `docker-compose.yaml` 기준 서비스: - `api`: Express API와 worker harness. - `playwright-service`: 브라우저 수집 microservice. - `redis`: queue/rate limit/cache. - `rabbitmq`: NuQ worker messaging. - `nuq-postgres`: NuQ 상태 저장. 필수/주요 환경 변수: - `PORT`, `HOST` - `USE_DB_AUTHENTICATION=false`로 self-host API key 없이 사용 가능 - `REDIS_URL`, `REDIS_RATE_LIMIT_URL` - `PLAYWRIGHT_MICROSERVICE_URL` - `NUQ_RABBITMQ_URL` - `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB`, `POSTGRES_HOST`, `POSTGRES_PORT` - `OPENAI_API_KEY`, `OPENAI_BASE_URL`, `MODEL_NAME`, `OLLAMA_BASE_URL` 등 AI 기능용 - `PROXY_SERVER`, `PROXY_USERNAME`, `PROXY_PASSWORD` - `SEARXNG_ENDPOINT` - `BULL_AUTH_KEY` - `MAX_CPU`, `MAX_RAM` - `ALLOW_LOCAL_WEBHOOKS` Self-host 제한: - Fire-engine 고급 기능은 cloud/internal 의존성이 있어 자체 호스팅에서 제한될 수 있다. - 기본적으로 fetch + Playwright + PDF/document 처리 중심으로 보는 것이 현실적이다. - Supabase/Stripe/Autumn/GCS/Sentry 의존 영역은 자체 플랫폼에서는 제거하거나 stub 처리해야 한다. ## 9. 현재 프로젝트와의 통합 설계 현재 프로젝트는 Python/FastAPI 기반이며 핵심 구조는 다음과 같다. - `crawler_platform/app/core/crawler`: fetch/discovery/clean/pipeline. - `crawler_platform/app/core/extractor`: rule-based/AI extractor. - `crawler_platform/app/core/ontology`: entity, relation, claim, triple store. - `crawler_platform/app/core/database`: SQLAlchemy 저장소. - `crawler_platform/app/core/research`: graph research loop. - `crawler_platform/app/api/routes.py`: 관리 API. - `configs/perfume_subscription.yaml`: Source/domain config. 권장 통합 방식: ```mermaid flowchart LR A["Crawler Platform FastAPI"] --> B["Firecrawl Adapter"] B --> C["Firecrawl Self-host API"] C --> D["Scrape / Map / Crawl / Search"] D --> E["Document"] E --> F["Page Upsert"] F --> G["Ontology Extractor"] G --> H["Entity / Claim / Evidence"] ``` ### 단계별 채택 계획 1. `FirecrawlClient` adapter 추가 - Python SDK 또는 HTTP client 사용. - `scrape_url`, `map_site`, `crawl_site`, `batch_scrape`, `search_sources`, `parse_file` 메서드 제공. 2. Source config 확장 - `fetcher: firecrawl` - `firecrawl.formats` - `firecrawl.actions` - `firecrawl.crawler_options` - `firecrawl.scrape_options` - `firecrawl.search_options` 3. Page 저장 모델 확장 - `markdown` - `raw_html_hash` - `metadata_json` - `scrape_id` - `content_type` - `cache_state` - `change_status` 4. 기존 extractor 연결 - Firecrawl Document의 `markdown`을 표준 입력으로 사용. - `metadata.sourceURL`을 evidence source로 유지. - `links/images`를 다음 discovery 후보 또는 evidence attachment로 저장. 5. UI 기능 추가 - Map preview. - Crawl job status. - Page markdown preview. - 실패 URL과 denial reason 표시. ## 10. 재사용 우선순위 ### 즉시 재사용 권장 - v2 API 명세와 옵션 체계. - `scrape`, `map`, `crawl`, `batch scrape`. - Document 결과 모델. - Python SDK 또는 HTTP adapter. - Docker Compose self-host 실행 방식. ### 부분 재사용 권장 - `actions`: Source별 필요한 경우에만. - `search`: Source 후보 발굴 단계. - `parse`: 파일 ingest 단계. - `monitor/changeTracking`: 업데이트 감지 단계. - `crawler.ts`의 denial reason/URL filtering 정책: Python config validation에 반영. ### 초기 제외 권장 - billing/credit/team/account 기능. - x402 micropayment. - support proxy. - agent signup. - Supabase/Stripe/Autumn/GCS/Sentry SaaS 운영 코드. - Fire-engine cloud 의존 기능. ## 11. 온톨로지 플랫폼 기능명세 초안 Firecrawl을 기반 수집기로 사용할 때 범용 온톨로지 구축 플랫폼은 다음 기능을 가져야 한다. ### 11.1 Source 등록 입력: - source name - base URL 또는 seed URL 목록 - source type: official, marketplace, review, document, search - fetcher: `requests`, `playwright`, `firecrawl` - Firecrawl crawler/scrape/search options - 신뢰도 기본값 - robots 준수 정책 - update schedule 출력: - Source record - Map preview 결과 - 예상 page count ### 11.2 URL 발견 기능: - Firecrawl Map 호출. - sitemap only/include/skip 선택. - include/exclude path regex 적용. - subdomain/external link 정책 적용. - query parameter 무시 여부. - URL 후보를 Page 상태 `discovered`로 저장. 검증: - URL 중복 제거. - domain/path scope 위반 차단. - robots 차단 URL 표시. ### 11.3 페이지 수집 기능: - 단일 URL scrape. - 다중 URL batch scrape. - site crawl job 실행. - Markdown, metadata, links, images 저장. - HTML 원문 저장 여부 선택. - screenshot 선택 저장. 상태: - discovered - queued - fetching - fetched - failed - blocked_by_robots - skipped ### 11.4 문서/파일 수집 기능: - PDF/DOCX/HTML 파일 업로드. - Firecrawl Parse 호출. - 문서 metadata와 markdown 저장. - 파일 기반 evidence source 생성. ### 11.5 구조화 추출 기능: - Firecrawl JSON format 또는 현재 Python extractor 선택. - 기본 경로는 `Document.markdown -> ontology extractor`. - JSON Schema 기반 추출은 도메인별 schema를 사용. - 추출 결과는 바로 확정하지 않고 Claim/Evidence로 저장. ### 11.6 Claim/Evidence 생성 기능: - Entity 후보 생성. - subject-predicate-object Claim 생성. - Evidence text와 source URL, page id, selector 또는 markdown span 저장. - confidence score 산출. - Source 신뢰도와 추출 방식에 따른 confidence 조정. ### 11.7 변경 감지 기능: - Page content hash 비교. - Firecrawl changeTracking format 사용 가능. - 변경된 페이지만 재추출. - 삭제/숨김/동일/변경 상태 기록. ### 11.8 검토 UI 기능: - Source별 Map preview. - Crawl job 진행률. - Page markdown 미리보기. - Claim 목록과 evidence 확인. - confidence 수동 조정. - entity merge. - 실패 URL과 denial reason 확인. ## 12. 리스크와 주의점 - 라이선스: Firecrawl root LICENSE는 AGPL 계열로 보인다. 소스 자체를 서비스에 내장/수정 배포할 경우 공개 의무가 발생할 수 있으므로 별도 확인이 필요하다. - 언어/스택 차이: 현재 프로젝트는 Python, Firecrawl 핵심은 TypeScript다. 직접 코드 병합보다 서비스 분리가 적합하다. - 운영 복잡도: Redis, RabbitMQ, Postgres, Playwright service가 필요하다. - Cloud 의존 기능: Fire-engine, 일부 index/search/branding/agent 기능은 self-host에서 제한될 수 있다. - 비용/속도: Playwright/action/screenshot/stealth는 비용이 크다. Source별 정책이 필요하다. - 데이터 보존: raw HTML/screenshot/audio 저장은 개인정보/저작권/용량 이슈가 있으므로 기본 off 권장. - 검색 결과 신뢰도: Search는 후보 발굴용이며 Claim 근거로 바로 쓰면 안 된다. ## 13. 구현 권장안 최초 구현은 다음 범위가 좋다. 1. Firecrawl self-host를 별도 Docker Compose로 실행한다. 2. Python 프로젝트에 `FirecrawlAdapter`를 만든다. 3. `POST /crawl` 또는 CLI `crawl-url`에 `fetcher=firecrawl` 옵션을 추가한다. 4. 단일 URL scrape 결과의 markdown을 기존 extractor로 넘긴다. 5. Map preview와 batch scrape는 두 번째 단계에서 붙인다. 6. Monitor/changeTracking/search/parse는 세 번째 단계에서 붙인다. 이 방식이면 Firecrawl의 강한 수집 능력을 거의 변형 없이 사용하면서, 현재 프로젝트의 핵심 가치인 범용 온톨로지/Claim/Evidence/추천 구조는 Python 코드에 유지할 수 있다.