AI 소식을 매일 수집해 Discord로 보내주는 요약 봇을 만들었습니다
요즘 AI 관련 소식은 올라오는 속도도 빠르고, 채널도 너무 다양합니다.
OpenAI 공식 뉴스, Claude Code 릴리즈, 주요 X 계정까지 각각 직접 확인하다 보니 생각보다 반복 비용이 크다고 느꼈고, 그래서 필요한 정보만 모아서 매일 한 번에 보내주는 작은 요약 봇을 만들어보게 됐습니다.
이번에 만든 프로젝트는 ai-signal-digest입니다.
GitHub:
https://github.com/blacknabis/ai-signal-digest
이 프로젝트는 기본적으로 아래 흐름으로 동작합니다.
config/sources.json에 등록된 소스를 읽습니다.- RSS / HTML / X RSS-compatible feed에서 최신 항목을 수집합니다.
- SQLite 상태 저장소를 기준으로 이미 본 항목을 제외합니다.
- 수집한 항목을 한국어 digest 형태로 정리합니다.
- Discord 웹훅으로 하루 1회 전송합니다.
기능 자체는 단순해 보이지만, 실제로는 "운영 가능한 자동화"가 되도록 구조를 나누는 데 조금 더 신경을 썼습니다. 한 파일에 전부 몰아넣기보다는, 수집과 상태 관리, 요약, 전송이 서로 독립적으로 바뀔 수 있도록 분리했습니다.
핵심 구성
cli.py- 실행 진입점입니다.
service.py- 수집, dedupe, enrichment, render, delivery까지 전체 파이프라인을 오케스트레이션합니다.
state.py- 중복 방지를 위한 SQLite 상태 저장소입니다.
collectors/rss.py,collectors/html.py- 소스 종류에 따라 수집 책임을 분리했습니다.
enrichment.py- 한국어 fallback 요약과 선택형 번역 처리를 담당합니다.
digest.py- Discord에 맞는 최종 메시지 포맷을 만듭니다.
discord.py- Discord 웹훅 전송과 메시지 chunking을 처리합니다.
이렇게 나눈 이유는 명확합니다. 예를 들어 X 수집 방식이 바뀌더라도 collector만 수정하면 되고, 요약 형식을 바꾸고 싶으면 digest/enrichment만 손보면 되도록 하기 위해서입니다. 실제로 만들다 보니 이런 분리가 나중 수정에 꽤 도움이 됐습니다.
상태 관리와 중복 방지
상태 저장은 SQLite를 사용했습니다.
이 프로젝트에서 중요한 건 "새 소식만 보내는 것"이기 때문에, 단순히 마지막 실행 시각만 저장하는 방식보다 항목별 상태를 저장하는 쪽이 더 안전하다고 판단했습니다.
현재는 seen, delivered, suppressed 개념을 나눠서 관리합니다.
seen- 한 번이라도 수집된 항목
delivered- Discord로 실제 전송된 항목
suppressed- 첫 실행 시 오래된 글처럼 의도적으로 제외한 항목
이렇게 분리해두면 Discord 전송 실패가 생겨도 수집 결과를 잃지 않고, 이후 재시도도 더 자연스럽게 처리할 수 있습니다.
또 처음 실행할 때 기존 글이 한꺼번에 쏟아지는 문제를 막기 위해 bootstrap 보호 장치도 넣었습니다.
BOOTSTRAP_LOOKBACK_HOURSBOOTSTRAP_MAX_ITEMS_PER_SOURCE
이 두 값을 환경 변수로 빼서 운영과 테스트에서 유연하게 조정할 수 있도록 했습니다.
X 수집에서 신경 쓴 부분
수집 쪽에서는 X가 가장 손이 많이 갔습니다.
처음부터 x.com HTML을 직접 긁는 방식은 피하고, RSS-compatible feed를 통해 가져오는 구조로 잡았습니다. 현재는 로컬 RSSHub를 사용하고 있습니다.
다만 RSSHub로 가져온 X 피드는 본문이 description 안에 HTML 형태로 들어오는데, 그대로 쓰면 <br>, 인용 블록, 이미지 태그, 영상 태그가 섞여 있어서 digest 품질이 좋지 않았습니다. 그래서 collector 단계에서 X 본문을 정리된 텍스트로 바꾸는 작업을 넣었습니다.
구체적으로는 아래처럼 처리했습니다.
<br>는 줄바꿈으로 유지- 인용문은 텍스트로 보존
- 이미지 / 영상 태그는 제거
content_text에는 비교적 긴 본문 텍스트를 저장content_preview는 Discord용 짧은 미리보기로 축약
이렇게 바꾸고 나니 요약 단계에서 훨씬 안정적으로 본문을 활용할 수 있었습니다.
한국어 정리 방식
처음에는 OpenAI API를 붙여서 한국어 번역까지 자동으로 넣으려고 했습니다.
그런데 실제로는 ChatGPT 구독과 API 사용이 별개이고, quota나 billing 이슈도 따로 관리해야 했습니다. 그래서 현재는 기본 동작을 로컬 한국어 fallback 요약으로 두고, 필요할 때만 ENABLE_OPENAI_TRANSLATION=true로 명시적으로 켜는 방식으로 바꿨습니다.
fallback 쪽도 단순히 영어 문장을 그대로 붙이는 방식이 아니라, 용어 사전을 기반으로 조금 더 읽기 쉬운 한국어 digest가 되도록 보강했습니다.
예를 들면 이런 식입니다.
agent orchestration->에이전트 오케스트레이션coding workflow->코딩 워크플로production operations->프로덕션 운영
완전한 번역은 아니지만, 매일 보는 digest라는 목적에는 오히려 이 정도가 더 안정적이고 실용적이라고 느꼈습니다.
Discord 출력 포맷
단순 링크 모음은 실제로 잘 읽히지 않아서, Discord 메시지는 아래처럼 구조를 나눴습니다.
- 오늘의 AI 새 소식
- 요약
- 핵심 하이라이트
- 카테고리별 업데이트
- 처리 참고
- 실패한 소스
또 Discord 길이 제한 때문에 메시지가 길어질 경우를 대비해서 chunking도 넣었습니다. 처음에는 줄 중간이 잘리는 문제가 있었는데, 이후에는 가능한 한 줄 단위 경계를 유지하도록 다듬었습니다.
테스트와 운영
테스트도 비교적 촘촘하게 넣으려고 했습니다.
- RSS / HTML collector 테스트
- state store 테스트
- digest 렌더링 테스트
- enrichment 테스트
- service 오케스트레이션 테스트
- CLI 실행 테스트
특히 이번에는 X 본문 정리 로직도 테스트에 추가해서, HTML description이 텍스트로 잘 정리되는지 확인하도록 했습니다.
운영 방식은 최대한 단순하게 가져갔습니다.
- PowerShell 스크립트로 실행
- 로컬 RSSHub 자동 기동
- Windows 작업 스케줄러 등록 가능
- 테스트 시에는 운영 DB 대신
test-state.db사용 - OpenAI 번역은 기본 비활성화
마무리
이 프로젝트를 만들면서 다시 느낀 점은, 이런 자동화는 "AI를 얼마나 화려하게 붙이느냐"보다 "매일 안정적으로 돌아가느냐"가 훨씬 중요하다는 점이었습니다. 특히 정보 수집 도구는 완벽한 번역보다도, 놓치지 않고, 중복 없이, 읽기 쉬운 형태로 꾸준히 제공하는 쪽이 훨씬 가치가 있다고 생각합니다.
아직 더 개선할 여지는 많습니다.
예를 들어 중요도 판단 로직을 더 세밀하게 만들 수도 있고, fallback 요약 표현을 더 다듬을 수도 있고, 장기적으로는 NotebookLM 같은 도구와 연동해서 주간/월간 분석용 워크플로도 만들 수 있을 것 같습니다.
그래도 지금 상태만으로도 "매일 AI 소식을 한 번에 확인하는 도구"로는 꽤 만족스럽게 동작하고 있습니다.
프로젝트 저장소는 아래에 있습니다.
'AI > 잡다한개발노트' 카테고리의 다른 글
| KikiLeoBook 릴리즈 준비 — 패키지 리네임부터 GitHub Release까지 (0) | 2026.03.29 |
|---|---|
| KikiLeoBook 개발 진행 상황 5차 (0) | 2026.03.29 |
| KikiLeoBook 개발 진행 상황 4차 (0) | 2026.03.26 |
| KikiLeoBook 개발 진행 상황 3차 (0) | 2026.03.25 |
| KikiLeoBook 개발 진행 상황 2차 (0) | 2026.03.24 |