TOC
들어가며
그동안 블로그 개발을 하면서 한 가지 마음의 짐이 있었어요. 바로 메타데이터와 오픈그래프, SEO에요. 그동안은 글을 쓰기 위한 준비를 해왔어요. 아래의 구현에 집중하면서 외부에서의 유입과 외부로의 공유에 필요한 요소들을 후순위로 미뤘었거든요.
- 1버전부터 쌓아오던 markdown 포스트 파일들을 mdx로 변환
- 내부 요소들의 스타일링
- 블로그스러운 라우팅과 내부 기능 구현
하지만 이제는 많은 기능들을 지원하고 스타일도 충분히 가꾼 것 같아 본격적으로 블로그 외부와의 상호작용을 위한 작업의 시기가 다가왔음을 느꼈어요. 그래서 SEO에 대한 발걸음을 떼보고자 야심차게 학습과 개발을 시작했습니다.
지피지기면 백전백승
뭘 고치고 개선할지 알려면, 무엇보다 현재 상황이 어떤지 명확하게 알 필요가 있었어요. 그래서 하나하나 따져봤습니다.
Google Analytics
- google-site-verification 등록 완료(참고자료)
Google Search Console
- robots.txt, sitemap.xml 다 조회 안됨

Naver Search Advisor
- naver-site-verification 등록 완료
- robots.txt 없음
- opengraph 없음
- title, description 없음

사이트 내 조회
- robots.txt, sitemap.xml 다 조회 안 됨
- 코드에서도
apps/robots.txt
와apps/sitemap.xml
부재


기타
- favicon 없음
- 대표 thumbnail 없음
- 플랫폼에 공유하면 그냥 링크만 표시
달성 목표
모니터링 사이트
- Google Search Console : robots.txt, sitemap.xml 조회 가능
- Google Analytics : 사이트 조회 및 유입 관련 데이터 확인
- Naver Search Advisor : 모든 항목 체크
개발 목표 - 기본
- robots.txt, sitemap.xml
- RSS - feed.xml
- opengraph, twitter card
- favicon
- thumbnail
- title, description
개발 목표 - 심화
- route 섹션별 다른 metadata 및 opengraph 처리
- 홈 / 포스트 리스트 / 포스트 디테일
- 구글 검색에 도움되는 포인트 추가
- keywords 설정
robots.txt
next-sitemap을 포기하다
저는 블로그 개발 초반에 next-sitemap을 활용해 robots.txt
와 sitemap.xml
를 만드는 블로그 포스팅(링크)을 보고 참고해 설정했어요. 실제로 빌드 이후 sitemap을 따로 만드는 스크립트가 돌았고, next export
를 통해 /out
폴더에 robots.txt
와 sitemap.xml
을 만들어져 있는 것을 확인할 수 있었어요.

