Skip to content

🏷 SEO: Sitemap & Meta tag

정다현 edited this page Dec 11, 2022 · 3 revisions

Knoticle 서비스에는 유저들이 작성한 다양한 글이 존재한다. 이러한 글들이 검색 엔진에 노출되도록, 검색 엔진 최적화(SEO)를 하는 것이 주요한 목표 중 하나다. 본문에서는 SEO를 위해 Sitemap과 Meta tag를 작성한 과정에 대해 소개하도록 하겠다.

SEO 기본 가이드

Google의 SEO 기본 가이드 에 따르면 다음과 같은 부분들을 개선할 수 있다.

  1. 사이트맵 등록하기
  2. 메타 태그 작성하기
  3. robots.txt

Sitemap

사이트맵이란?

웹사이트에서 구글이나 네이버와 같은 검색 엔진에 색인할 모든 페이지를 나열한 XML 파일

사이트맵이 필요한 이유

Google의 SEO 기본 가이드에 따르면…

내 사이트가 Google에서 검색되도록 하기 위한 첫 번째 단계는 Google이 사이트를 발견할 수 있도록 하는 것입니다. 이때는 사이트맵을 제출하는 것이 가장 좋습니다. 사이트맵은 사이트에 있는 파일로서 새 페이지나 변경된 페이지가 있을 때 이를 검색엔진에 알려 줍니다.

  • Googlebot 및 기타 웹 크롤러는 한 페이지에서 다른 페이지로 연결되는 링크를 따라 이동하여 웹을 크롤링하는데, 다른 사이트가 링크되어 있지 않으면 페이지를 찾지 못할 수 있다.

  • 사이트맵은 검색엔진 크롤러에 어떤 페이지가 있는지 알려주어, 검색엔진이 찾기 어려운 페이지도 문제없이 크롤링될 수 있게 한다.

  • 내 사이트는 사이트맵이 필요할까?

    • 매우 큰 사이트거나, 연결되는 외부 링크가 많지 않고, 사이트끼리 잘 연결되지 않은 상태라면 사이트맵이 필요할 수 있다.

    • 반면 크기가 작은 사이트거나, 내부적으로 긴밀히 연결된 사이트라면 사이트맵을 사용하지 않아도 된다.

🤔 Knoticle의 사이트맵을 생성하려면

  • 사용자가 작성한 글 페이지들을 모두 사이트맵에 등록해야한다.

    글의 주소가 knoticle.app/viewer/{책 id}/{글 id} 와 같이 구성되어 있다.

  • 글들이 계속 업데이트 되기 때문에 sitemap을 동적으로 생성해야 한다.

    존재하는 {책 id}/{글 id} 를 DB에서 일정 시간 간격으로 받아와서 sitemap

    을 생성해야 한다.

    next-sitemap이라는 라이브러리 사용 (링크)

next-sitemap으로 dynamic/server-side sitemap 생성하기

  1. DB로부터 생성해야 하는 페이지 정보들을 받아온다.
  • 사용자가 작성한 글 페이지의 주소를 완성하기 위해서는 책 id글 id가 필요하다.

  • Knoticle 서비스에서는 scraps 테이블에 책 id글 id가 저장되어 있다.

    → 그 중 글이 원본인 아이템(즉, 원본 책 id글 id의 조합)만 받아오도록 했다. 검색엔진에 원본 글만 잡히는 것이 맞다고 생각했다.

  1. 받아온 정보들로 페이지마다 field를 생성한다.

    field는 다음과 같은 형태로 구성되어 있는데,

        loc: `${process.env.NEXT_PUBLIC_CLIENT_URL}/viewer/${scrap.book_id}/${scrap.article_id}`,
        changefreq: 'daily',
        priority: '1.0',
        lastmod,
    • changefreq: 사이트가 얼마나 자주 바뀌는지에 대한 정보. 검색 엔진한테 대략 어느 주기로 페이지의 변화를 체크해야 하는지 알려준다.
    • priority: 사이트 내에서 페이지들의 상대적인 우선 순위를 나타낸다.

    → 하지만 Google 검색 센터에 따르면, Google에서는 <priority> 및 <changefreq> 값을 무시한다고 한다.

  2. 생성된 fields로 sitemap.xml을 구성한다.

