Next.js에서 SEO 도전!

AnSuebin·2023년 12월 27일
0
post-thumbnail

검색 최적화
저희 회사는 핵심 상품인 앱을 웹으로도 운영 중입니다.
검색 최적화된 웹을 통해 유저를 유입하기 위함입니다.

실제로 비대면 진료가 멈춘 이후로 마케팅을 중단했음에도 불구하고,
검색을 통해 찾아 들어오는 유저가 지속적으로 증가하고 있습니다.

저는 최근 웹사이트에 새로운 페이지를 추가하는 작업을 하였고,
여기서 제가 작업한 SEO 구현 포인트에 대해 다뤄보고자 합니다.


Next.js를 사용한 이유

Next.js는 SSR을 간편하게 구축할 수 있는 프레임워크입니다.
react만으로 구축된 CSR는 처음에 빈 html을 가져오기 때문에 SEO에 취약하다는 단점을 가지고 있습니다. 반면에 SSR은 pre-reloading을 통해 미리 데이터가 렌더링 된 페이지를 가져올 수 있기 때문에 SEO 친화적인 사이트를 구축하는 데 유용합니다.

저희는 검색 최적화로 유저를 유입하는 게 목표였고, 그런 점에서 Next.js를 사용하였습니다.

SEO 성능 높이기 위해 한 일들

1. SSR을 통한 프리패칭
getServerSideProps를 통해서 서버로 데이터를 렌더링해주었습니다.
query 값에 동적으로 바뀌어야 할 데이터를 뽑아내도록 구현하였습니다.

interface Context extends NextPageContext {}

export async function getServerSideProps({ query }: Context) {
  const id = query && query.id ? Number(query.id) : 0;
  const detail = await APIGetDetail(id);
  let tag = {};

  if (detail) {
    tag = {
      pageTitle: detail.title,
      title: detail.title,
      description: detail.category,
      og: {
        title: detail.title,
        description: detail.category,
        url: `https://[url]/detail/${detail.id}`,
      },
    };
  }

  return { props: { id, detail, tag } };
}

2. 동적 메타 태그 만들기
Head 태그를 가진 MetaHead라는 공통 컴포넌트를 제작하였습니다.
그리고 페이지별 별로 SSR를 통해 가져온 데이터를 전달해 주었습니다.
1번 예시 코드의 tag 객체를 활용해 동적 메타 태그를 구성하였습니다.

const MetaHead: React.FC<Props> = ({ tag }) => {
  const { pageTitle, title, description, keywords, og, themeColor } = tag;

  return (
    <Head>
      <title>{pageTitle || '기본 페이지 타이틀'}</title>
      <meta charSet="utf-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <link rel="shortcut icon" href="/favicon.ico"></link>
      <meta
        name="viewport"
        content="width=device-width, height=device-height, initial-scale=1 viewport-fit=cover"
      />
      <meta name="theme-color" content={themeColor || '#fdffff'} />
      <meta name="title" content={title || '기본 타이틀'} />
      <meta
        name="description"
        content={
          description ||'기본 설명'
        }
      />
      <meta
        name="keywords"
        content={
          keywords ||'키워드'
        }
      />
      ...
    </Head>

3. 동적 사이트 맵 만들기
사이트맵이란 웹 크롤러가 웹 사이트의 페이지를 쉽게 찾을 수 있도록 돕기 위해 만들어진 파일입니다. 저는 next-sitemap 라이브러리를 사용하여 구현하였습니다.

큰 페이지별로 sitemap.xml 파일을 만들어 index 파일 내에 상세 내용을 넣어주었습니다.
따라서 next-sitemap.config.js에 파일구조로 인해 생긴 페이지에 대한, 빠져야 할 페이지와 넣어야 할 페이지를 작성해 주었습니다.

// next-sitemap.config.js

module.exports = {
  siteUrl: 'https:// 기본 URL',
  generateRobotsTxt: false,
  exclude: [
    '/페이지1/sitemap.xml',
    '/페이지2/sitemap.xml',
  ],
  robotsTxtOptions: {
    additionalSitemaps: [
      'https://www.doctorbella.kr/페이지1/sitemap.xml',
      'https://www.doctorbella.kr/페이지2/sitemap.xml',
    ],
  },
};

페이지별 sitemap에는 getServerSideProps로 각 페이지별 list에 관련된 내용을 가져와, 아래와 같이 getServerSideSitemap으로 반환해주었습니다.

// sitemap/index.tsx

  const contents = await APIGetCounselingList({ page: 1 });
  const lastmod = new Date().toISOString();

  if (!contents) {
    return { notFound: true };
  }

  const contentFields = contents.items.map((content) => ({
    loc: `${SITE_URL}/counseling/detail/${content.id}`,
    lastmod,
  }));
  
  const fields = [...contentFields];
  return getServerSideSitemap(ctx, fields);

마치며

사실 next.js를 업무에 사용하며 처음에는 생각대로 되지 않았습니다.
그래서 머리를 쥐어뜯은 적이 참 많았죠. 그러나 저희 프로덕트를 위해서는 꼭 해야만 하는 일이었고, 지금은 과거의 저를 아주 기특하게 생각합니다.

그리고 가장 중요한 포인트인데
하고 나면 참 별거 아닙니다.

profile
고객에게 명료한 의미를 전달하고, 명료한 코드를 통해 생산성 향상에 기여하고자 노력합니다.

0개의 댓글