Sitemap은 쉽게 말해서 검색 엔진이 크롤링을 함으로써 사용자들이 방문할 수 있는 페이지의 목록을 나타낸 것
예시
<urlset
xmlns="<http://www.sitemaps.org/schemas/sitemap/0.9>"
xmlns:news="<http://www.google.com/schemas/sitemap-news/0.9>"
xmlns:xhtml="<http://www.w3.org/1999/xhtml>"
xmlns:mobile="<http://www.google.com/schemas/sitemap-mobile/1.0>"
xmlns:image="<http://www.google.com/schemas/sitemap-image/1.1>"
xmlns:video="<http://www.google.com/schemas/sitemap-video/1.1>"
>
<url>
<loc><https://ji5485.github.io/></loc>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
<url>
<loc><https://ji5485.github.io/about/></loc>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
<url>
<loc><https://ji5485.github.io/portfolio/></loc>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
</urlset>
Gatsby와 같은 정적 사이트 생성기의 경우에는 마크다운 파일을 추가함으로써 계속해서 다른 페이지가 생성되기 때문에 직접 Sitemap을 작성하기에는 큰 어려움이 있음.
프로젝트 빌드 시에 자동으로 생성되는 페이지에 대해서 Sitemap에 추가해주는 라이브러리인 gatsby-plugin-sitemap 을 사용
npm i gatsby-plugin-sitemap
gatsby-config.js 파일에서 설정 코드를 추가
module.exports = {
siteMetadata: { ... },
plugins: [
...,
'gatsby-plugin-sitemap',
],
};
프로젝트를 npm run build 하여 Sitemap이 잘 생성되는지 확인
아래와 같은 에러가 뜸. 서버 사이드 렌더링 작업 시에 볼 수 있는 에러
WebpackError: ReferenceError: IntersectionObserver is not defined
IntersectionObserver는 브라우저 API이기 때문에 클라이언트 렌더링 시에 사용할 수 있는 API
로컬 서버를 실행하게 되면 Gatsby는 일반 React 애플리케이션과 동일하게 클라이언트 사이드 렌더링을 통해 화면을 보여주기 때문에 IntersectionObserver나 window 객체와 같이 브라우저에서 제공하는 요소를 아무 문제 없이 사용할 수 있음!
하지만, Gatsby는 기본적으로 빌드 시에는 Node.js 환경에서 진행되기 때문에 위와 같은 브라우저 API를 사용할 수 없음.
API또는 객체가 undefined인지 확인하는 조건문을 추가해주는 방법
if (IntersectionObserver === undefined) return
if (window === undefined) return
useEffect를 사용하는 방법. (useEffect 내부에 있는 코드는 클라이언트 렌더링 시에 실행되기 때문에 빌드 시에는 실행되지 않음.)
useEffect를 통해 useInfiniteScroll.tsx 수정.
import { MutableRefObject, useState, useEffect, useRef, useMemo } from 'react'
import { PostListItemType } from 'types/PostItem.types'
export type useInfiniteScrollType = {
containerRef: MutableRefObject<HTMLDivElement | null>
postList: PostListItemType[]
}
const NUMBER_OF_ITEMS_PER_PAGE = 10
const useInfiniteScroll = function (
selectedCategory: string,
posts: PostListItemType[],
): useInfiniteScrollType {
const containerRef: MutableRefObject<HTMLDivElement | null> =
useRef<HTMLDivElement>(null)
const observer: MutableRefObject<IntersectionObserver | null> =
useRef<IntersectionObserver>(null)
const [count, setCount] = useState<number>(1)
const postListByCategory = useMemo<PostListItemType[]>(
() =>
posts.filter(
({
node: {
frontmatter: { categories },
},
}: PostListItemType) =>
selectedCategory !== 'All'
? categories.includes(selectedCategory)
: true,
),
[selectedCategory],
)
useEffect(() => {
observer.current = new IntersectionObserver((entries, observer) => {
if (!entries[0].isIntersecting) return
setCount(value => value + 1)
observer.unobserve(entries[0].target)
})
}, [])
useEffect(() => setCount(1), [selectedCategory])
useEffect(() => {
if (
NUMBER_OF_ITEMS_PER_PAGE * count >= postListByCategory.length ||
containerRef.current === null ||
containerRef.current.children.length === 0 ||
observer.current === null
)
return
observer.current.observe(
containerRef.current.children[containerRef.current.children.length - 1],
)
}, [count, selectedCategory])
return {
containerRef,
postList: postListByCategory.slice(0, count * NUMBER_OF_ITEMS_PER_PAGE),
}
}
export default useInfiniteScroll
프로젝트 빌드를 진행한 후, 새로 생성된 public/sitemap/sitemap-index.xml 파일을 확인
빌드 성공 후 sitemap-index.xml 와 sitemap-0.xml 이런식으로 생성이 되는데 이렇게 사이트맵을 생성하는 이유는 몇몇 웹 마스터 도구에서 특정 개수(대략 5만) 이상의 URL이 담긴 사이트맵을 인식하지 못한다는 문제가 발생하기 때문
sitemap-0.xml, sitemap-1.xml, ...의 사이트맵을 생성sitemap-index.xml 파일에서 참조생성된 public/sitemap/sitemap-0.xml 예시
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="<http://www.sitemaps.org/schemas/sitemap/0.9>"
xmlns:news="<http://www.google.com/schemas/sitemap-news/0.9>"
xmlns:xhtml="<http://www.w3.org/1999/xhtml>"
xmlns:mobile="<http://www.google.com/schemas/sitemap-mobile/1.0>"
xmlns:image="<http://www.google.com/schemas/sitemap-image/1.1>"
xmlns:video="<http://www.google.com/schemas/sitemap-video/1.1>"
>
<url>
<loc><https://my-website-link.com/test/></loc>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
<url>
<loc><https://my-website-link.com/></loc>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
</urlset>
a. URL의 호스트 부분에 해당되는 my-website-link.com 부분은 gatsby-config.js 파일 내에서 siteMetadata 내부에 있는 siteUrl 프로퍼티를 참조하기 때문에 프로젝트 배포 후 변경 (나중에)
참고자료