본문 바로가기
개발

[Claude 블로그 자동화] Python Flask + RSS 자동 수집 시스템 만들기 2편

by 요즘IT 2026. 5. 29.

매일 아침 IT 뉴스 체크하는 루틴, 있으신 분 많죠?

Hacker News 열고, GeekNews 열고, The Verge 열고…

탭이 10개 넘어가는 순간 이미 피곤해요.

근데 생각해보면 이거 다 RSS 피드가 있거든요.

긁어오면 되는 거잖아요. 자동으로.

그래서 만들었어요. Python Flask로 RSS 수집기 하나 올려두고, 매일 아침 자동으로 글감을 모아두는 시스템을요.

 

이전 글: [서버, 인프라] - Ubuntu 서버에 Claude Code 도커로 올리기 1편


뭘 만드는 건지 먼저 그림 잡기

구조 자체는 단순해요.

매일 05:00 crontab 실행
↓
collector.py → 여러 RSS 소스 수집
↓
data/ 폴더에 JSON 저장
↓
Flask 웹에서 목록 확인
↓
"오늘 수집 데이터 복사" 버튼 클릭
↓
Claude.ai에 붙여넣기

DB 없어요. JSON 파일로 저장해요.

처음엔 "이게 맞나?" 싶었는데, 솔직히 이 정도 규모에선 DB가 오버스펙이거든요.

파일로 충분해요.


프로젝트 구조

web-scrap-note/
 ├ app.py
 ├ crawler/
 │   └ collector.py       ← 멀티 소스 통합 수집
 ├ templates/
 │   ├ index.html         ← 수집 목록 + 복사 버튼
 │   └ detail.html        ← 상세 보기
 ├ data/                  ← 수집된 JSON 저장
 ├ requirements.txt
 └ Dockerfile

파일 수 적죠? 이게 포인트예요.

복잡하게 만들수록 나중에 안 써요.


1단계 — 패키지 설치

# requirements.txt
flask==3.0.0
feedparser==6.0.10

딱 두 개예요.

feedparser는 RSS XML을 파싱해주는 라이브러리예요. 직접 XML 파싱 안 해도 되니까 코드가 엄청 짧아지거든요.

pip install -r requirements.txt

2단계 — RSS 수집기 만들기 (collector.py)

RSS feed reader diagram
RSS feed reader diagram

수집 소스는 이렇게 구성했어요.

카테고리 소스

IT/개발 Hacker News, GeekNews
AI MIT Technology Review, The Verge AI
커뮤니티 Dev.to, Reddit r/programming

소스별로 상위 10개씩, 중복 URL은 제거해요.

실제 코드예요.

# crawler/collector.py
import feedparser
import json
import os
from datetime import datetime

SOURCES = [
    {"name": "hackernews",          "url": "https://news.ycombinator.com/rss"},
    {"name": "geeknews",            "url": "https://news.hada.io/rss"},
    {"name": "mit_tech",            "url": "https://www.technologyreview.com/feed/"},
    {"name": "theverge",            "url": "https://www.theverge.com/ai-artificial-intelligence/rss/index.xml"},
    {"name": "devto",               "url": "https://dev.to/feed"},
    {"name": "reddit_programming",  "url": "https://www.reddit.com/r/programming/.rss"},
]

DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data")


def fetch_source(source):
    try:
        feed = feedparser.parse(source["url"])
        items = []
        for entry in feed.entries[:10]:
            items.append({
                "title":      entry.get("title", "").strip(),
                "url":        entry.get("link", ""),
                "summary":    entry.get("summary", "")[:300].strip(),
                "source":     source["name"],
                "created_at": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
            })
        print(f"[OK] {source['name']} — {len(items)}개 수집")
        return items
    except Exception as e:
        print(f"[SKIP] {source['name']} — {e}")
        return []


def collect():
    os.makedirs(DATA_DIR, exist_ok=True)

    all_items = []
    seen_urls = set()

    for source in SOURCES:
        for item in fetch_source(source):
            if item["url"] and item["url"] not in seen_urls:
                seen_urls.add(item["url"])
                all_items.append(item)

    today = datetime.now().strftime("%Y%m%d")
    filename = f"{today}_{len(all_items):03d}.json"
    path = os.path.join(DATA_DIR, filename)

    with open(path, "w", encoding="utf-8") as f:
        json.dump(all_items, f, ensure_ascii=False, indent=2)

    print(f"\n저장 완료: {filename} ({len(all_items)}개)")


if __name__ == "__main__":
    collect()

어? 생각보다 짧죠?

feedparser가 RSS 파싱을 다 처리해줘서, 우리는 필요한 필드만 뽑으면 돼요.