그런데 아무리 해도 production 환경에서 robots.txt
와 sitemap.xml
파일을 확인할 수 없었어요. 자세한 과정은 생략하겠지만 이 이슈 때문에 저어어엉말 많이 시간을 쓰고 구글을 다 뒤졌는데도 해결이 되지 않아 next-sitemap
라이브러리를 사용한 robots.txt
와 sitemap.xml
빌드는 포기하기로 했습니다.
다만 Next13(app router)에서는 robots.txt와 sitemap을 생성하는 가이드 문서가 있어서, 공식 가이드대로 진행하기로 했어요.
robots.txt의 역할
robots.txt
란 웹 크롤러에게 사이트에서 어떤 페이지나 파일을 크롤링할 수 있고, 없는지 알려주는 규칙을 정의한 파일이에요. 검색 엔진 크롤러가 사이트를 효과적으로 탐색하도록 돕는 동시에, 원치 않는 크롤링을 방지하는 데 사용돼요. 즉, SEO를 위한 기본이자 필수입니다.
어떤 크롤러(User-Agent)에게 어떤 경로의 접근을 허용(Allow)하고 비허용(Disallow)할지 명시합니다. 또한 이후에 다루게 될 sitemap
에 대한 경로를 제시하는 역할을 해요.
next.js와 robots.txt
공식문서(링크)에 따르면 app/robots.txt
로 정적 파일을 직접 추가할 수도 있고, app/robots.(js | ts)
를 통해 스크립트 형식으로 robots.txt를 만들 수 있습니다. user agent를 명시하고 구분할 필요는 못 느껴서 기본적인 동적 robots.txt 생성에 대해 알아보겠습니다.
import { BASE_CONFIG } from '@/configs/base.config';
import { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: '/private/',
},
],
sitemap: `${BASE_CONFIG.URL}/sitemap/1`,
};
}
제 코드에는 sitemap에 대한 경로가 있지만, 모든 설정을 마친 최종본이기 때문에 있는 거에요. 이후에 경로가 확정되면 robots.txt
에 추가해 넣어주면 됩니다.
sitemap
sitemap의 역할
sitemap
은 웹사이트의 구조를 검색 엔진 크롤러에게 명확히 전달하기 위해 작성된 XML 형식의 파일입니다. 이 파일은 웹사이트의 URL 리스트를 제공하며, 각 URL에 대한 추가 정보를 포함할 수 있습니다. 이를 통해 검색 엔진이 웹사이트의 콘텐츠를 더 효과적으로 크롤링하고 인덱싱할 수 있도록 돕습니다. robots.txt와 더불어 SEO에 필수적인 역할을 하는 파일이죠.
next.js와 sitemap
Next.js 공식문서(링크)에 따르면 robots.txt
처럼 정적으로 app/sitemap.xml
파일을 추가할 수 있고, sitemap.(js | ts)
를 통해 스크립트 형식으로 sitemap.xml를 만들 수 있어요.
robots.txt
와 달리 category, post들의 path에 따라 모든 route에 대해 sitemap.xml에 적용을 해주어야 하기 때문에 스크립트 방식이 역시 유리할 것이라고 생각해 이 방향으로 개발해봤어요.
Next.js 공식 가이드 코드
우선 Next.js에서 제시한 example 코드를 보시죠.
import type { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: 'https://acme.com',
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 1,
},
{
url: 'https://acme.com/about',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: 'https://acme.com/blog',
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.5,
},
]
}
url마다 마지막 수정시각, 변경빈도, 우선순위를 설정해주고 있어요. 이에 따라서 제가 블로그에서 보여줘야 하는 모든 페이지에 대한 객체를 생성해보겠습니다.
트러블슈팅을 거친 결과 코드
sitemap에서 정말 눈물 나는 트러블슈팅의 과정이 있었어요.
우선 전쟁을 겪고 난 코드를 보여드릴게요.
// sitemap.ts
import { BASE_CONFIG } from '@/configs/base.config';
import { allPosts } from '@/contentlayer/generated';
import { ROOT_CATEGORY } from '@/routes/category/category.constant';
import { getAllCategoryRoute } from '@/routes/category/category.util';
import type { MetadataRoute } from 'next';
// route
const routeSiteMap: MetadataRoute.Sitemap = [
{
url: `${BASE_CONFIG.URL}`,
lastModified: new Date().toISOString(),
changeFrequency: 'monthly',
priority: 1,
},
];
// blog - category
const blogCategoryRoute = getAllCategoryRoute(ROOT_CATEGORY);
const blogCategorySiteMap: MetadataRoute.Sitemap = blogCategoryRoute.map(
(category) => ({
url: `${BASE_CONFIG.URL}/blog/posts/${category}`,
lastModified: new Date().toISOString(),
changeFrequency: 'weekly',
priority: 0.8,
}),
);
// blog - post
const blogPostsSiteMap: MetadataRoute.Sitemap = allPosts.map((post) => ({
url: `${BASE_CONFIG.URL}/blog/posts${post.slug}`,
lastModified: new Date(post.modifiedAt || post.createdAt),
changeFrequency: 'daily',
priority: 0.7,
}));
// NOTE:: 이거 없으면 빌드 터짐
// docs: TroubleShooting - Fix dynamic sitemap detection - https://github.com/vercel/next.js/pull/60356
// 생성되는 사이트맵 경로 : [dv] {URL}/sitemap.xml/1 | [pr] {URL}/sitemap/1
export async function generateSitemaps() {
return [{ id: 1 }];
}
export default function sitemap(): MetadataRoute.Sitemap {
return [...routeSiteMap, ...blogCategorySiteMap, ...blogPostsSiteMap];
}
우선 sitemap()
함수에서 MetadataRoute.Sitemap
의 객체 리스트를 반환하는 것이 핵심이에요. 때문에 마지막 export default
구문에서부터 시작해보죠. 저는 sitemap을 구성하는 페이지들을 3가지로 나눠봤어요.
- routeSiteMap : home을 포함하는 비정형 route
- blogCategorySiteMap : 블로그의 카테고리 및 포스트 리스트
- blogPostsSiteMap : 특정 포스트의 세부 페이지
그리고 각각의 SiteMap에 대해서는 하드하게 지정하거나(1) 생성하는 로직별로 순회(2, 3)해서 만들었습니다. 네, 여기까지는 쉬웠어요. 왜 제가 애를 먹었는지 시행착오의 과정을 소개할게요.
sitemap trouble shooting
Pull Request에서 일부 정리한 내용을 풀어서 정리해보겠습니다.

