React-Helmet과 React-Snap를 이용한 SEO

씌미씌미·2022년 11월 7일
6

SSR VS CSR

SEO는 SSR 혹은 CSR을 이용하여 적용할 수 있습니다.

SSR은 서버사이드에서 정적인 페이지로 렌더링이 되어서 사용자에게 내려옵니다. 따라서 초기 로딩속도가 빠르고 SEO에 사용되는 meta 태그들이 미리 정의됩니다.

CSR은 브라우저가 자바스크립트를 받아와 동적으로 렌더링합니다. 첫 로딩시에 필요한 파일크기는 더 크지만 다 받기만 하면 동적으로 빠르게 렌더링 하기 때문에 사용자가 느끼는 UX에 유리합니다.

이번 프로젝트에서는 next.js나 gatsby를 사용하지 않았으므로 CSR환경으로 SEO를 적용하였습니다.

❗️PROBLEM 1️⃣ - 메타태그 정의 문제

CSR환경에서는 하나의 HTML파일로 모든 페이지를 구성하기 때문에 meta 태그 정의에 어려움이 있었습니다.

😎 SOLUTION - 페이지별 메타태그가 적용됨

react-helmet 라이브러리를 사용하여 meta 태그를 동적으로 제어하였습니다.

  • react-helmet 라이브러리 설치

    yarn add react-helmet

  • helmet을 이용한 코드

import { Helmet } from 'react-helmet-async';

const Meta = ({ attribute, amount, id }: MetaProps) => {
  const { brand, name, imageUrl } = attribute;
  return (
    <Helmet>
      <title>{`${brand} ${name}`}</title>
      <meta name="description" content={`${amount}`} />
      <meta property="og:type" content="website" />
      <link href={imageUrl} />
      <meta property="og:url" content={`${process.env.PUBLIC_URL}/${id}`} />
      <meta name="og:title" content={`${brand} ${name}`} />
      <meta name="og:description" content={`${amount.toLocaleString()}`} />
      <meta property="og:image" content={imageUrl} />
      <meta property="og:image:width" content={IMAGE_SIZE.width.toString()} />
      <meta property="og:image:height" content={IMAGE_SIZE.height.toString()} />
    </Helmet>
  );
};

< 각 웹 페이지 별 title과 meta태그가 다르게 적용됨 >

  • item1 페이지

  • item2 페이지

❗️PROBLEM 2️⃣ - 크롤러가 하나의 html 파일만을 바라봄

여전히 html 파일은 하나이고 SEO 친화적이지 않습니다. 그래서 크롤러가 웹페이지에 들어왔을때는 하나의 html 파일만을 바라보게 됩니다.
때문에, 공유하였을 시 동적으로 변한 meta 태그가 보이지 않음을 알 수 있었습니다.

😎 SOLUTION - 빌드시 페이지별 html파일이 생성됨으로서 크롤러가 페이지별 html 파일을 볼 수 있음

이를 해결하기 위해 react-snap 라이브러리를 사용하였습니다.

  • react-snap 라이브러리 설치

yarn add react-snap

  • index.tsx 에 hydrate 적용
import { hydrate, render } from 'react-dom';

const container = document.getElementById('root') as HTMLElement;
const root = ReactDOM.createRoot(container);

if (container.hasChildNodes()) {
  ReactDOM.hydrateRoot(
    container,
    <React.StrictMode>
      <ThemeProvider theme={Theme}>
        <GlobalStyle />
        <Router />
      </ThemeProvider>
    </React.StrictMode>
  );
} else {
  root.render(
    <React.StrictMode>
      <ThemeProvider theme={Theme}>
        <GlobalStyle />
        <Router />
      </ThemeProvider>
    </React.StrictMode>
  );
}
  • package.json script 수정
...
...
"scripts": {
  ...
  ...
  "postbuild": "react-snap"
}
...
  • 빌드 시 생성 된 html파일들
    build 폴더 내에 각 페이지별 index.html 파일이 생성됩니다.

위와 같은 방법으로 적용하면, 따로 SSR을 구현하지 않고, 어떤 페이지의 URL로 접속하던 상관없이 똑같은 SPA의 형태를 유지하면서 SEO 친화적인 웹페이지를 만들 수 있습니다.

react-snap이 적용되어 공유된 페이지들

  • 페이스북 공유

  • 카카오톡 공유

카카오톡은 meta 태그의 description이 잘 적용되지 않는 이슈가 존재합니다.

  • 웹 공유
profile
entry software frontend engineer

0개의 댓글

관련 채용 정보