인공지능/AI Agent

해외 축구 뉴스를 Claude AI로 자동 요약하는 서비스 만들기

mino28 2026. 2. 2. 16:03

⚽ 해외 축구 뉴스를 Claude AI로 자동 요약하는 서비스 만들기

Node.js + TypeScript + Claude API로 RSS 수집 → AI 요약 → 대시보드까지 풀스택 개발


💡 프로젝트 개요

해외 축구 뉴스를 매일 챙겨보는데, 영어 기사를 하나하나 읽기가 번거로웠습니다. BBC Sport, ESPN, Goal.com 등의 RSS 피드를 자동으로 수집하고, Claude AI가 한국어로 요약해주는 서비스를 만들었습니다.

🎯 목표

  1. RSS 피드에서 최신 축구 뉴스 자동 수집
  2. 기사 본문 크롤링
  3. Claude AI로 한국어 요약 + 카테고리 분류
  4. 웹 대시보드에서 보기 좋게 표시

🛠 기술 스택

Runtime: Node.js + TypeScript
서버: Express.js
DB: SQLite (better-sqlite3)
AI: Claude API (Anthropic SDK)
크롤링: rss-parser + cheerio
프론트: 순수 HTML/CSS/JS


🏗 시스템 아키텍처

 
 
RSS 피드 (BBC, ESPN, Goal.com)
        ↓
  RSS 파싱 (Promise.allSettled)
        ↓
  본문 크롤링 (cheerio + fallback)
        ↓
  Claude AI 요약 + 분류
        ↓
  SQLite 저장 (상태 관리)
        ↓
  REST API
        ↓
  웹 대시보드

📚 핵심 구현 내용

1️⃣ 프로젝트 설계 결정

💡 CommonJS를 선택한 이유

better-sqlite3가 네이티브 C++ addon이라 ESM에서 import 충돌 가능성이 있어 CJS로 통일했습니다. 개발 서버는 tsx로 TypeScript를 직접 실행합니다.

DB: better-sqlite3 선택

  • 동기 API 제공으로 직관적한 코드 작성
  • WAL 모드로 읽기/쓰기 동시성 확보
  • 별도 마이그레이션 도구 없이 sql/ 폴더의 SQL 파일을 순차 적용

2️⃣ 뉴스 수집 파이프라인

📡 RSS 파싱: 부분 실패 허용

 
 
typescript
// Promise.allSettled로 개별 실패 허용
const results = await Promise.allSettled(
  feeds.map(feed => parseFeed(feed))
);
```

피드 3개 중 1개가 다운되어도 나머지 2개는 정상 처리됩니다. 이런 **부분 실패 허용(fault tolerance)** 설계가 안정적인 수집의 핵심입니다.

**🕷 본문 크롤링: Cheerio 선택**

Puppeteer 대신 Cheerio를 선택한 이유:
- 뉴스 사이트는 대부분 SSR → JS 렌더링 불필요
- 메모리 사용량: Puppeteer 500MB+ vs Cheerio 수 MB

**다단계 Selector Fallback**
```
<article> → [role="main"] → .article-body → <p> 태그

불필요 요소(nav, ad, footer)는 사전 제거하고, 크롤링이 실패하면 RSS description으로 fallback합니다. 어떤 상황에서도 파이프라인이 멈추지 않습니다.


3️⃣ Claude AI 요약 시스템

⚠️ 비용 최적화: 모델 티어 분리

모든 요청에 고성능 모델을 쓸 필요는 없습니다.

  • 요약/분류: Sonnet (빠르고 저렴)
  • 심층 분석: Opus (고품질)
  • .env로 모델 ID 관리 → 코드 변경 없이 교체 가능

⚡ 단일 호출로 요약 + 분류

별도 API 호출로 나누면 비용 2배, 지연 2배입니다. 단일 호출로 처리:

 
 
json
{
  "summary": "손흥민이 토트넘 더비에서 결승골을 터뜨리며...",
  "category": "경기 결과"
}

📝 프롬프트 엔지니어링 포인트

  1. 본문 3000자 컷 - 리드 문단에 핵심 집중, 토큰 비용 절약
  2. 선수명 한국어 표기 규칙 - 일관된 번역 품질
  3. JSON 파싱 방어 - ```json` 코드블록 제거 로직
  4. 카테고리 자동 보정 - 정의된 목록 외 값은 "기타"로 변환

🔄 순차 처리를 선택한 이유

Claude API의 rate limit를 고려해 순차 + 500ms 간격이 가장 안정적입니다. 병렬로 처리하면 429 에러가 발생하고 재시도 로직이 복잡해집니다.


4️⃣ 데이터 저장 및 상태 관리

