Post

Jekyll 블로그에 RSS 피드로 최신 기술 뉴스 자동 포스팅 시스템 구축하기

Jekyll 블로그에 RSS 피드로 최신 기술 뉴스 자동 포스팅 시스템 구축하기

들어가며

이 포스트에서는 GitHub ActionsNode.js를 활용하여, 여러 기술 블로그의 RSS 피드를 주기적으로 수집하고 내 Jekyll 블로그에 자동으로 포스팅하는 시스템을 구축하는 방법을 소개합니다. 한번 설정해두면 알아서 최신 콘텐츠를 수집해주므로 블로그를 더욱 풍성하게 만들 수 있습니다.

시스템 아키텍처

우리가 만들 시스템은 다음과 같은 흐름으로 동작합니다.

  1. GitHub Actions (스케줄러): 매일 정해진 시간에 워크플로우를 실행시켜 자동화 프로세스를 시작합니다.
  2. Node.js 스크립트 (콘텐츠 수집기): 실행된 워크플로우가 Node.js 스크립트를 호출합니다. 이 스크립트는 지정된 RSS 피드 URL에서 최신 기사 목록을 가져옵니다.
  3. 마크다운 파일 생성: 스크립트는 수집한 기사 데이터를 Jekyll이 인식할 수 있는 마크다운(.md) 파일로 변환하여 _posts 폴더에 저장합니다.
  4. 자동 커밋 & 푸시: 새로 생성된 마크다운 파일들을 Git을 통해 자동으로 저장소에 커밋(Commit)하고 푸시(Push)합니다.
  5. Jekyll 자동 배포: main 브랜치에 새로운 커밋이 푸시되면, 기존에 설정해 둔 Jekyll 배포용 GitHub Actions가 이를 감지하여 사이트를 다시 빌드하고 GitHub Pages에 배포합니다.

구축 단계

1단계: RSS 파싱을 위한 Node.js 스크립트 작성

먼저, RSS 피드를 읽고 파싱하여 마크다운 파일로 만들어 줄 Node.js 스크립트가 필요합니다.

의존성 설치

프로젝트에 RSS 파싱 라이브러리를 추가합니다.

1
pnpm add rss-parser # 또는 npm install rss-parser

스크립트 작성

프로젝트 루트에 scripts 폴더를 만들고, 그 안에 fetch-rss.mjs 파일을 생성한 후 아래 코드를 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// scripts/fetch-rss.mjs
import fs from 'fs';
import path from 'path';
import Parser from 'rss-parser';

// 1. 수집할 RSS 피드 주소 목록
const RSS_FEEDS = [
  { url: 'https://toss.tech/rss.xml' },
  { url: 'https://tech.kakao.com/feed/' },
  { url: 'https://techblog.woowahan.com/feed/' },
];

// 2. 게시물을 저장할 Jekyll 포스트 경로
const OUTPUT_DIR = path.join(process.cwd(), '_posts');

// Jekyll의 날짜 형식에 맞게 변환하는 헬퍼 함수
function formatDateForJekyll(date) {
  // ... (날짜 포맷 변환 로직) ...
  const pad = (num) => num.toString().padStart(2, '0');
  const year = date.getFullYear();
  const month = pad(date.getMonth() + 1);
  const day = pad(date.getDate());
  const hours = pad(date.getHours());
  const minutes = pad(date.getMinutes());
  const seconds = pad(date.getSeconds());
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds} +0900`;
}

(async () => {
  console.log('Fetching RSS feeds...');
  const parser = new Parser();

  if (!fs.existsSync(OUTPUT_DIR)) {
    fs.mkdirSync(OUTPUT_DIR, { recursive: true });
  }

  for (const feedConfig of RSS_FEEDS) {
    try {
      const feed = await parser.parseURL(feedConfig.url);
      console.log(`- Fetched: ${feed.title}`);

      for (const item of feed.items) {
        // Jekyll 형식 파일명 생성 (YYYY-MM-DD-title.md)
        const itemDate = new Date(item.pubDate);
        const postDateStr = `${itemDate.getFullYear()}-${(itemDate.getMonth() + 1).toString().padStart(2, '0')}-${itemDate.getDate().toString().padStart(2, '0')}`;
        const safeTitle = item.title.replace(/[^a-zA-Z0-9가-힣\s]/g, '').replace(/\s+/g, '-').substring(0, 50);
        const fileName = `${postDateStr}-${safeTitle}.md`;
        const filePath = path.join(OUTPUT_DIR, fileName);

        if (fs.existsSync(filePath)) {
          continue; // 이미 파일이 존재하면 건너뛰기
        }
        
        // Jekyll Front Matter 형식에 맞게 마크다운 콘텐츠 생성
        const markdownContent = `---
title: "${item.title.replace(/"/g, '\\"')}"
date: ${formatDateForJekyll(itemDate)}
categories: [TechInfo]
tags: ["${feed.title.split(' ')[0]}", "RSS"]
source: ${item.link}
---

> 이 글은 **${feed.title}** 블로그에서 가져온 글입니다. 자세한 내용은 원문을 참고해 주세요.

**[➡️ 원문 보러 가기](${item.link})**

---

### 원문 요약

${item.contentSnippet?.replace(/\n/g, ' ') || '요약 정보가 없습니다.'}
        `;

        fs.writeFileSync(filePath, markdownContent);
        console.log(`  - Created: ${fileName}`);
      }
    } catch (error) {
      console.error(`Error fetching feed from ${feedConfig.url}:`, error);
    }
  }
})();

2단계: GitHub Actions 워크플로우 설정

이제 위 스크립트를 주기적으로 실행시켜 줄 GitHub Actions 워크플로우를 설정합니다.

.github/workflows/ 폴더에 rss-fetch.yml 파일을 만들고 아래 내용을 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# .github/workflows/rss-fetch.yml
name: Fetch Latest Tech Blog Posts

on:
  schedule:
    # 매일 UTC 00:00 (한국 시간 오전 9시)에 실행
    - cron: '0 0 * * *'
  workflow_dispatch: # 수동 실행을 위한 옵션

jobs:
  fetch-and-commit:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js and pnpm
        uses: pnpm/action-setup@v3
        with:
          version: 8
      - uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install

      - name: Fetch RSS feeds and create posts
        run: node scripts/fetch-rss.mjs

      - name: Commit and push new posts
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: "feat(auto): Add new posts from RSS feeds"
          commit_user_name: "GitHub Actions Bot"
          commit_user_email: "actions@github.com"
          commit_author: "GitHub Actions Bot <actions@github.com>"

이 워크플로우는 매일 오전 9시에 fetch-rss.mjs 스크립트를 실행하고, 변경된 내용(새로 생성된 마크다운 파일)이 있으면 자동으로 커밋 및 푸시합니다.

마무리

이제 모든 설정이 끝났습니다. 변경된 파일들을 GitHub 저장소에 푸시하면, 그 후부터는 매일 자동으로 새로운 기술 소식들이 내 블로그의 _posts 폴더에 차곡차곡 쌓이게 됩니다. 그리고 기존에 설정해 둔 Jekyll 배포 워크플로우가 이 변경사항을 감지하여 자동으로 사이트를 업데이트해 줄 것입니다.

```

This post is licensed under CC BY 4.0 by the author.