---
date: 2026-07-06
project: knowledge-base
type: feature
status: active
tags:
  - ai-agent
  - 경쟁력
  - rag
  - crawling
  - freshness
related:
  - "[[에이전트 경쟁력 모델]]"
  - "[[레이턴시 엔지니어링]]"
---

# 실시간 지식 파이프라인

> [!NOTE] 요약
> "매일 갱신되는 자사 홈페이지를 크롤링해 CS 에이전트가 항상 최신 정보를 답한다"의 핵심은 크롤러가 아니라 **변경 감지 → 증분 인덱싱 → 신선도 인지 검색**의 3단 배선이다. 평시엔 증분(바뀐 것만 즉시), 주기적으로 전체 대조(reconciliation)로 누락을 복구한다. 엄밀히는 "실시간"이 아니라 **near-real-time**이며, 본질은 "원천 변경 → 답변 반영"의 end-to-end 시차를 정의하고 SLA로 관리하는 것이다.

## 전체 아키텍처

```mermaid
graph LR
    subgraph 수집
        A[Sitemap / RSS<br/>CMS Webhook] --> B[변경 감지<br/>lastmod·해시 비교]
        B -->|변경분만| C[크롤러 fetch]
    end
    subgraph 처리
        C --> D[파싱·정제<br/>본문 추출]
        D --> E[청킹 + 메타데이터<br/>updated_at·source_url]
        E --> F[임베딩]
    end
    subgraph 저장·서빙
        F --> G[(벡터DB<br/>새 버전 삽입→전환→구버전 정리)]
        B -->|삭제 감지| G
        G --> H[신선도 인지 RAG]
        B -.->|무효화 이벤트| I[시맨틱 캐시]
        H --> J[CS 에이전트 답변<br/>+ 기준 시점 명시]
    end
```

## 1. 변경 감지 — 파이프라인의 심장

전체 사이트를 매번 다시 긁으면 ① 느리고 ② 원 서버에 부담이고 ③ 임베딩 비용이 폭증한다. **바뀐 페이지만 식별**하는 게 먼저다.

| 방법 | 신선도 | 비용 | 적용 조건 |
|------|-------|------|----------|
| **CMS/DB Webhook** | 초~분 (최상) | 최저 | 자사 시스템 — 가능하면 무조건 이것 |
| Sitemap `lastmod` | 크롤 주기 | 낮음 | sitemap이 정직하게 관리될 때 |
| RSS/Atom 피드 | 분 | 낮음 | 공지·블로그류 |
| 콘텐츠 해시 비교 | 크롤 주기 | 중간 | lastmod 못 믿을 때 — fetch 후 본문 해시 비교, 동일하면 하류 스킵 |
| HTTP ETag / Last-Modified | 크롤 주기 | 낮음 | 서버가 지원할 때, 조건부 요청으로 fetch 자체 절약 |

> [!TIP] 자사 사이트라는 이점을 써라
> "자사 홈페이지 크롤링"이 과제라면 사실 크롤링이 최선이 아닐 수 있다. CMS에 발행/수정 webhook을 걸면 크롤러 없이 분 단위 신선도가 나온다. **크롤링은 원천 시스템에 손댈 수 없을 때의 차선책**이다. 컨설팅에서 이 질문("원천에 webhook 걸 수 있나요?") 하나로 아키텍처가 바뀐다. 단 webhook도 공짜는 아니다 — 초안/발행 구분, 예약 발행, 중복·역순 이벤트, 실패 재시도(DLQ)까지 배선해야 신뢰할 수 있다.

## 2. 증분 인덱싱

- **upsert 단위 = 문서 ID**: **CMS/DB의 원본 ID가 최우선** — URL은 개편·canonical 변경에 깨지므로 `source_url + 앵커`는 원본 ID를 못 얻을 때의 차선이다. 변경 시 해당 문서의 청크를 통째로 교체한다(청크 단위 부분 갱신은 경계가 어긋나 유령 청크를 남긴다). 단 "삭제 후 재삽입" 사이의 **검색 공백**을 피하려면 순서를 뒤집는다: 새 버전 삽입 → 검색 대상 전환 → 구버전 삭제 (버전 필드 또는 soft delete).
- **삭제 전파**: 사이트에서 내려간 페이지(404, sitemap에서 제거)는 인덱스에서도 지운다. "단종 상품을 계속 안내"하는 사고의 단골 원인이 삭제 미전파다.
- **메타데이터 필수 필드**: `doc_id`(원본 ID), `version`, `source_url`, `updated_at`, `crawled_at`, `content_hash`, `doc_type`(FAQ/공지/상품) + 도메인에 따라 `effective_at`/`expires_at`(규정·프로모션), `authority`(출처 권위), `acl`/`tenant_id`(권한), `locale`(다국어). 아래의 신선도 인지 검색·권한 필터·캐시 무효화는 전부 이 필드들 위에서만 동작한다 — 여기서 빠뜨리면 뒤에서 구현 불가.
- **버전 스위칭**: 대규모 개편 시엔 새 인덱스를 옆에 빌드하고 alias 전환 — 반영 중 반쪽짜리 검색 결과 방지.
- **주기적 reconciliation**: 증분만 믿으면 놓친 변경·삭제가 조용히 쌓인다. 주기적으로(예: 주 1회) 원천 전체 목록과 인덱스를 대조해 누락을 복구한다. 파서 로직·청킹 규칙·임베딩 모델을 바꿨을 때의 전체 재빌드 경로이기도 하다 — "증분이 기본, 전체 대조가 안전망".

