🚀   새로운 블로그로 이전했습니다.

블로그에 RSS, JSON Feed 추가하기

2023.03.17
5분

RSSJSON Feed웹사이트의 콘텐츠를 손쉽게 구독할 수 있게 해주는 기술이다.
모두 웹사이트의 업데이트를 손쉽게 확인하고, 원하는 콘텐츠를 효율적으로 모아볼 수 있는 기능을 제공한다.


RSS (Really Simple Syndication)

RSSXML 기반으로 웹 콘텐츠를 제공해준다.
사용자는 RSS 리더를 통해 여러 사이트의 RSS를 통해 피드들을 한 눈에 볼 수 있다.
자신이 좋아하는 블로그들의 글을 웹사이트 돌아다닐 필요 없이 한 페이지에서 모아 볼 수 있게 된다!

추가로 Atom이라는 XML 기반의 표준도 있다.
RSS보다 더 확장성이 있고 더욱 상세한 정보를 기입할 수 있다.


JSON Feed

JSON Feed는 이름대로 JSON 기반으로 웹 콘텐츠를 구독한다.
JSON이기 때문에 파싱이 쉽고, 가독성이 좋고, 가볍고... XML보다 이점을 많이 갖고 있다.


블로그에 적용하기

JSON Feed가 성능상 이점이 있지만 오랫동안 사용되어 온 RSS를 내려놓기 어렵다.
하지만 꼭 하나만 선택할 필요는 없다. RSS, JSON Feed 모두 제공해주면 된다.

feed를 활용해서 구현해보자.
typescript 기반으로 구현된 라이브러리이며 RSS Atom JSON Feed를 모두 생성할 수 있다.

yarn add feed

데이터 생성하기

해당 블로그에서 적용한 방법이다.
빌드시 rss.xml feed.json 정적 파일을 생성하여 github pages에 배포하는 방식이다.

scripts/generate-rss.ts
import { Feed } from 'feed';
import { writeFileSync } from 'fs';

import PostJson from '../.contentlayer/generated/Post/_index.json';
import { siteConfig } from '../src/config';

const master = {
  name: siteConfig.author.name,
  email: siteConfig.author.contacts.email,
  link: siteConfig.url,
};

const feed = new Feed({
  title: siteConfig.title,
  description: siteConfig.description,
  id: siteConfig.url,
  link: siteConfig.url,
  language: 'ko',
  image: `${siteConfig.url}/images/base.jpg`,
  favicon: `${siteConfig.url}/favicon.ico`,
  copyright: `All rights reserved since ${siteConfig.since}, ${master.name}`,
  generator: 'generate-rss',
  feedLinks: {
    json: `${siteConfig.url}/json`,
    atom: `${siteConfig.url}/atom`,
  },
  author: master,
});

PostJson.forEach((post) => {
  feed.addItem({
    title: post.title,
    id: post.slug,
    link: `${siteConfig.url}${post.slug}`,
    description: post.description,
    content: post.body.raw,
    author: [master],
    contributor: [master],
    date: new Date(post.date),
    image: post.image,
    category: post.tags.map((tag) => ({ name: tag })),
  });
});

feed.addCategory('Technologies');

// Output: RSS 2.0
writeFileSync('out/rss.xml', feed.rss2(), 'utf-8');
// Output: Atom 1.0
writeFileSync('out/rss-atom.xml', feed.atom1(), 'utf-8');
// Output: JSON Feed 1.0
writeFileSync('out/feed.json', feed.json1(), 'utf-8');

속성들은 직관적이기 때문에 어렵지 않게 자신 환경에 맞춰 작성할 수 있을 것이다.
만들어진 데이터를 writeFileSync 통해 파일로 생성하면 된다.

이제 빌드시점에서 파일들이 생성되도록 package.json에 스크립트를 추가한다.

package.json
{
  //...
  "homepage": "https://bepyan.github.io/",
  "scripts": {
    //...
    "build": "next build && next export && yarn rss",
    "rss": "ts-node --project tsconfig.node.json ./scripts/generate-rss.ts",
  },
}
tsconfig.node.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs",
  }
}

웹사이트에 심기

<link> 태그를 활용하여 RSS JSON Feed 피드 존재를 드러낼 수 있다.
브라우저는 피드를 인식하고 사용자에게 구독 옵션을 제공할 수 있게 된다.

_document.tsx
<Head>
  <link rel="alternate" type="application/rss+xml" href="/rss.xml" title="RSS" />
  <link rel="alternate" type="application/atom+xml" href="/rss-atom.xml" title="RSS Atom" />
  <link rel="alternate" type="application/json" href="/feed.json" title="JSON Feed" />
</Head>

rel 속성은 현재 문서와 연결된 리소스 간의 관계를 설명하고,
alternate 값은 대체 콘텐츠를 제공하는 연결된 리소스를 나타낸다.

추가로 이는 PC, Mobile 페이지, 다국 언어 페이지 리소스를 연결 해주기도 한다.

다른 방법 - API

사실 꼭 정적인 파일을 생성할 필요는 없다.
api를 통해서 응답을 줘도 된다!

pages/api/rss.ts
import { Feed } from 'rss';
// ... (생성한 feed 코드 삽입)

export default async (req, res) => {
  res.setHeader('Content-Type', 'application/rss+xml');
  res.write(feed.rss2());
  res.end();
};