Research 엔진 vs Seed 엔진 개요
This content is not available in your language yet.
🔍 Newsfork: Research 엔진 vs Seed 엔진
섹션 제목: “🔍 Newsfork: Research 엔진 vs Seed 엔진”📋 전체 시스템 개요
섹션 제목: “📋 전체 시스템 개요”Newsfork는 2단계 파이프라인으로 구성되어 있습니다:
[Research Engine] → [Seed Engine] → [Scraper Engine] "어디서" "어떻게" "실제 수집"각 엔진은 명확하게 분리된 책임을 가지며, 독립적으로 개발/테스트/확장할 수 있도록 설계되었습니다.
🔬 Research 엔진 (URL 발견 단계)
섹션 제목: “🔬 Research 엔진 (URL 발견 단계)”🎯 핵심 철학
섹션 제목: “🎯 핵심 철학”“Research Engine discovers WHERE to look.”
Research 엔진은 URL 발견에만 집중합니다. 콘텐츠 품질, 수집 방법, 유효성을 판단하지 않습니다.
📁 데이터 구조
섹션 제목: “📁 데이터 구조”research/├── datasets/ # 발견된 URL 데이터셋 (불변)│ └── country=sg/category=news/2026-01-25_0001.json├── liveness/ # 도메인 생존 확인 결과│ └── country=sg/2026-01-25.json├── blocked/ # 차단된 도메인 (403, captcha)│ └── country=sg/2026-01-25.json└── dead/ # 죽은 도메인 (DNS 실패, 접근 불가) └── country=sg/2026-01-25.json🔧 주요 기능
섹션 제목: “🔧 주요 기능”✅ Research 엔진이 하는 일
섹션 제목: “✅ Research 엔진이 하는 일”- URL 발견: Google Search, crt.sh, Wayback Machine 등을 통한 URL 수집
- 도메인 정규화:
www.mom.gov.sg→mom.gov.sg - Domain ID 생성:
gov:sg:mom.gov.sg형식으로 고유 식별자 생성 - 생존 확인: Phase 1-A 생존성 체크 (HTTP 200 응답 확인)
- 불변 스냅샷: 발견된 URL들의 시점별 불변 데이터셋 생성
- 메타데이터 관리: D1에 배치 상태 및 통계 저장
❌ Research 엔진이 하지 않는 일
섹션 제목: “❌ Research 엔진이 하지 않는 일”- 콘텐츠 타입 결정 (RSS/HTML/API)
- 콘텐츠 성격 분류 (뉴스/정책/가이드)
- 메타데이터 추출
- Seed 계약 생성
📊 Research 데이터 예시
섹션 제목: “📊 Research 데이터 예시”{ "meta": { "dataset_id": "sg-news-2026-01-25-0001", "country": "SG", "category": "news", "discovered_at": "2026-01-25T03:12:00Z", "research_methods": ["google_search", "crtsh"], "queries": ["Singapore government news site:.gov.sg"], "record_count": 8 }, "records": [ { "raw_url": "https://www.mom.gov.sg/newsroom", "normalized_domain": "mom.gov.sg", "domain_id": "gov:sg:mom.gov.sg", "source_type": "gov", "discovery_method": "google_search", "confidence": 0.95, "content_hints": ["news", "government_content"] } ]}🚀 Research 워크플로우
섹션 제목: “🚀 Research 워크플로우”[API Request] POST /api/v1/queues/research │ ▼[Queue Batch Creation] → D1에 배치 메타데이터 저장 │ ▼[Queue Consumer] → 메시지 배치 처리 │ ▼[Domain Functions] ├── discoverUrlsFromSource() ├── createResearchOutput() └── generateDatasetId() │ ▼[Storage] ├── R2 (Raw datasets) ├── D1 (Metadata, batch state) └── GitHub (Audit trail)🔌 Research API 엔드포인트
섹션 제목: “🔌 Research API 엔드포인트”| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/research | Research 출력 목록 조회 |
| GET | /api/v1/research/:country/:category/:date | 특정 Research 조회 |
| POST | /api/v1/research | Research 출력 생성 |
| POST | /api/v1/queues/research | Research 배치 생성 |
🌱 Seed 엔진 (수집 계약 생성 단계)
섹션 제목: “🌱 Seed 엔진 (수집 계약 생성 단계)”🎯 핵심 철학
섹션 제목: “🎯 핵심 철학”“Seed Engine defines HOW to fetch.”
Seed 엔진은 Research 엔진이 발견한 URL들을 기반으로 **수집 계약(Contract)**을 생성합니다.
📁 데이터 구조 (Raw/Prod 2단계)
섹션 제목: “📁 데이터 구조 (Raw/Prod 2단계)”seed-engine/├── raw/country=sg/category=news/date=2026-01-28/│ ├── raw_0001.json # Research 엔진 출력을 입력으로 받음│ ├── raw_0002.json│ ├── raw_metadata.json│ └── raw_NNNN.json.success # 처리 완료 체크포인트└── prod/country=sg/category=news/date=2026-01-28/{domain}/ ├── domain_metadata.json # 도메인별 수집 메타데이터 ├── robots.txt # 수집된 robots.txt ├── sitemap.xml # 수집된 sitemap.xml └── domain_metadata.json.success🔧 주요 기능
섹션 제목: “🔧 주요 기능”✅ Seed 엔진이 하는 일
섹션 제목: “✅ Seed 엔진이 하는 일”- Raw 데이터 처리: Research 엔진 출력을 입력으로 받아 처리
- 도메인별 그룹화: URL들을 registrable_domain 기준으로 그룹화
- Technical 메타데이터 수집:
robots.txt다운로드 및 분석sitemap.xml수집- 서버 응답 헤더 분석
- Seed 계약 생성: 실제 스크래핑을 위한 기술적 계약서 작성
- 체크포인트 시스템:
.success파일을 통한 idempotent 처리
❌ Seed 엔진이 하지 않는 일
섹션 제목: “❌ Seed 엔진이 하지 않는 일”- URL 발견 (Research 엔진의 역할)
- 실제 콘텐츠 스크래핑 (Scraper 엔진의 역할)
- 콘텐츠 품질 평가
🔄 Seed 워크플로우 (3단계)
섹션 제목: “🔄 Seed 워크플로우 (3단계)”Step 1: Orchestrator
섹션 제목: “Step 1: Orchestrator”POST /api/v1/seeds/orchestrate// R2에서 raw/ 파일들을 스캔하여 SEED_QUEUE로 전송
Input: R2: raw/.../raw_NNNN.jsonOutput: SEED_QUEUE 메시지들Step 2: File Processor (SEED_QUEUE)
섹션 제목: “Step 2: File Processor (SEED_QUEUE)”// 입력: raw/country=sg/category=news/date=2026-01-28/raw_0001.json// 처리: JSON 파싱 → 도메인별 그룹화// 출력: DOMAIN_QUEUE 메시지들 + .success 체크포인트
{ file_path: "raw/country=sg/category=news/date=2026-01-28/raw_0001.json", partition_info: { country: "sg", category: "news", date: "2026-01-28" }}Step 3: Domain Collector (DOMAIN_QUEUE)
섹션 제목: “Step 3: Domain Collector (DOMAIN_QUEUE)”// 입력: 도메인별 URL 그룹// 처리: robots.txt, sitemap.xml 수집// 출력: prod/{domain}/domain_metadata.json + 증거 파일들
const { domain, urls, partition_info } = message;// robots.txt, sitemap.xml 수집 후 prod/에 저장📊 Seed 데이터 예시
섹션 제목: “📊 Seed 데이터 예시”{ "domain": "mom.gov.sg", "urls": [ { "url": "https://mom.gov.sg/employment-practices/employment-act", "title": "Employment Act - Ministry of Manpower" } ], "robots_txt_size": 1024, "sitemap_xml_size": 2048, "processed_at": "2026-01-30T10:00:00.000Z"}🔌 Seed API 엔드포인트
섹션 제목: “🔌 Seed API 엔드포인트”| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/seeds/orchestrate | Seed 처리 오케스트레이션 |
| GET | /api/v1/seeds/status | 처리 상태 조회 |
🔗 엔진 간 연결 및 데이터 흐름
섹션 제목: “🔗 엔진 간 연결 및 데이터 흐름”📊 전체 데이터 파이프라인
섹션 제목: “📊 전체 데이터 파이프라인”┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ Research │ │ Seed │ │ Scraper ││ Engine │───▶│ Engine │───▶│ Engine ││ │ │ │ │ ││ "어디서 찾을까?" │ │ "어떻게 가져올까?"│ │ "실제로 수집" │└─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ ▼ ▼ ▼research/datasets/ raw/ + prod/ final/content/- URL 발견 - 기술 메타데이터 - 실제 콘텐츠- 도메인 정규화 - robots.txt - 구조화된 데이터- 생존성 확인 - sitemap.xml - 최종 산출물🔄 역할 분리 원칙
섹션 제목: “🔄 역할 분리 원칙”| 엔진 | 입력 | 처리 | 출력 | 책임 |
|---|---|---|---|---|
| Research | 검색 쿼리, 도메인 힌트 | URL 발견, 도메인 정규화 | research/datasets/*.json | ”어디서 찾을까?” |
| Seed | Research 출력 | 기술 메타데이터 수집 | raw/, prod/ | ”어떻게 가져올까?” |
| Scraper | Seed 출력 | 실제 콘텐츠 수집 | final/content/ | ”실제로 수집” |
📋 Taxonomy (분류 체계)
섹션 제목: “📋 Taxonomy (분류 체계)”Content Nature (콘텐츠 성격)
섹션 제목: “Content Nature (콘텐츠 성격)”news: 시간에 민감한 뉴스policy: 법률, 규정, 시스템guide: 사용법, 지침서faq: Q&A 구조화된 정보data: 수치/통계/원시 데이터research: 학술/연구 논문announcement: 단순 공지, 이벤트directory: 목록형 정보opinion: 논평, 칼럼alert: 긴급/경고 정보
Source Identity (출처 정체성)
섹션 제목: “Source Identity (출처 정체성)”government: 정부 기관organization: 일반 조직ngo: 비정부기구company: 기업
Medium (전달 형식)
섹션 제목: “Medium (전달 형식)”web: 일반 웹 페이지social: 소셜 미디어video: 비디오 콘텐츠audio: 팟캐스트document: PDF, DOC 파일
🛠️ 기술적 구현
섹션 제목: “🛠️ 기술적 구현”🗄️ 스토리지 분리
섹션 제목: “🗄️ 스토리지 분리”R2 버킷 구조:├── research/datasets/ # Research 엔진 출력├── research/liveness/ # 생존성 확인 결과├── research/blocked/ # 차단된 도메인├── research/dead/ # 죽은 도메인├── raw/ # Seed 엔진 입력 (불변)├── prod/ # Seed 엔진 출력 (파이프라인 산출물)└── final/ # Scraper 엔진 출력 (최종 콘텐츠)⚡ Queue 시스템
섹션 제목: “⚡ Queue 시스템”Research 엔진:├── RESEARCH_QUEUE → URL 발견 작업└── LIVENESS_QUEUE → 도메인 생존성 확인
Seed 엔진:├── SEED_QUEUE → Raw 파일 처리└── DOMAIN_QUEUE → 도메인별 메타데이터 수집🔄 체크포인트 시스템
섹션 제목: “🔄 체크포인트 시스템”Idempotent 처리를 위한 .success 파일:├── raw_0001.json.success # Seed 처리 완료├── domain_metadata.json.success # Domain 수집 완료└── liveness_check.json.success # 생존성 확인 완료🏗️ 아키텍처 레이어
섹션 제목: “🏗️ 아키텍처 레이어”Routes Layer (HTTP)├── /api/v1/research/* # Research API└── /api/v1/seeds/* # Seed API
Domain Layer (비즈니스 로직)├── research/ # Research 도메인 함수└── seed/ # Seed 도메인 함수
Infrastructure Layer (Cloudflare)├── r2/ # R2 스토리지 어댑터├── d1/ # D1 데이터베이스 어댑터├── queues/ # Queue 핸들러└── kv/ # KV 캐시 어댑터🎯 핵심 차이점 요약
섹션 제목: “🎯 핵심 차이점 요약”| 측면 | Research 엔진 | Seed 엔진 |
|---|---|---|
| 목적 | URL 발견 | 수집 계약 생성 |
| 입력 | 검색 쿼리, 힌트 | Research 출력 |
| 출력 | URL 목록 | 기술 메타데이터 |
| 판단 | 하지 않음 (발견만) | 기술적 분석 |
| 스토리지 | research/ | raw/, prod/ |
| 불변성 | 완전 불변 | Raw 불변, Prod 갱신 가능 |
| 의존성 | 외부 검색 API | Research 출력 |
| 처리 방식 | 배치 처리 | 스트리밍 파이프라인 |
| 체크포인트 | 배치 레벨 | 파일/도메인 레벨 |
🚀 운영 특징
섹션 제목: “🚀 운영 특징”Research 엔진
섹션 제목: “Research 엔진”- 스케줄링: 정기적 배치 실행 (일 1-2회)
- 확장성: 국가/카테고리별 병렬 처리
- 모니터링: 배치 성공률, 발견된 URL 수
- 실패 처리: DLQ를 통한 재처리
Seed 엔진
섹션 제목: “Seed 엔진”- 트리거: Research 출력 기반 이벤트 드리븐
- 확장성: 파일/도메인별 병렬 처리
- 모니터링: 처리 진행률, 메타데이터 수집 성공률
- 실패 처리: 체크포인트 기반 재시작
🎉 결론
섹션 제목: “🎉 결론”이 2단계 분리를 통해 각 엔진이 명확한 책임을 가지며, 독립적으로 개발/테스트/확장할 수 있습니다:
- Research 엔진: “무엇을 찾을까”에 집중
- Seed 엔진: “어떻게 가져올까”에 집중
이러한 관심사의 분리(Separation of Concerns)를 통해 시스템의 복잡성을 관리하고, 각 엔진의 전문성을 극대화할 수 있습니다.