블로그 사이트맵 자동 생성

작성일: 2023-10-31

이슈

현재 글에 대한 url을 제목으로 사용하고 있었는데, 다음과 같은 이슈가 있었습니다.

  • 제목 변경 시 기존의 글에 업데이트 되지 않고 새로운 포스트가 생성 (중복 포스팅 발생)
  • 엔티티 이스케이프 처리되어 URL 가독성이 떨어지는 이슈

이미 작성한 글의 제목을 변경하는 일이 자주 발생하지 않지만, 제목 수정 시 이전 글을 삭제해 주어야 하는 불편함이 있어 이를 해결하기 위해 Notion에서 PK 용도로 제공하는 ID 값을 URL로 사용했습니다.

Notion에서 배포하는 테이블에 ID 값을 아래와 같이 추가하고,

배포 스크립트에 Markdown 파일명과 permalink 속성 값을 ID로 설정해주었습니다.

for (const r of response.results) {
    const id = r.id
    let pk = r.properties?.["ID"]?.["unique_id"]?.["number"]
...
header += `
permalink: '${pk}'`
...
	const fTitle = `${pk}.md`
	fs.writeFile(path.join(folderPath, fTitle), header + body, (err) => {
	  if (err) {
	    console.log(err)
	  }
	})

위의 코드를 수정해서 아래와 같이 파일명과 permalink 값이 변경된 것을 확인했습니다.

그리고 permalink 값으로 URL 접근이 가능한 것을 확인했습니다.

사이트맵

URL이 변경되었으니 구글에게 변경된 사실을 알려주어야 하는데, 이때 사용하는 방법 중 한 가지가 사이트맵을 등록하는 방법입니다.

구글 검색 센터에서 사이트맵에 대해 다음과 같이 설명하고 있습니다.

사이트맵은 검색엔진에서 사이트의 URL을 발견하도록 도와주지만 사이트맵의 모든 항목이 크롤링되고 색인 생성된다고 보장하지는 않습니다. 하지만 대부분의 경우 사이트에 사이트맵이 있다면 도움이 됩니다.

구조

사이트맵은 다양한 포맷으로 구성할 수 있고 저는 xml 포맷으로 구성했습니다.

사이트맵의 전체 구조는 이곳에서 확인할 수 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
   <url>
      <loc>http://www.example.com/</loc>
      <lastmod>2005-01-01</lastmod>
      <changefreq>monthly</changefreq>
      <priority>0.8</priority>
   </url>
</urlset>

속성에 대한 정의는 다음과 같습니다.

속성설명
loc페이지의 URL입니다. 이 URL은 프로토콜(예: http)로 시작하고 웹 서버에서 요구하는 경우 후행 슬래시로 끝나야 합니다. 이 값은 2,048자 미만이어야 합니다.
lastmod페이지를 마지막으로 수정한 날짜입니다. 이 날짜는 W3C 날짜 형식이어야 합니다. 이 형식을 사용하면 원하는 경우 시간 부분을 생략하고 YYYY-MM-DD를 사용할 수 있습니다.
changefreq페이지가 변경될 가능성이 있는 빈도. 이 값은 검색 엔진에 일반적인 정보를 제공하며 검색 엔진이 페이지를 크롤링하는 빈도와 정확히 상관관계가 없을 수 있습니다. 유효한 값은 다음과 같습니다: always, hourly, daily, weekly, monthly, yearly, never. archived된 URL을 설명할 때는 “never” 값을 사용해야 합니다.
priority사이트의 다른 URL에 대한 이 URL의 상대적 우선 순위입니다. 유효한 값의 범위는 0.0에서 1.0입니다. 이 값은 페이지가 다른 사이트의 페이지와 비교되는 방식에는 영향을 주지 않으며, 크롤러에게 가장 중요하다고 판단되는 페이지를 검색 엔진에 알려줄 뿐입니다. 페이지의 기본 우선 순위는 0.5입니다.

규칙

사이트맵 작성 규칙입니다.

  • 모든 XML 파일과 마찬가지로 모든 태그 값은 엔티티 이스케이프 처리되어야 합니다.
  • Google에서는 <priority> 및 <changefreq> 값을 무시합니다.
  • Google에서는 <lastmod> 값이 일관되고 정확성을 검증(예: 페이지의 마지막 수정사항과 비교)할 수 있는 경우에 이 값을 사용합니다.

코드

사이트맵을 자동으로 생성하기 위해 sitemap.js 라이브러리를 사용했습니다.

_scripts/notion-import.js

function generateSitemap(links) {
  const stream = new SitemapStream({
    hostname: "https://devshjeon.github.io/",
    lastmodDateOnly: true,
  })
  streamToPromise(Readable.from(links).pipe(stream)).then((data) => {
      fs.writeFile("sitemap.xml", data.toString(), (err) => {
        if (err) {
          console.log(err)
        }
      })
    },
  )
}

...

const links = []
  const priority = 0.8
  const changeFreq = "daily"

  for (const r of response.results) {
    const id = r.id
    let pk = r.properties?.["ID"]?.["unique_id"]?.["number"]
    let modifiedDate = moment(r.last_edited_time).tz("Asia/Seoul").format("YYYY-MM-DD")

    // 사이트맵
    links.push(
      {
        url: `/${pk}`,
        lastmod: modifiedDate,
        changefreq: changeFreq,
        priority,
      },
    )

...

	}

  generateSitemap(links)
})()

배포 후 사이트맵이 정상적으로 반영된 것을 확인할 수 있습니다.