2023년 온라인 졸업전시 웹사이트를 배포한 후 검색 엔진 최적화를 진행하고 프로젝트를 마무리한 과정을 기록해두기 위해서 글을 작성했습니다. 전 과정을 기록하지 않고 출처에 나와있는 과정들을 따라했기에 생략이 되어있을 수도 있습니다!
sitemap.xml과 robots.txt 설정
티스토리 블로그의 검색 최적화와 비슷했습니다. robots.txt를 생성하고, Sitemap 정보에 대해서 특정 url로 진입하라는 내용을 넣어주면 됐습니다. sitemap의 경우에 블로그는 동적으로 생성되는 로직이 자동으로 되어있었습니다.
하지만 Nextjs는 Sitemap을 직접 넣어주거나, 동적으로 생성되게 하기 위해서 pages/api 폴더를 사용했습니다. 그리고 api 폴더로 강제되는 url을 next.config.js 파일에서 rewrites 함수를 통해서 다른 url로 매핑했습니다.
// pages/api/sitemap.ts
import { NextApiRequest, NextApiResponse } from "next";
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.statusCode = 200;
res.setHeader("Content-Type", "text/xml");
// Instructing the Vercel edge to cache the file
res.setHeader("Cache-control", "stale-while-revalidate, s-maxage=3600");
// generate sitemap here
const xml = `
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://sak-exhibition.vercel.app/</loc>
<lastmod>2023-07-17T11:19:38+00:00</lastmod>
<priority>1.00</priority>
</url>
<url>
<loc>https://sak-exhibition.vercel.app/home</loc>
<lastmod>2023-07-17T11:19:38+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://sak-exhibition.vercel.app/about</loc>
<lastmod>2023-07-17T11:19:38+00:00</lastmod>
<priority>0.64</priority>
</url>
<url>
<loc>https://sak-exhibition.vercel.app/exhibition</loc>
<lastmod>2023-07-17T11:19:38+00:00</lastmod>
<priority>0.64</priority>
</url>
<url>
<loc>https://sak-exhibition.vercel.app/contactus</loc>
<lastmod>2023-07-17T11:19:38+00:00</lastmod>
<priority>0.64</priority>
</url>
</urlset>`;
res.end(xml);
}
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = (phase) => {
return {
async rewrites() {
return [
{
source: "/sitemap.xml",
destination: "/api/sitemap",
},
];
},
// ...다른 설정들
};
};
module.exports = nextConfig;
Google Search Console과 Naver Search Advisor 연결
검색 로그를 대시보드에서 확인하기 위해서는 아래처럼 meta 태그를 넣어주면 됩니다. 저는 혹시몰라서 환경변수에 추가해서 넣어주었습니다.
{/* Naver Site Verification*/}
<meta
name="naver-site-verification"
content={process.env.NEXT_PUBLIC_NAVER_SITE_VERIFICATION}
/>
{/* Google Site Verification*/}
<meta
name="google-site-verification"
content={process.env.NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION}
/>
검색을 해보니 GitHub 레포지토리의 About에 적히는 내용들이 description 속성으로 들어가서 검색을 했을 때, 보여지는 것을 보고, 아래 오른쪽 이미지 처럼 영어와 한글을 둘 다 적어주었습니다.
Open Graph 동적으로 설정
Naver Search Advisor에서 저희 웹사이트의 조회결과를 알려주는 데 Open Graph에 대해서 설정되어있지 않다라는 것을 알려주었습니다. 찾아보니 Open Graph Protocol 이라는 것을 알게 되었고, 자세히 들어다 보지는 않았지만 네이버에서 가이드해주는 것 대로, meta 태그만 잘 넣어주면 되는 것으로 파악했습니다.
meta 태그를 주어진 형식대로 잘 넣어주면, 카카오톡에 링크를 공유 했을 때, 해당하는 open graph meta 태그를 보고 썸네일, 제목, 설명, 링크를 통해서 카드를 생성해줍니다.
Google Analytics 연결
사실 웹사이트가 규모가 있거나, 수익을 창출하는 웹사이트는 아니였지만, 하는 김에 경험해보자는 마음으로 GA도 연결해봤습니다. Nextjs의 경우에는 13버전 부터 Script 태그를 따로 제공해주기 때문에 검색하는데 시간이 걸렸습니다. 막상 찾으면 금방 적용하니 어렵지는 않았습니다.
{/* 구글 애널리틱스 */}
<Script
strategy="afterInteractive"
src={`https://www.googletagmanager.com/gtag/js?id=${ga_key}`}
/>
<Script
id="gtag-init"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${ga_key}', {
page_path: window.location.pathname,
});
`,
}}
/>
meta tag 동적 할당
// pages/exhibition/[...slug].tsx
export default function ProjectPage({
projectData,
}: {
projectData: IProject;
}) {
return (
<>
<Head>
<title>SAK-Exhibition | {projectData.name}</title>
<meta property="og:type" content="website" />
<meta
property="og:title"
content={`SAK-Exhibition | ${projectData.name}`}
/>
<meta property="og:description" content={projectData.excerpt} />
<meta
property="og:image"
content={`https://sak-exhibition.vercel.app/posts-images/${projectData.slug.replaceAll(
"/",
"_"
)}/thumbnail.jpg`}
/>
<meta
property="og:url"
content={`https://sak-exhibition.vercel.app/exhibition/${projectData.slug}`}
/>
</Head>
<MainLayout>
<Project projectData={projectData} />
</MainLayout>
</>
);
}
전체 코드
// pages/_app.tsx
export default function App({ Component, pageProps }: AppProps) {
const router = useRouter();
const clientId = process.env.NEXT_PUBLIC_NAVER_MAP_CLIENT_ID;
const ga_key = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_KEY;
return (
<>
<Head>
<title>SAK-Exhibition</title>
<meta
name="description"
content="SAK-Exhibition Generated by Sae-sak"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="msapplication-TileColor" content="#FBFBFB" />
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png" />
{/* Naver Site Verification*/}
<meta
name="naver-site-verification"
content={process.env.NEXT_PUBLIC_NAVER_SITE_VERIFICATION}
/>
{/* Google Site Verification*/}
<meta
name="google-site-verification"
content={process.env.NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION}
/>
</Head>
{/* 구글 애널리틱스 */}
<Script
strategy="afterInteractive"
src={`https://www.googletagmanager.com/gtag/js?id=${ga_key}`}
/>
<Script
id="gtag-init"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${ga_key}', {
page_path: window.location.pathname,
});
`,
}}
/>
{/* 네이버지도 API */}
<Script
type="text/javascript"
src={`https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=${clientId}`}
defer
></Script>
{/* 렌더링할 컴포넌트 */}
<Component {...pageProps} key={router.route} />
</>
);
}
참고
https://darrengwon.tistory.com/246
https://www.zodaland.com/tech/16
https://jisoo-log.tistory.com/19
https://velog.io/@zinukk/d-v8gyfq4x
https://otter-log.world/post/next-seo-optimazation
https://searchadvisor.naver.com/guide/markup-content
https://blog.ab180.co/posts/open-graph-as-a-website-preview
'Framework > - Next.js' 카테고리의 다른 글
Nextjs standalone 빌드 와 nginx 연결 후 font 파일을 찾지 못하는 현상 기록 (0) | 2023.05.15 |
---|
댓글