개인 도구에서 제품으로: AI 뉴스봇 확장기

이 글은 AI 뉴스봇을 이틀 만에 만들었다의 후속편입니다. 요약하면 이렇습니다. 코딩 에이전트 Harry와 함께 개인용 AI 뉴스 큐레이터를 만들고 15번 넘게 반복하면서 슬롯 기반 v2 랭킹 엔진을 완성해서 매일 텔레그램으로 다이제스트를 받고 있었습니다.

v2 엔진은 안정적이었고 결과물도 꽤 마음에 들어서 실제로 매일 쓰고 있었습니다.

그러다 당연한 질문이 떠올랐습니다. 이걸 왜 나만 쓰지?

라이브 피드는 여기 있습니다: llm-digest.com


파이프라인 강화

공개하기 전에 파이프라인을 더 단단하게 만들어야 했기에 Harry한테 전체 시스템을 처음부터 끝까지 리뷰하고 뭘 고쳐야 하는지 봐달라고 했습니다.

손본 것들:

  • 설정 프리셋: 모든 설정값을 세세하게 알지 못해도 튜닝할 수 있도록 표준화한 설정
  • 상세한 진단 정보: 매 실행마다 슬롯 우선순위, LLM 사용량, 소스 상태, 타이밍 분석을 상세하게 기록
  • Git 정리: 불필요하게 추적되던 런타임 아티팩트 정리 및 .gitignore 정비
  • 슬롯 쿼터 재조정: 전체 아이템 수 증가 및 슬롯별 할당량 조정

개별적으로는 사소해 보이지만 “내 컴퓨터에서는 돌아감”과 “실제 환경에서 안정적으로 돌아감” 사이의 차이를 만드는 작업들입니다.


Vercel 전환

Harry한테 물어봤습니다. “이걸 Vercel에 배포해서 다른 사람들도 피드를 볼 수 있게 하면 어떨까?”

보통이라면 데이터베이스를 세팅하고, API를 만들고, 별도 서버를 띄우는 방향으로 가기 쉬운데, Harry는 훨씬 단순한 방법을 제안했습니다. GitHub를 콘텐츠 저장소로 쓰자는 것이었습니다.

생각해보면 피드 아티팩트(다이제스트, 처리된 JSON, 진단 정보)는 이미 레포지토리에 쌓이고 있고 매 실행마다 업데이트됩니다. 그러니 그 파일들을 읽어서 렌더링하는 정적 사이트만 있으면 충분합니다.

그래서 만든 구조는 이렇습니다. 이 블로그와 같은 Astro 엔진이 피드를 웹 페이지로 렌더링하고 GitHub가 데이터베이스 역할을 하며 Vercel이 push할 때마다 자동으로 배포합니다. 관리할 서버가 없습니다.


브라우저로 소스 탐색하기

여기서부터 작업이 꽤 재미있어졌습니다. RSS 피드 말고 X, Medium, Substack에서도 양질의 콘텐츠를 찾고 싶었기 때문입니다. 보통은 공식 API 연동부터 떠올리기 쉬운데, API에는 토큰 발급, 속도 제한, 지속적인 유지보수 비용이 따라옵니다.

대신 Harry에게 브라우저를 쥐여주고 제 계정으로 직접 둘러보게 했습니다. “직접 돌아다니면서 좋은 소스 좀 찾아봐.”

찾아낸 소스들

Medium: 팔로잉 피드에서 훌륭한 엔지니어링 퍼블리케이션들을 건졌습니다:

  • Netflix TechBlog
  • Airbnb Tech Blog
  • Pinterest Engineering

여기서 얻은 인사이트: 노이즈를 거르려면 팔로잉 피드 원본을 그대로 긁지 말고 퍼블리케이션 단위 화이트리스트를 써야 합니다.

Substack: 가장 신호가 뚜렷했습니다. 홈 스트림에서 바로 발견한 소스들:

  • Alberto Romero (The Algorithmic Bridge)
  • Steve Yegge
  • Kent Beck

품질은 높고 노이즈는 적어서 피드에 바로 추가할 만한 소스들이었습니다.

X: 건질 건 있지만 노이즈가 너무 심합니다. 즉흥적인 핫테이크와 진짜 인사이트가 마구 섞여 있어서 훨씬 더 정교한 필터링이 필요했습니다.

