본문 바로가기

프론트엔드

Next.js 블로그 동적 사이트맵 만들기

  • Next.js 13버전 이후로 app디렉토리 내에 sitemap.ts라는 예약어 파일을 만들면, 빌드 시점에 미리 sitemap을 생성해준다.
  • 블로그처럼 게시글을 계속해서 올릴 경우, 사이트맵에 들어갈 내용이 많을 경우에 sitemap.ts파일 하나를 만들어두면 아주 손쉽게 sitemap.xml을 생성할 수 있으며 nextjs에서는 그 방법 또한 매우 간단하다.

1. sitemap.ts 파일 생성

  • app폴더 내에 sitemap.ts 파일을 만들고, sitemap에 들어가야할 리스트를 return한다.
  • 나의 경우 tag/ 이하 url과 detail/ 이하 url들을 동적으로 구현하였다.
  • 방법은 아래 코드를 보면 알겠지만, 아주 간단히도.. sitemap을 생성할 리스트를 받아와서 넣어주면 끝이다.
import { Post, Tag } from '@/util'
import { getAllPosts, getAllTags } from '@/util/sitemapPosts'
import { MetadataRoute } from 'next'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const posts:Post[] | null = await getAllPosts()
  const tags:Tag[] | null = await getAllTags()

  return [
    {
      url: 'https://ha0.work',
      lastModified: new Date(),
    },
    {
      url: 'https://ha0.work/blog',
      lastModified: new Date(),
    },
    ...posts!.map((post) => {
      return {
        url: `https://ha0.work/detail/${post._id.toString()}`,
        lastModified: new Date(post.createdTime!),
      }
    }),
    ...tags!.map((tag) => {
      return {
        url: `https://ha0.work/blog/tag/${tag.name}`,
        lastModified: new Date(),
      }
    }),
  ]
}

2. 몽고DB 데이터 가져오기

  • 블로그 게시글의 CRUD들은 몽고DB에 연결해서 구현하였는데, 이번엔 DB에 직접 연결하지 않고 몽고디비에서 지원하는 dataAPI를 사용하여 데이터를 읽어와보았다.
import { Post, Tag } from ".";

export async function getAllPosts(): Promise<Array<Post> | null> {
    const body = {
        dataSource: dataSource,
        database: database,
        collection: collection
    }

    try {
        const result = await fetch('https://us-west-2.aws.data.mongodb-api.com/app/data-zulli/endpoint/data/v1/action/find', {
            headers: {
              'Content-Type': 'application/json',
              'API-Key': process.env.NEXT_PUBLIC_MONGODB_API_KEY,
              'Access-Control-Request-Headers': '*',
              'Accept': 'application/json'
            },
            body: JSON.stringify(body),
            method: 'POST'
        })
        const data = await result.json();
        return data.documents
        
    } catch (error) {
        console.log('error', error)
        return null
    }
}

export async function getAllTags(): Promise<Array<Tag> | null> {
    ...이하동일
}