수집 실패한 소스는 그냥 skip하고 넘어가거든요. 하나 터진다고 전체가 멈추면 안 되니까요.


3단계 — Flask 웹 서버 만들기 (app.py)

웹에서 수집 결과를 보고, "오늘 데이터 복사" 버튼 한 번으로 Claude.ai에 붙여넣을 수 있게 만들어요.

# app.py
import os
import json
from flask import Flask, render_template, jsonify
from datetime import datetime

app = Flask(__name__)
DATA_DIR = "data"


def load_today_items():
    today = datetime.now().strftime("%Y%m%d")
    items = []
    for fname in sorted(os.listdir(DATA_DIR), reverse=True):
        if fname.startswith(today) and fname.endswith(".json"):
            with open(os.path.join(DATA_DIR, fname), encoding="utf-8") as f:
                items = json.load(f)
            break
    return items


def load_all_files():
    files = []
    for fname in sorted(os.listdir(DATA_DIR), reverse=True):
        if fname.endswith(".json"):
            files.append(fname)
    return files


@app.route("/")
def index():
    files = load_all_files()
    today_items = load_today_items()
    return render_template("index.html", files=files, today_items=today_items)


@app.route("/api/today")
def api_today():
    items = load_today_items()
    return jsonify(items)


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=False)

4단계 — 오늘 데이터 복사 버튼 만들기

이게 사실 제일 자주 쓰는 기능이에요.

버튼 하나 누르면 이런 형식으로 클립보드에 복사돼요.

=== 오늘의 IT 이슈 (2025-06-01) ===
[1] 제목
요약: ...
링크: ...
소스: hackernews

[2] 제목
요약: ...
...

이걸 그대로 Claude.ai에 붙여넣고 "오늘 쓸만한 주제 추천해줘" 하면 끝이거든요.

index.html에 JavaScript로 구현해요.

<!-- templates/index.html 핵심 부분 -->
<button onclick="copyToday()">오늘 수집 데이터 복사</button>

<script>
async function copyToday() {
  const res = await fetch("/api/today");
  const items = await res.json();
  const today = new Date().toISOString().split("T")[0];

  let text = `=== 오늘의 IT 이슈 (${today}) ===\n\n`;
  items.forEach((item, i) => {
    text += `[${i + 1}] ${item.title}\n`;
    text += `요약: ${item.summary}\n`;
    text += `링크: ${item.url}\n`;
    text += `소스: ${item.source}\n\n`;
  });

  await navigator.clipboard.writeText(text);
  alert("복사 완료!");
}
</script>

5단계 — crontab으로 매일 자동 수집

서버에서 매일 오전 5시에 자동 실행돼요.

# crontab -e
0 5 * * * docker exec web-scrap-note python crawler/collector.py >> /opt/scrap-data/cron.log 2>&1

crontab schedule automation terminal
crontab schedule automation terminal

여기서 포인트가 있어요.

docker exec으로 컨테이너 안에서 직접 실행하는 거거든요.

호스트에 Python 깔 필요 없이, 컨테이너 환경 그대로 써요.


실제로 돌려보면

# 컨테이너 안에서 직접 테스트
docker exec web-scrap-note python crawler/collector.py
[OK] hackernews — 10개 수집
[OK] geeknews — 10개 수집
[OK] mit_tech — 8개 수집
[OK] theverge — 10개 수집
[OK] devto — 10개 수집
[OK] reddit_programming — 10개 수집

저장 완료: 20250601_058.json (58개)

58개. 매일 이 정도 글감이 쌓여요.

다 쓸 필요는 없고, 그중에 눈에 띄는 거 하나 골라서 Claude.ai한테 던지는 거예요.


근데 여기서 반전이 있어요

수집은 잘 되는데, 처음 며칠은 막상 안 써요.

"오늘은 별로 없네" 하고 탭 닫는 거거든요.

그게 쌓이면 3일치, 5일치가 돼요.

오히려 그게 낫더라고요. 주제 고를 때 선택지가 많아지거든요.

자동화의 진짜 가치는 "매일 수집"이 아니라 "내가 안 봐도 쌓여있다" 는 거예요.


여기까지 정리하면

Flask + feedparser로 RSS 수집기 만들었고, 웹에서 바로 복사해서 Claude.ai에 붙여넣는 흐름까지 완성됐어요.

다음 편에서는 Jenkins로 이 프로젝트를 자동 배포하는 파이프라인을 만들어요.

코드 push 하면 → 자동 빌드 → 컨테이너 재시작까지.

한 번 설정해두면 이후에 코드 고칠 때마다 손 안 대도 되거든요.

결국 핵심은 이거예요.

글감 수집은 서버한테 맡기고, 나는 쓰는 것에만 집중한다.