결정: 소셜 플랫폼 수집기는 뒤로 미루기로 했습니다. RSS 기반 소스만으로도 이미 탄탄한 데다 소셜 플랫폼은 인증과 속도 제한, 콘텐츠 추출 복잡도가 아직은 효용에 비해 과하기 때문입니다. 그래도 나중에 필요할 때 어디를 파야 할지는 명확해졌습니다.


스케줄링: 클라우드 떠나기

파이프라인은 원래 GitHub Actions의 크론 트리거로 단순하게 돌렸습니다. 그런데 문제가 생겼습니다. LLM 연동은 로컬 OAuth(pi-ai)를 쓰는데 GitHub Actions 러너에서는 이 브라우저 인증 환경이 돌아가지 않습니다.

그래서 스케줄링을 전부 로컬 크론으로 옮겼습니다. 일정은 OpenClaw가 직접 관리합니다:

  • 09:00 KST: 아침 다이제스트
  • 12:00 KST: 점심 리프레시
  • 19:00 KST: 저녁 다이제스트

하루 세 번. 이 분야가 움직이는 속도를 생각하면 충분히 납득할 만한 주기입니다.

GitHub Actions는 수동 트리거용으로 남겨뒀지만 일상적인 실행은 온전히 로컬에서 끝납니다.


자동 배포 루프 완성하기

예상치 못했던 복병도 있었습니다. 로컬 크론 실행이 Vercel 배포를 자동으로 트리거하지 않는다는 점이었습니다.

파이프라인은 로컬에서 돌면서 다이제스트 파일을 갱신하고, 텔레그램과 GitHub Issues에 발행하는 데까지는 잘 해냅니다. 하지만 Vercel은 main 브랜치에 push가 있어야만 다시 배포하는데 로컬 실행만으로는 원격에 push가 발생하지 않습니다.

Harry가 깔끔한 파이프라인을 짰습니다:

파이프라인 실행
    ↓
다이제스트 빌드
    ↓
git pull --rebase --autostash  (동기화 유지)
    ↓
변경된 아티팩트 커밋
    ↓
main에 git push
    ↓
Vercel 자동 배포 트리거
    ↓
텔레그램 + GitHub Issue 발행

이제 매 크론 실행 → git push → Vercel 재배포 → 공개 웹 피드 업데이트까지 전체 루프가 매끄럽게 이어집니다.

배포 없이 테스트만 돌리고 싶을 때를 대비해 AUTO_PUSH_RUNTIME=0 킬 스위치도 달아뒀습니다.


패턴

하루 만에 이 프로젝트는 “나한테 알림을 보내주는 개인 도구”에서 “공개 웹 페이지, 하루 3회 자동 갱신, 로컬 실행과 클라우드 배포가 맞물리는 파이프라인을 갖춘 제품”으로 바뀌었습니다.

작업할 때마다 결국 같은 패턴으로 돌아옵니다:

  1. 먼저 나를 위해 만듭니다. 사용자라는 추상적인 대상을 상상하지 말고 내 불편부터 해결합니다.
  2. 결과물이 좋을 때까지 반복합니다. 코드 자체보다 내가 실제로 보고 쓰는 결과물의 품질이 먼저입니다.
  3. 제대로 작동할 때 비로소 일반화합니다. 기반이 탄탄하면 개인 도구에서 공개 제품으로의 확장은 생각보다 가볍습니다.
  4. 아키텍처는 지루하게 유지합니다. GitHub가 데이터베이스, Vercel이 정적 서빙, 로컬 크론이 스케줄링을 맡습니다. 쿠버네티스도, 메시지 큐도, 마이크로서비스도 필요 없습니다.

가장 지루한 스택이 결국 배포까지 가는 스택입니다.


다음 단계

  • 웹 피드: 일일 다이제스트를 보여주는 공개 Astro 사이트 (진행 중)
  • RSS 출력: 개인 리더기에서 구독할 수 있도록 지원
  • 다국어 요약: 한국어와 영어 버전 병행 제공
  • 추가 소스: Substack, Medium 연동
  • 오픈소스 공개: 거친 부분을 가다듬고 나면 파이프라인 자체를 다른 사람들도 쓸 수 있게 공개

이 도구는 계속 자라고 있습니다. 시작은 중요한 뉴스를 놓치기 싫었던 엔지니어 한 명의 답답함이었습니다. 모든 건 거기서 자연스럽게 이어져 나왔습니다.