sitemap.xml이 확인이 안 된다
sitemap.ts
을 통해 localhost:3000/sitemap.xml
에서 sitemap을 확인할 수 있을 것이라 기대했는데 잘 안 됐어요. 왜 그럴까 계속 알아보니 next.config.mjs
에서 export: 'output'
으로 설정해둔 것 때문이었습니다. 이걸 삭제하니 sitemap.ts
가 sitemap.xml
을 잘 만들어주어 확인이 가능했어요.
// next.config.mjs
const nextConfig = {
reactStrictMode: true,
swcMinify: false,
// export: 'output',
sassOptions: {...},
};
sitemap.ts가 있으면 빌드가 터진다
sitemap.ts
파일이 없을 때는 빌드가 정상적으로 됐는데, sitemap.ts
을 추가하자마자 바로 빌드에 실패해버렸어요. 파일 자체의 문제인가 해서 동적으로 순회하는 모든 로직을 배제하고 정적 객체만 return했음에도 불구하고 말이죠.
정말 애를 많이 먹었는데, 원인은 dynamic routes
때문이었어요. 결론부터 말하면 dynamic routes
가 있는 경우엔 반드시 generateSitemaps()
가 정의되어야 한다는 거에요.
/app
└─ /blog
└─ /posts
└─ /[...slug]
└─ page.tsx
우선 저는 이런 구조로 포스트 리스트와 포스트 디테일을 slug로 판단하는 dynamic routes를 사용하고 있어요. 그런데 분명 sitemap.ts
에서는 별도의 linear한 자료구조를 통해서 sitemap.xml을 구성할 수 있음에도 불구하고, sitemap.ts
만 있으면 빌드가 터졌죠. next.js repo와 인터넷을 돌아다니며 조사한 결과 generateSitemaps
를 추가해주니 빌드가 정상적으로 동작했습니다. 그래서 아래와 같은 코드가 나오게 된 거죠.
// NOTE:: 이거 없으면 빌드 터짐
// docs: TroubleShooting - Fix dynamic sitemap detection - https://github.com/vercel/next.js/pull/60356
export async function generateSitemaps() {
return [{ id: 1 }];
}
generateSitemaps
는 미리 선언한 id를 담은 list를 순회하며 sitemap()
을 실행하여 sitemap list를 만드는 함수예요. 구글에서는 1개의 sitemap에 최대 50,000개까지 페이지 정보를 넣을 수 있는데, 거대 사이트의 경우 5만 개의 페이지가 넘길 수 있기 때문에 sitemap을 잘라가며 만드는 등, 용도에 따라 사용하기 위해 마련된 함수인 거죠. id가 1이면 /sitemap/1
의 경로로 route처럼 취급되어 sitemap이 생성돼요.
dynamic routes에서 발생하는 문제를 이렇게 해결한다는 게 의아하긴 하지만, 저는 이렇게 해결했고, 단지 이 문제 해결을 위한 generateSitemaps
의 사용이었으므로 sitemap()
함수에서 id는 별도로 사용하지 않았습니다.
참고자료
- Next.js - generateSitemaps
- build breaks when mentioning "generateSitemaps" in a comment
- Fix bug sitemap() without generateSitemaps fails
- Fix dynamic sitemap detection
generateSitemaps를 넣었는데도 빌드가 터진다
산 넘어 산이었어요. 빌드가 잘 되는 것 같았는데, 다시 빌드가 터졌어요. generateSitemaps
를 마지못해 만들었으니, id를 'main'으로 하여, 모니터링 사이트에 sitemap을 등록할 때 /sitemap/main
같은 느낌으로 등록하고 싶었거든요. 그래서 처음엔 아래처럼 코드를 작성했습니다.
export async function generateSitemaps() {
return [{ id: 'main' }];
}
그런데 development 환경에서는 /sitemap.xml/main
로 잘 확인이 되는데, production 환경에서는 잘 안 되더라고요. 왜 그런가 했더니, 알고보니 id가 string이면 문제가 생겨서 고쳐진 이력(링크)이 있었어요. 고쳐진 버전 이후인데도 왜 안 되는지는 모르겠지만 그냥 id를 다시 number 1로 지정해줬습니다... (path는 /sitemap/1
)
참고자료
development와 production의 sitemap 경로가 다르다
development 환경에서는 /sitemap.xml/1
로 확인이 되는데, production 환경에서는 /sitemap.xml/1
로 조회해도 not-found만 뜨더라고요.