## 3. 신선도 인지 RAG

인덱스가 최신이어도 검색과 생성이 그걸 못 살리면 소용없다. (검색 자체는 벡터 단독보다 하이브리드(BM25+벡터)+re-rank가 기본값 — 04_RAG의 04_검색·05_리랭킹 문서 참조. 여기서는 신선도 관점만 다룬다.)

- **Recency 가중**: 유사도 점수에 시간 기반 보정. 동일 주제의 구 공지 vs 새 공지가 있으면 새 것이 이겨야 한다(일반 지식은 가중 약하게, 요금·정책·이벤트는 강하게 — doc_type별 차등). 단 `updated_at`(수정 시각)만으론 부족한 도메인이 있다 — 규정·약관·프로모션은 **`effective_at`(발효일)·`expires_at`(만료일)·출처 권위**를 함께 필터·가중해야 "최신이지만 아직 발효 전" 같은 오답을 막는다.
- **모순 해소 규칙**: 검색 결과에 상충 정보가 섞이면 우선순위 규칙을 프롬프트에 명시 — 기본은 "**발효 중**(`effective_at` 도래, `expires_at` 미도래)이고 **권위 높은** 출처 우선, 그 안에서 최신 우선". 단순 "updated_at 최신 우선"은 아직 발효 전인 새 약관을 고르는 오답을 만든다.
- **기준 시점 노출**: 답변에 "2026-07-05 공지 기준"처럼 출처·시점을 붙인다. 신뢰를 만들고, 틀렸을 때 원인 추적이 된다.
- **캐시 무효화 연동**: 변경 감지 이벤트 발생 시 해당 문서와 연관된 시맨틱 캐시 엔트리를 무효화 → [[레이턴시 엔지니어링]]. "연관"을 찾는 실행 가능한 방식은 **답변 생성 시 참조한 doc_id 목록을 캐시 엔트리에 의존성으로 저장**해두는 것이다(임베딩 유사도로 사후 추정하는 건 부정확). 이 배선이 없으면 "인덱스는 최신인데 답은 낡은" 상태가 된다.

## 4. 신선도를 SLA로 만들기

경쟁력은 측정될 때만 관리된다.

> [!SUCCESS] 예시 신선도 SLA
> - 원천 변경 → 답변 반영: webhook 경로 **10분 내**, 크롤 경로 **1시간 내** (p95)
> - 삭제된 페이지 인용 incident: 0건/주 — 측정 정의를 고정할 것(예: 주간 샘플링 평가 + 신고 접수 기준. "전체 트래픽에서 0건"은 검증 불가능한 약속이다)
> - 파이프라인 실패 알림: 5분 내

측정 방법: 변경 이벤트에 타임스탬프를 찍고, 반영 후 해당 내용을 묻는 **카나리 질문**을 자동 실행해 새 정보가 답에 나오는지 확인한다. 이 카나리 질문셋 자체가 회귀 테스트 자산이 된다 → [[RAG Evaluation]].

## 5. 운영 함정 체크리스트

- [ ] **파서 취약성**: 사이트 개편 한 번에 본문 추출이 통째로 깨진다. "추출 본문 길이 급감" 알림을 걸어라 — 가장 흔한 조용한 장애.
- [ ] **robots.txt·크롤링 예절**: 자사여도 rate limit 준수. 새벽 전체 크롤 + 주간 증분이 일반적 조합.
- [ ] **JS 렌더링 페이지**: 정적 fetch로 빈 본문이 들어오는지 확인. 필요 시 헤드리스 브라우저, 단 비용 10배각.
- [ ] **중복·정규화**: 같은 내용의 print 버전·UTM 붙은 URL이 별개 문서로 들어와 검색을 오염시킴 — canonical URL로 정규화.
- [ ] **임베딩 모델 교체 대비**: 모델 바꾸면 전체 재임베딩. `embedding_model` 필드를 메타데이터에 남겨두면 점진 마이그레이션 가능.
- [ ] **조용한 파이프라인 정지**: 크롤러가 죽어도 에이전트는 멀쩡히 (낡은) 답을 한다. "마지막 성공 실행 시각" 모니터링 필수.
- [ ] **오염된 원천·간접 프롬프트 인젝션**: 크롤링한 페이지 속 텍스트는 신뢰할 수 없는 데이터다. 문서 안의 지시문("이전 지시를 무시하고…")이 에이전트의 지시로 승격되지 않게 컨텍스트에서 데이터로 격리한다 → [[Prompt Injection]], [[가드레일]].
- [ ] **권한·비공개 문서 격리**: 내부 문서·고객 등급별 정보가 한 인덱스에 섞이면 ACL 메타데이터로 검색 단계에서 필터해야 한다. "권한 없는 문서 인용" 사고는 신선도 사고보다 치명적이다.

## 관련 문서

- [[에이전트 경쟁력 모델]] — 신선도가 경쟁력 축인 이유
- [[레이턴시 엔지니어링]] — 캐시 무효화 배선
- [[RAG Evaluation]] · [[Hallucination Detection]] — 반영 검증
- [[문서 수집과 파싱]] 외 04_RAG 인덱싱 단계 문서들 (01_수집파싱~03_임베딩인덱싱)
