축적되는 인텔리전스: 우리 AI 뉴스봇이 더 이상 잊지 않게 된 이유

AI SOTA Feed Bot은 하루 3번 돌아갑니다. 24개 소스를 스크래핑하고, 랭킹을 매겨서 상위 AI 뉴스를 보여줍니다.

최근까지는 매 실행마다 이전 결과를 덮어쓰기 했습니다. 오전 9시 결과는 정오 실행이 끝나면 사라졌습니다. 이 봇은 기억 없이 매번 새로 시작하는 구조였습니다.

단순 대시보드로는 괜찮지만 지난 흐름을 돌아봐야 하는 순간에는 치명적입니다.


휘발성 피드의 한계

실행 사이의 기록이 남지 않으면 이런 기본적인 질문에도 답하기 어려워집니다.

  • 이번 주 AI 뉴스에서 진짜 큰 이슈는 뭐였지?
  • 며칠 연속으로 계속 등장한 논문은 뭐였을까?
  • 지난달 흐름은 어땠나?
  • 연말 회고에서 무엇을 근거로 정리할 것인가?

그리고 중요한 시그널도 사라집니다. 8회 연속 등장한 글은 1회 등장한 글과 무게감이 완전히 다르기 때문입니다. 누적 저장은 등장 빈도 자체를 유의미한 랭킹 신호로 바꿔줍니다.

그래서 Harry와 함께 축적 레이어를 만들었습니다.


아키텍처: 스냅샷 + 중복 제거 + 시간 윈도우

실행마다 스냅샷 저장

파이프라인 종료 시 write_run_snapshot()이 호출되어 두 가지 작업을 합니다:

  1. 전체 결과를 data/processed/runs/<timestamp>.json에 저장
  2. runs_index.json 업데이트 (최신순, 최대 500개)

각 스냅샷에는 실행 시각, 아이템 개수, 점수와 요약이 담긴 아이템 배열이 온전히 들어갑니다.

data/processed/
├── latest.json              ← 하위 호환용 유지
├── runs_index.json          ← 스냅샷 인덱스
└── runs/
    ├── 20260216-080057.json
    ├── 20260216-090315.json
    ├── 20260216-120003.json
    └── ...

API가 시간 범위를 받습니다

/api/feed는 이제 from, to, limit 쿼리를 지원합니다.

/api/feed?from=2026-02-10T00:00:00Z&to=2026-02-16T23:59:59Z&limit=50

지정한 범위에 맞는 스냅샷만 골라서 병합합니다.

중복 제거와 히스토리 유지

중심에는 accumulateItems() 함수가 있습니다. 이 함수는 url + title 복합 키로 중복 제거를 하면서 아래 필드를 추적합니다.

  • first_seen: 처음 등장한 시각
  • last_seen: 가장 최근 등장 시각
  • seen_count: 몇 번의 실행에서 등장했는지

중복이 발견되면 최신 실행의 메타데이터를 우선 적용하되, 히스토리는 그대로 누적합니다.

결과는 last_seen 내림차순으로 정렬되어 최근 활성 아이템이 먼저 올라옵니다.


20개 실행만으로도 보이는 변화

누적 저장을 갓 시작했을 때(20개 스냅샷) 데이터가 아직 많지 않았는데도, 시간 범위 조회가 벌써 꽤 유용했습니다.

  • 최근 6시간 조회: 지금 막 뜨는 이슈만 확인
  • 최근 48시간 조회: 반복 등장한 아이템이 seen_count로 명확히 드러남

앞으로 데이터가 쌓이면(하루 3회, 주 21회, 월 약 90회) 그 가치가 훨씬 커집니다.


다음에 가능해지는 것들

이 기능은 앞으로 만들 것들의 기반 레이어입니다.

주간 리캡

from=월요일, to=일요일로 조회해서 seen_count 기준으로 상위 정렬하면 됩니다. 한 주 동안 15회 이상 등장한 이슈는 그 주를 지배한 핵심 스토리로 봐도 됩니다.

월간 트렌드

약 90회 실행 데이터를 보면 흐름이 보입니다:

  • 어떤 소스가 꾸준히 고품질 아이템을 공급하는지
  • 어떤 카테고리(플랫폼, 릴리즈, 연구)가 오르내리는지
  • 어떤 토픽(에이전트 엔지니어링, 추론 최적화, 신모델)이 강세인지

연말 회고

연말이면 약 1,000개 실행 스냅샷이 생깁니다. 느낌이나 기억에 기대는 대신 타임스탬프가 찍힌 근거로 2026 AI 회고를 만들 수 있게 됩니다.

빈도 기반 시그널

seen_count는 지금도 강력한 신호입니다.

  • 1회: 일회성 소식이거나 매우 최신 글
  • 5~10회: 며칠간 꾸준히 언급되는 주목할 만한 글
  • 20회 이상: 주간이나 월간 단위의 핵심 이슈

향후 랭킹에서 LLM relevance 점수와 함께 가중치로 쓰기 좋습니다.


지루하지만 중요한 운영 포인트

하위 호환

스냅샷이 없으면 API는 기존 latest.json으로 자동 폴백하고 seen_count: 1로 감싸서 반환합니다. 기존 사용처가 깨질 일은 없습니다.

인덱스 상한

runs_index.json은 최대 500개로 제한하는데 하루 3회 기준 약 5.5개월 분량입니다. 인덱스만 순환하고 실제 스냅샷 파일은 유지되므로 언제든 복구할 수 있습니다.

그레이스풀 디그레이데이션

인덱스가 잘리거나 깨져도 API는 runs/ 디렉터리에서 다시 읽어옵니다. 안전장치가 이중으로 들어가 있습니다.


중요한 설계 선택

뉴스 피드는 보통 “최신만 보여줘”에 맞춰지기 쉽습니다. 실시간, 항상 최신, 매번 교체하는 방식입니다.

하지만 진짜 가치 있는 데이터 제품은 기억합니다. 과거를 잊는 검색 엔진은 개인화할 수 없고 과거를 덮어쓰는 피드는 무엇이 중요했는지 알려줄 수 없습니다.

이번 변화 자체는 작았습니다. 함수 하나, 디렉터리 하나, 쿼리 파라미터 몇 개가 전부였습니다.

그런데 이 작은 변화로 봇의 성격이 완전히 바뀌었습니다. 단순한 피드가 아니라 시간축 위에서 축적되는 AI 변화의 기록이 되었습니다.

코드 diff에서는 작아 보여도, 제품의 미래를 바꾸는 종류의 변경이었습니다.