왜 그런지 정말 알 수가 없었는데요, development와 production의 sitemap 경로를 다르게 처리했던 전력이 있더라고요.

그래서 /sitemap/[id]
로 통일하는 것으로 수정이 되었는데요, 아무튼 /sitemap/1
의 경로로 조회해보니 잘 조회가 됨을 확인했습니다.

RSS
RSS의 이해
RSS는 Really Simple Syndication 또는 Rich Site Summary의 약자에요. 웹사이트의 업데이트 내용을 자동으로 사용자에게 전달하기 위해 사용되는 XML 기반의 데이터 형식입니다. RSS는 주로 블로그, 뉴스 사이트, 팟캐스트 등 자주 업데이트되는 콘텐츠를 구독할 때 사용된다고 하네요.
rss와 sitemap
sitemap이 검색 엔진 크롤러에게 사이트 구조와 URL, 기타 정보를 한 번에 제공하기 위한 목적이라면, rss는 업데이트된 콘텐츠를 사용자와 애플리케이션에 전달하기 위한 목적이 강합니다. 그래서 SEO에는 크게 영향을 주지 않는다는 입장도 있어요.
하지만 구글의 경우 SEO 수집 방법이 자세하게는 드러나지 않고, 네이버와 구글 모두 모니터링 사이트에 rss를 등록할 수 있기 때문에, 밑져야 본전이라는 생각으로 RSS도 추가해보았습니다.
next.js와 rss
RSS는 next.js에서 공식적으로 지원하는 것은 없어서, npm RSS 라이브러리를 활용하는 블로그 포스팅(링크)을 참고했어요. sitemap
처럼 category와 post에 대한 기존 linear data를 기반으로 코드를 짰습니다. 생각보다 쉽게 풀렸어요.
feed.xml/route.ts
next.js에서는 특정 path에 대한 페이지를 만들 수 있는데요, {URL}/feed.xml
에서 rss feed를 확인하기 위해 /app/{path}/route.ts
을 만들고 내부에서 Response 코드를 작성해줬어요.
RSS 객체에서 config를 넣은 feed instance를 만들고, feed.item()
에 페이지마다 데이터를 넣는 자체적인 문법을 활용해 feed instance를 확장합니다. 그리고 이를 Response에 실어보내는 거죠.
// src/app/feed.xml/route.ts
import { BASE_CONFIG } from '@/configs/base.config';
import { allPosts } from '@/contentlayer/generated';
import { allCategories } from '@/routes/category/category.constant';
import { getCategoryRoute } from '@/routes/category/category.util';
import RSS from 'rss';
export const GET = async () => {
const feed = new RSS({
title: BASE_CONFIG.TITLE,
description: BASE_CONFIG.DESCRIPTION,
site_url: BASE_CONFIG.URL,
feed_url: `${BASE_CONFIG.URL}/feed.xml`,
image_url: `${BASE_CONFIG.URL}/imgs/open-graph/thumbnail.png`,
copyright: `All rights reserved by ${BASE_CONFIG.AUTHOR}`,
pubDate: new Date(),
});
allCategories.map((category) => {
feed.item({
title: category.name.ko,
description: '',
url: `${BASE_CONFIG.URL}/blog/posts/${getCategoryRoute(category.path)}`,
date: new Date(),
});
});
allPosts.map((post) => {
feed.item({
title: post.title,
description: post.excerpt || '',
url: `${BASE_CONFIG.URL}/blog/posts${post.slug}`,
date: new Date(post.modifiedAt || post.createdAt),
});
});
return new Response(feed.xml({ indent: true }), {
headers: {
'Content-Type': 'application/atom+xml; charset=utf-8',
'Cache-Control': 'public, s-maxage=1200, stale-while-revalidate=600',
},
});
};
feed.xml

