# 간단한 SEO 적용(NEXT.JS) B2C 서비스에서, 특히 웹서비스를 기반으로 한다면 SEO는 가장 중요한 지표 중 하나이다. SEO(search engine optimization)의 증진은 검색 엔진이 웹 페이지를 잘 찾아낼 수 있게끔 하는 과정입니다. ## 기본적인 내용 ### 검색엔진 검색엔진은 미리 웹상의 정보를 수집하여 색인 목록을 만들어두고 사용자가 검색엔진을 사용했을 때 관련 키워드를 색인목록에서 찾아 노출시킵니다. 검색엔진이 정보를 수집하여 색인목록을 만드는 과정은 봇(또는 크롤러)의 크롤링을 통해 이루어집니다. 따라서 SEO의 증진은 봇이 웹페이지를 색인을 더 잘 할수 있게끔 만드는 과정입니다. ### SEO 가이드 전 세계 웹 사용자의 92%가 구글을 이용한다고 하는 만큼 구글에 서비스가 노출 되는 것은 중요합니다. 구글은 이를 위한 SEO 가이드 및 개발 도구(search console)등을 제공합니다. 가이드를 살펴보면 url의 설정 기준, meta 태그의 설정, 사이트 맵, robots.txt등 다양한 기준이 정의되어 있습니다. ### 기본적인 SEO 측정 Chrome의 경우 개발자 도구에 Lighthouse를 통해 SEO지표를 측정할 수 있습니다. Lighthouse를 통해 분석하면 5가지 지표가 나오는데 SEO 지표는 해당 웹 사이트가 몇몇 기준에 부합하는 정도를 점수화 해서 보여줍니다. 또한 어떤 부분이 설정되었는지 되어있지 않은지를 알려주어 작업할 수 있도록 돕습니다. 아래는 "모두의 개발"의 Lighthouse 점수표와 SEO에 대한 세부 내용입니다. 현재 해당 페이지에 robots.txt 파일이 없음을 알려주고 있습니다. ![img](https://gitblogserver.cf/public/1667137763661-lighthouse.png) ![img](https://gitblogserver.cf/public/1667138021364-seo%20score.png) ## 기초적인 SEO 작업 ### head의 설정 head는 웹 페이지를 표현하는 문서(html)의 정보를 담은 meta data 세트로 검색 엔진이 분석하는 주요 요소 입니다. 구글 SEO 가이드에 따르면 메타 데이터에 유효한 요소인 `title`, `meta`, `link`등의 요소만 넣을 것을 권장합니다. 또한 읽을 수 있는 meta 태그만 넣을것을 권장하는 만큼 적절한 tag를 입력하여 처리하도록 합시다. 자세한 내용은 가이드를 참고할 수 있도록 합시다. [구글 SEO 가이드](https://developers.google.com/search/docs/crawling-indexing/valid-page-metadata?hl=ko) React나 NEXT.JS에서 head의 작성은 이전 글인 "**React \<head\>**" 를 참고합니다. [React \<head\>](https://blog-seolim.vercel.app/article/1) ### sitemap.xml / robots.txt sitemap.xml과 robots.txt는 모두 봇(크롤러)가 페이지를 색인하기 위해 참고하는 파일입니다. robots.txt는 크롤러가 페이지에 접근할 때 어떤 페이지를 접근할지에 대한 설정을 가지고 있고 sitemap.xml은 해당 서비스가 어떻게 구성되어있는지를 봇에게 알려주어 크롤링 효율을 높입니다. robots.txt는 아래와 같이 작성됩니다. ``` User-agent: * Allow: / Sitemap: http://localhost:4000/sitemap.xml Sitemap: http://localhost:4000/server-sitemap-index.xml ``` User-agent는 봇의 이름을 설정하고 Allow/Disallow를 통해 접근을 하게 할지 말지를 결정합니다. 또한 Sitemap의 위치를 알려줍니다. sitemap은 여러 포맷으로 작성될 수 있습니다. 구글의 경우 rss, xml, text 여러 포맷을 지원합니다. 아래처럼 작성합니다. ```xml <?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="https://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="https://www.w3.org/1999/xhtml" xmlns:mobile="https://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="https://www.google.com/schemas/sitemap-image/1.1" xmlns:video="https://www.google.com/schemas/sitemap-video/1.1"> <url><loc>http://localhost:4000</loc><lastmod>2022-10-30T10:22:43.162Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> <url><loc>http://localhost:4000/login</loc><lastmod>2022-10-30T10:22:43.162Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> <url><loc>http://localhost:4000/post</loc><lastmod>2022-10-30T10:22:43.162Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url> </urlset> ``` 위 두 파일을 root path에서 정적파일로 제공하면 봇은 두 파일을 참고합니다. ## next-sitemap NEXT로 SSR을 만들어 둔다면 동적으로 페이지를 생성하는 경우가 많습니다. 그 때마다 sitemap을 재설정하는 것은 비효율 적이므로 stiemap.xml또한 동적으로 생성하여 봇에게 제공하는 것이 좋습니다. 이를 생성하는 스크립트를 직접 만들 수 도 있겠지만 `next-sitemap`을 사용하면 쉽게 sitemap을 간단히 개발할 수 있습니다. [next-sitemap](https://www.npmjs.com/package/next-sitemap) `next-sitemap` 은 작성된 configuration에 따라 기본적인 사이트맵(sitemap)을 build 과정에서 생성하고 동적페이지에 대해서 server-sitemap.index.xml를 동적으로 생성하고 기본 사이트맵에서 가르키도록 생성됩니다. 아래와 같이 configuration파일을 작성합니다. ```typescript /** @type {import('next-sitemap').IConfig} */ module.exports = { siteUrl: 'your url', generateRobotsTxt: true, /** robots.txt를 생성할지 여부 */ sitemapSize: 7000, /** 이 하단은 동적페이지를 생성할 경우 필요한 옵션 */ exclude: ['/server-sitemap-index.xml'], // <= exclude here robotsTxtOptions: { additionalSitemaps: [ `yout url/server-sitemap-index.xml`, // <==== Add here ], }, } ``` 위 설정인 동적 페이지 생성을 통한 xml을 제공하려면 추가적으로 pages에 server-sitemp.index.xml 폴더를 생성하고 index.tsx를 아래와 같이 작성합니다. 스크립트는 요구되는 url정보를 list로 받아 xml를 동적으로 생성합니다. 아래 예시는 서버로 부터 게시글을 받아와 모든 게시글 페이지를 sitemap에 등록하여 보여주는 과정입니다. ```typescript // pages/server-sitemap-index.xml/index.tsx import { getServerSideSitemapIndex } from 'next-sitemap'; import { GetServerSideProps } from 'next'; export const getServerSideProps: GetServerSideProps = async (ctx) => { const { articles } = await fetch(`${process.env.BASEURL}/api/articles`).then((res) => res.json()); return getServerSideSitemapIndex( ctx, articles.map(({ id }: { id: number }) => `${process.env.SITE_URL}/article/${id}`), ); }; // Default export to prevent next.js errors export default function SitemapIndex() {} ``` 마지막으로 기본 빌드시 sitemap을 생성할 수 있도록 아래 스크립트를 package.json에 추가한다. ```json "script": { "postbuild": "next-sitemap --config {your config file}", } ``` 혹은 `next-sitemap.config.js`를 루트에 작성하면 `next-sitemap`만으로 동작시킬 수 있습니다. build후 public 디렉토리에 sitemap.xml이 생성된 것을 확인할 수 있습니다. ## CSR vs SSR "CSR은 SEO가 나쁘다" 라는 것은 반은 맞고 반을 틀린말입니다. CSR의 SEO가 나쁜 까닭은 처음으로 보내는 index.html이 비어있고 이후 스크립트(js)를 통해 화면을 그리기에 봇은 사이트를 빈 페이지로 인식하기 때문입니다. 다만 최신 구글 봇은 js 코드를 해석하고 sitemap등을 통해 SPA의 라우팅에 대한 정보도 넘겨줄 수 있습니다. 또한 meta데이터는 index.html을 통해 제공할 수 있으므로 어느정도 SEO를 보장할 수 있습니다. 그러나 구글 에드센스 신청등에서 SSR은 높은 점수를 받는 편으로 확인되고 html바디를 직접적으로 그리는 만큼 SEO에 대한 관점으로 볼 때는 SSR을 권장하는 편입니다. ## 마무리 SEO 향상을 위한 기초적인 방법을 제시하였습니다. 이 외에도 적절한 키워드나 edge function(lambda edge)등 SEO를 향상시키는 다양한 방법론과 기술이 존재합니다. SEO는 개발 연습에 있어 간과하기 쉽지만 꼭 한번씩은 이해하고 실습해보기 바랍니다.