코드는 다음과 같다.

// pages/sitemap.xml.tsx 

import { GetServerSidePropsContext } from 'next';
import { getServerSideSitemap } from 'next-sitemap';

import { getScrapsApi } from '@apis/scrapApi';

export default function SiteMapXML() {
  return <></>;
}

export const getServerSideProps = async (context: GetServerSidePropsContext) => {
  const scraps = await getScrapsApi();

  const lastmod = new Date().toISOString();

  const defaultFields = [
    {
      loc: `${process.env.NEXT_PUBLIC_CLIENT_URL}`,
      changefreq: 'daily',
      priority: '1.0',
      lastmod,
    },
  ];

  const scrapFields = scraps.map((scrap: { book_id: number; article_id: number }) => ({
		loc: `${process.env.NEXT_PUBLIC_CLIENT_URL}/viewer/${scrap.book_id}/${scrap.article_id}`,
    changefreq: 'daily',
    priority: '1.0',
    lastmod,
  }));

  const fields = [...defaultFields, ...scrapFields];

  return getServerSideSitemap(context, fields);
};

사이트맵 제출하기

  • 검색엔진 크롤러가 사이트맵을 찾을 수 있도록 검색엔진별로 제출하는 것이 필요하다.

Meta tag

메타 태그란?

  • <meta> 태그는 해당 문서에 대한 정보인 **메타데이터(metadata)**를 정의할 때 사용한다

    : <base>, <link>, <script>, <style>, <title> 요소와 같은 다른 메타데이터 관련 요소들이 나타낼 수 없는 다양한 종류의 메타데이터를 제공할 때 사용되며, 이렇게 제공된 정보는 브라우저나 검색 엔진, 다른 웹 서비스에서 사용하게 된다

메타 태그를 작성해야 하는 이유

  • SEO를 위해서는 메타 태그를 작성해주어야 한다. 구글의 SEO 기본 가이드에 다음과 같은 내용이 있다.

    메타 설명 태그는 중요합니다. Google에서 설명 메타 태그를 Google 검색결과에서 페이지의 스니펫으로 사용할 수 있기 때문입니다.

    • 여기서 스니펫이란 검색 결과가 표시되는 부분이다.

      image

      : 타이틀은 <title> 태그와 관련되어 있고, 아래 설명은 <meta name=”description”>과 관련되어 있다.

어떤 메타 태그를 포함시켜야 할까?

구글 공식 문서에 따르면, 구글에서 인식하는 메타 태그에는 다음이 있다.

  • <meta name="description" content="A description of the page" />

    : 간단한 페이지 설명

  • <meta name="viewport" content="...">

    : 휴대기기에서 페이지를 렌더링하는 방법을 브라우저에 알리는 태그. 이 태그를 사용하면 페이지가 모바일 친화적이라는 사실을 Google에 알릴 수 있다.

  • <meta http-equiv="Content-Type" content="...; charset=..." /> <meta charset="..." >

    : 페이지의 콘텐츠 유형과 문자 집합을 정의하는 태그. 가능한 경우 Unicode/UTF-8을 사용하는 것이 좋다.

따라서,

  • <title><meta name=”description”> 태그를 페이지마다 다르게 생성하자.
  • 그 외 open graph에 관련된 메타 태그도 페이지마다 다르게 지정해주자.

Open graph란?

  • 사이트를 공유했을 때 사이트에 대한 정보를 미리보기로 확인할 수 있도록, 미리보기에 담을 메타데이터를 표준화하기 위한 프로토콜