OpenGraph
OpenGraph의 이해
오픈그래프는 웹페이지의 콘텐츠를 소셜 미디어 플랫폼에서 공유할 때 시각적으로 풍부하고 일관된 정보를 표시하도록 돕는 메타데이터 프로토콜입니다. 페이스북에서 처음 개발했으나, 현재는 트위터, 링크드인, 카카오톡 등 다양한 소셜 미디어 플랫폼에서 널리 사용되고 있다고 하네요.
플랫폼에 링크를 붙여넣었을 때, 자동으로 페이지의 title, description, thumbnail 등 많은 정보가 카드 형식으로 보여지는 것들이 바로 페이지의 오픈그래프를 읽고 자체적인 포맷팅을 하기 때문입니다. 그래서 외부에 공유할 때 링크 접속 없이도 preview를 하기 위해서는 꼭 필요한 정보이죠.
지금 블로그의 공유 UI 개선을 위해 꼭꼭꼭 필요한 요소였습니다.
next.js와 opengraph
Next.js 공식문서(링크)에 따르면 Next13 app router부터 Metadata
라는 객체를 layout.tsx
와 page.tsx
에서 선언하여 페이지의 메타데이터를 설정할 수 있는데요, 오픈그래프도 Metadata 설정의 일부로 설정할 수 있습니다.
코드는 생략
- 코드가 너무 방대해요. Next.js 포스팅이 아니니까 내용이 깊은 부분은 줄이겠습니다.
- 설명하기 어려운 프로젝트 코드의 이해가 선행되어야 해요.
- 코드 리팩토링이 조금 더 필요해요.
다음에 Next.js Metadata 설정에 관련해서 깊게 다루는 포스팅을 별도로 제작해서 소개하겠습니다.
주요 기획 내용
- 모든 플랫폼에서 segment별 title, description, thumbnail이 확인되어야 한다.
- post detail에서 별도의 thumbnail이 없다면, 가장 최하위 category의 thumbnail이 매핑되어야 한다.
- post thumbnail은 별도로 지정 가능하고, 절대 경로인 경우와, next /public에 지정한 상대 경로인 경우 모두 대응 가능해야 한다.
Figma Thumbnail 제작 과정
저는 저만의 썸네일 체계를 만들고 싶었어요. 그리고 이미 버전 1부터 가져온 꽤 많은 양의 포스트와 카테고리 경로 시스템도 모두 커버하고 싶었죠. 그래서 figma에서 나름의 디자인 규칙을 가진 썸네일을 모두 만들었습니다.


vercel metadata 확인
원래 metadata가 잘 적용되었는지 확인하기 위해서는 production 환경으로 배포가 되어야 합니다. 하지만 Vercel에서는 브랜치만 push되어도 해당 브랜치의 형상을 기준으로 metadata를 확인할 수 있는데, 이 방법을 공유하려 해요.
Vercel Project Deployments

우선 Vercel의 내 프로젝트 공간에서 Deployments 탭을 확인해봅니다. main 브랜치가 아니더라도, github repo에 push한 브랜치는 자동 CI/CD로 인해 해당 브랜치의 형상으로 배포가 되어있어요.
원하는 형상을 클릭해봅시다. (작업중이라면 아마 제일 최근 배포 형상이겠죠?)
Vercel Open Graph
특정 형상에 대해 배포 상태를 확인하는 Deployments
탭, 소스코드를 확인하는 Source
탭, Open Graph를 확인하는 Open Graph
탭 등이 보입니다. 이 중 Open Graph
탭을 클릭합니다.

현재 임시 배포된 브랜치의 형상에서 특정 path의 metadata 정보와 opengraph 데이터를 확인할 수 있습니다. 이를 통해 원하는 페이지의 title, description, thumbnail이 잘 적용되었는지를 main 브랜치 배포, 즉 불필요한 Pull Request의 누적 없이 확인할 수 있었어요.
절대 경로와 상대 경로
여기서 조금 애를 먹은 게 있는데, openGraph의 images 경로를 설정하는 거였어요.
export const metadata: Metadata = {
...
openGraph: {
...
images: [
{
url: `${BASE_CONFIG.URL}/imgs/thumbnails/main.png`,
width: 1200,
height: 630,
},
],
}
}
처음에는 이렇게 설정했는데, 이렇게 되면 배포된 production siteUrl의 /public
폴더에 저장된 이미지 파일을 끌어오기 때문에 production 배포 이전에는 vercel의 preview에서 제대로 확인이 안됐어요.
절대경로가 편의성이 떨어지니 상대경로를 사용해서 url: '/imgs/thumbnails/main.png'
로 작성했어요. 이렇게 하니 vercel의 브랜치가 배포된 임시 url에서도 상대경로로 해당 배포 형상 source에 저장된 이미지를 끌어오며 local 환경에서도, vercel open graph에서도 잘 확인할 수 있었습니다.