🔒 중복 방지: DB 레벨에서 처리

 
 
sql
guid UNIQUE
INSERT OR IGNORE
```

애플리케이션 코드가 아닌 **DB 레벨에서 중복을 방지**하는 게 핵심입니다.

**🔄 멱등성 설계**

각 기사는 `pending → summarized | failed` 상태를 가집니다. 

파이프라인을 여러 번 실행해도:
- 이미 처리된 기사는 건너뜀
- 실패한 기사만 재처리

이걸 **멱등성(idempotency)**이라고 합니다.

**🛡 기사별 격리**

- try-catch로 개별 기사 실패를 격리
- 전체 파이프라인 중단 방지
- 실패 기사는 `failed` 상태로 마킹해 원인 추적 가능

---

### 5️⃣ REST API
```
GET /health                     # 서버 상태
GET /articles?limit=20&offset=0 # 기사 목록 (필터/페이징)
GET /stats                      # 통계
GET /categories                 # 카테고리 목록
```

**설계 포인트**
- limit 최대값 100 제한
- WHERE 조건 동적 조합
- 카테고리 엔드포인트 분리 → 프론트엔드 필터 UI 동적 구성

---

### 6️⃣ 웹 대시보드

**✅ 프레임워크 없이 단일 HTML 파일**

백엔드 파이프라인이 본질이고 UI는 결과 확인용이라 React/Vue는 과잉입니다. 

`express.static`으로 `public/` 폴더를 바로 서빙하니:
- 빌드 스텝 불필요
- CORS 문제 없음
- 배포 간단

**주요 기능**
- 📊 통계 카드 (전체/완료/대기/실패)
- 🔍 카테고리·상태 필터
- 📰 기사 카드 (소스 배지, 요약, 상대 시간)
- 📄 페이지네이션
- 📱 반응형 디자인

**보안**: 모든 동적 데이터를 HTML 이스케이프 처리

---

## 🐛 트러블슈팅

### better-sqlite3 빌드 실패 (Windows)

Windows에서 `npm install` 시 네이티브 C++ 컴파일 실패:
```
gyp ERR! find VS - missing any Windows SDK
```

**원인**: Windows SDK 컴포넌트 누락

**해결 방법**:
1. Visual Studio Installer 실행
2. "Desktop development with C++" 워크로드 선택
3. Windows SDK 컴포넌트 추가 설치

**💡 교훈**: 네이티브 addon 사용 시 환경별 빌드 요구사항을 README에 명시해야 합니다.

---

## 💡 배운 점

### 1. AI API 연동은 방어적으로
응답 형식이 항상 기대대로 오지 않습니다. JSON 파싱 방어, 카테고리 자동 보정 같은 fallback이 필수입니다.

### 2. 부분 실패를 허용하는 설계
`Promise.allSettled`, 기사별 try-catch, RSS description fallback 등 어디서 실패해도 전체가 멈추지 않게 만드는 것이 실서비스 안정성의 핵심입니다.

### 3. 비용 최적화는 아키텍처 레벨에서
모델 티어 분리, 요약+분류 단일 호출, 본문 3000자 컷 등 작은 결정들이 모이면 비용 차이가 큽니다.

### 4. 멱등성은 배치 시스템의 생명
같은 파이프라인을 여러 번 돌려도 안전해야 크론잡이나 재시도가 가능합니다.

### 5. 기술 선택에는 이유가 있어야 한다
"왜 이 라이브러리를?" "왜 이 패턴을?"에 답할 수 있어야 의미 있는 프로젝트입니다.

---

## 📂 프로젝트 구조
```
football-news/
├── public/index.html           # 웹 대시보드
├── sql/001_init.sql            # DB 스키마
├── src/
│   ├── ai/                     # Claude AI 연동
│   ├── db/                     # Repository 패턴
│   ├── rss/                    # 뉴스 수집
│   ├── index.ts                # Express 서버
│   └── pipeline.ts             # 오케스트레이터
├── .env.example
├── package.json
└── tsconfig.json

🚀 실행 방법

 
 
bash
cd D:\workspace\football-news
npm install
copy .env.example .env          # ANTHROPIC_API_KEY 설정
npm run db:migrate              # DB 스키마 적용
npm run pipeline                # 뉴스 수집 + AI 요약
npm run dev                     # 서버 시작 → http://localhost:3000

'인공지능 > AI Agent' 카테고리의 다른 글

OpenCode, oh-my-opencode 설치 및 사용 가이드  (0) 2026.02.02
벡터 데이터베이스  (0) 2025.09.17
랭그래프 Reflection  (0) 2025.09.17
랭그래프를 이용한 간단한 챗봇  (1) 2025.09.15
랭그래프 기초  (0) 2025.09.15