적용하기

  • 뷰어페이지에 적용하기

    1. getServerSideProps로 article 데이터 받아오기
    export const getServerSideProps: GetServerSideProps = async (context) => {
      const [bookId, articleId] = context.query.data as string[];
      const article = await getArticleApi(articleId);
    
      return { props: { article } };
    };
    • getServerSideProps는 서버에서 동작하는 코드이므로, 함수 내부에서 next/router를 사용할 수가 없다. 처음에 사용했더니 다음과 같은 오류가 발생했다.

      image

    • 공식 문서에 따르면 context를 사용해야 한다. context 객체 내의 query에서 dynamic route의 query parameter를 가져올 수 있다.

    1. 가져온 아티클 정보로 title 및 메타 태그 완성하기
    import Head from 'next/head';
    
    interface ViewerHeadProps {
      articleTitle: string;
      articleContent: string;
    }
    
    export default function ViewerHead({ articleTitle, articleContent }: ViewerHeadProps) {
      return (
        <Head>
          <title>{articleTitle}</title>
          <meta name="description" content={articleContent.slice(0, 150)} />
          <meta name="viewport" content="initial-scale=1.0, width=device-width" />
          <meta property="og:title" content={articleTitle} />
          <meta property="og:description" content={articleContent.slice(0, 150)} />
          <meta property="og:type" content="website" />
          <meta property="og:url" content="https://www.knoticle.app" />
          <meta property="og:image" content="https://kr.object.ncloudstorage.com/j027/knoticle.png" />
        </Head>
      );
    }
  • open graph 적용 결과

    아래와 같이 knoticle 서비스의 글 링크를 복사해서 붙여넣으면 다음과 같이 표현된다.

    image

    og:title에 넣은 글 제목과, og:description에 넣은 글 본문의 일부를 확인할 수 있다.

Robots.txt

robots.txt란?

  • robots.txt 파일은 크롤러가 사이트의 어느 부분에 액세스할 수 있는지에 관한 규칙이 포함된 간단한 텍스트 파일

robots.txt 파일의 역할

  • robots.txt 파일을 사용하여 크롤링 트래픽을 관리하거나(서버에 Google 크롤러의 요청으로 인한 과부하가 발생할 것으로 생각되는 경우) 사이트에서 중요하지 않은 페이지 또는 비슷한 페이지의 크롤링을 방지할 수 있다.

    • 웹페이지가 Google에 표시되는 것을 방지하기 위한 메커니즘이 아니다.
  • sitemap.xml의 위치를 등록하여 sitemap이 어딨는지 알려준다.

robots.txt 작성

  • Knoticle 서비스에서 글을 쓸 수 있는 에디터 페이지(editor)와 검색 페이지(search)는 검색 엔진에 노출되지 않았으면 했기에 아래와 같이 작성하였다.
# *
User-agent: *
Allow: /

# Disallow
User-agent: *
Disallow: /editor
Disallow: /search

# Host
Host: https://www.knoticle.app/

# Sitemaps
Sitemap: https://www.knoticle.app/sitemap.xml # Index sitemap

결과

  • Lighthouse SEO 점수가 80 → 97까지 상승

    • 이전

      image

    • SEO를 위한 방법들 적용 후

      image

  • Lighthouse SEO 점수를 높이는 것은 어렵지 않았다. title 및 meta 태그를 작성한 것이 결정적이었던 것 같다.

  • 점수를 높이는 게 쉬운 만큼, 웬만한 사이트들은 높은 점수를 유지하고 있을텐데 그 중에서도 검색 엔진에 잘 노출되게 하려면 더 다양한 방법을 시도해봐야 할 것 같다.

참고 자료

사이트맵이란 무엇인가요? | Google 검색 센터 | 문서 | Google Developers

The Importance of The XML Sitemap Priority and Changefreq Tags

사이트맵 만들기부터 제출하기: 쉬운 단계별 가이드 | TBWA 데이터랩

Data Fetching: getServerSideProps | Next.js

Robots.txt Sitemap: Add Your Sitemap To Your Robots.txt File

What is Open Graph and how can I use it for my website?

Clone this wiki locally