그런데 막상 production 환경에서는 잘 되지 않았죠. 그 이유는 잘 모르겠습니다. 사이트 head에서는 정상적으로 images의 path가 url이 붙어서 정상적으로 보여졌거든요. 이유를 찾다가 우선순위가 아닌 것 같아 넘어갔습니다.
결론적으로는 local과 dev모드에서는 상대경로를, 배포된 이후에는 production에서는 절대 경로를 조건적으로 적용하는 방식으로 해결했습니다.
// env.constant.ts
...
export const isDevMode = ENV_TYPE === ENV.DV;
export const filePrefix = isDevMode ? '' : BASE_CONFIG.URL;
// layout.tsx
export const metadata: Metadata = {
...
images: [
{
url: `${filePrefix}/imgs/thumbnails/main.png`,
},
],
}
이렇게 환경변수를 활용하여 development(local)과 production을 구분하고, metadata의 image path를 포함한 모든 file의 prefix를 조건적으로 설정해준 것이죠. 이렇게 잘 해결할 수 있었습니다.
작업 결과
위의 과정을 통해서 robots.txt
, sitemap
, rss(feed.xml)
, metadata
, opengraph
가 설정되었어요. 이를 검색 엔진 사이트에 등록해야 검색 엔진에서 제 블로그를 색인화하고 등록해줍니다. 이 결과를 보시죠.
Google Search Console
Google Search Console LNB 메뉴에서 [색인생성] - [Sitemaps]
를 클릭하면 sitemap과 rss feed를 등록하는 페이지를 만날 수 있어요.

Naver Search Advisor
사이트 간단 체크
robots.txt, title/description 등 기본 설정, opengraph를 포함합니다. All Check 달성에 성공했어요.

RSS

Sitemap

OpenGraph
home부터 post list, post detail에 이르기까지 페이지별로 title과 description, thumbnail이 적절하게 잘 매핑되는 것을 확인할 수 있었어요.

예시로는 Notion에 공유한 링크 북마크들이지만, 카카오톡, Slack, Twitter 등 다른 플랫폼에 공유해도 잘 보여짐을 확인할 수 있었습니다. 이게 정말 뿌듯하고 짜릿한 순간이었어요.
마치며
아쉬움
SEO는 OpenGraph처럼 바로 결과가 나오는 경우도 있지만, 검색 엔진에서 크롤링과 색인화를 거치는 시간이 고려되어야 하기 때문에 바로 결과를 보지 못하는 게 아쉬웠어요. 그리고 아직은 미지의 영역이에요. 설정은 했지만 색인이 잘 될 지도 미지수이고, 앞으로 어떤 어려움을 추가로 겪게 될 지도 종잡을 수 없습니다.
기쁨
그래도 벼르고 있던 페이지별 title, description, thumbnail을 구축했다는 사실이 너무 기쁘게 다가왔어요. 앞으로의 포스팅에 있어서도 구조를 잡기 좋을 것 같네요. 또한 Google Analytics를 통해 내 포스팅 중 어떤 것들이 인기가 있고, 얼마나 많은 유저들이 내 블로그를 찾아주는지 등 모니터링의 초석을 다지게 되어서 너무 기쁩니다.
남은 과제
하지만 아직 더 다뤄야 할 것들이 있어요. generateMetadata
를 통한 Metadata 생성도 조금 더 모듈화와 코드 정리가 필요해요. 지금은 어떤 걸 넣었을 때, 결과가 어떻게 나오는지 확인하는 것과, 보다 더 기능적인 면을 확보하는 데에 신경 썼기 때문이에요. 리팩토링을 안 하고 포스팅을 이렇게 해도 되나 싶은데 정리가 되면 추가로 포스팅을 하거나 본 포스팅을 수정할 것 같네요.
이 밖에도 Footer에 RSS 페이지로 연결되는 RSS 로고도 넣을 거고요, category나 tag들에 대한 페이지들이 나오면 또 sitemap과 rss 처리를 해줘야겠죠. 이번 기반 설정이라는 마음으로 앞으로 필요할 때 더 깊게 다뤄보면 좋을 것 같습니다.