react-helmet-async으로 SEO 최적화하기

최주희·2024년 9월 24일
2
post-thumbnail
post-custom-banner

react-helmet-async란

react app의 부분을 동적으로 관리할 수 있도록 도와주는 라이브러리이다.

react-helmet의 문제점을 해결하기 위해 만들어진 포크(fork) 버전이다.

이전 react-helmet는 왜 사용하지않는가?

기본 개념 설명을 해보자면,

  • SSR : 사용자가 페이지를 요청하면, 서버에서 HTML을 미리 만들어서 보내준다 → 이때 서버는 동시에 여러 요청을 처리할 수 있다.
    • ex) A 사용자가 페이지를 요청할 때와, B 사용자가 다른 페이지를 요청할 때 서버가 동시에 두 요청을 처리할 수 있죠.
  • thread-safe : 여러 요청이 동시에 들어오더라도 서로 데이터를 침범하지 않고, 안전하게 처리되는 것

react-helmet이 thread-safe하지 않은 react-side-effect에 의존하고 있어 서버 사이드 렌더링 환경에서 비동기 작업을 처리할 때 문제가 발생할 수 있다 .⇒ thread-safe를 지원하지 않기 때문

Q. 구체적으로 어떤 문제가 생기나요?

예를 들어, A 사용자가 페이지 1을 요청하고, B 사용자가 페이지 2를 요청한다고 가정해봅시다.

  • A와 B의 요청이 동시에 처리되면, 두 요청의 <head> 태그 정보가 섞여버릴 수 있습니다. 즉, A의 요청에 B의 페이지 정보가 들어가거나, 반대로 B의 페이지에 A의 정보가 들어가는 혼란스러운 상황이 발생할 수 있죠.

이게 바로 thread-safe하지 않다는 말의 의미입니다. 동시에 여러 요청이 처리될 때, 서로의 데이터가 충돌하고 섞여버리는 문제가 발생할 수 있다는 뜻이죠.

[react-helmet의 package.json]

  "dependencies": {
    "object-assign": "^4.1.1",
    "prop-types": "^15.7.2",
    "react-fast-compare": "^3.1.1",
    "react-side-effect": "^2.1.0"
  },

위의 코드를 보면 react-side-effect가 디펜던시로 추가 되어 있음을 확인할 수 있었다.

그럼 react-helmet-async의 package.json에는있을까? 없다.

  "dependencies": {
    "invariant": "^2.2.4",
    "react-fast-compare": "^3.2.2",
    "shallowequal": "^1.1.0"
  },

실제로 react-helmet은 마지막 업데이트가 2024.09 기준 4년전이 마지막이다.

Q. 왜 각 페이지별로 title이나 meta 태그 등을 설정하기 왜 어려움?

: 하나의 index.html을 두고 있기 때문에 페이지 마다 페이지를 설명하는 메타태그를 설정하기 어렵다.

Q. 왜 크롤러가 모든 페이지의 정보를 가져갈 수 없는가?

위와 같은 이유로 브라우저 크롤러가 페이지를 크롤링 할 때 모든 페이지의 정보를 가져올 수 없어 SEO에는 좋지 않다.

react-helmet-async 사용해보기

1. 설치

npm i react-helmet-async

2. 컴포넌트 감싸기

function App() {
  return (
    <ThemeProvider theme={theme}>
     ...
        <HelmetProvider>
            <Router />
        </HelmetProvider>
		...
    </ThemeProvider>
  );
}

3. 각 페이지 별로 Helmet 컴포넌트를 사용해 title과 메타 태그 등을 통해 원하는 페이지 정보를 검색엔진에 노출

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

const HomePage = () => {
  return (
    <div>
      <Helmet>
        <title>Home - My Website</title>
        <meta name="description" content="Welcome to the home page of My Website" />
        <meta property="og:title" content="Home - My Website" />
        <meta property="og:description" content="This is the home page of My Website" />
        <meta property="og:url" content="https://www.mywebsite.com/" />
        <meta property="og:type" content="website" />
      </Helmet>
      <h1>Home Page</h1>
      <p>Welcome to the home page!</p>
    </div>
  );
};

export default HomePage;

1) 주요 메타 태그

(1) <meta name="description">

  • 설명: 페이지의 내용을 설명하는 태그
  • 사용 목적: 검색 엔진 결과 페이지(SERP)에서 페이지 미리보기를 제공하는 데 사용

(2) <meta name="viewport">

  • 설명: 페이지의 뷰포트 설정을 정의
  • 사용 목적: 모바일 친화적인 웹 페이지를 만들기 위해 사용됩니다. 특히 반응형 웹 디자인에서 필수

2. 소셜 미디어 관련 메타 태그

(1) Open Graph Tags (OG 태그)

  • 설명: 소셜 미디어에서 웹 페이지를 공유할 때 표시되는 정보를 제어하는 메타 태그. Facebook, LinkedIn 등에서 사용
  • 예시:
    <meta property="og:title" content="웹 페이지 제목">
    <meta property="og:description" content="웹 페이지에 대한 설명">
    <meta property="og:image" content="https://www.example.com/image.jpg">
    <meta property="og:url" content="https://www.example.com/">
    
  • 주요 속성:
    • og:title: 공유할 때 보이는 제목.
    • og:description: 공유할 때 보이는 설명.
    • og:image: 공유할 때 표시되는 이미지 URL.
    • og:url: 해당 콘텐츠의 URL.
    • og:type: 콘텐츠의 유형을 정의 (예: article, website).

3-1. metaTag 컴포넌트 생성해서 재사용하기

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

interface Props {
  title: string;
  description: string;
  keywords: string;
  imgsrc?: string;
  url: string;
}
function MetaTag(Meta: Props) {
  const { title, description, keywords, imgsrc, url } = Meta;

  return (
    <Helmet>
      <title>{title}</title>

      <meta name='description' content={description} />
      <meta name='keywords' content={keywords} />

      <meta property='og:type' content='website' />
      <meta property='og:title' content={title} />
      <meta property='og:site_name' content={title} />
      <meta property='og:description' content={description} />
      <meta property='og:image' content={imgsrc} />
      <meta property='og:url' content={url} />

      <link rel='canonical' href={url} />
    </Helmet>
  );
}

export default MetaTag;

[가지고 와서 재사용]

 <MetaTag
        title='리크루트 - 전통주와 함께하는 새로운 경험'
        description='리크루트 메인 페이지에서 전통주와 관련된 다양한 정보를 만나보세요.'
        keywords='리크루트, 전통주, 메인 페이지'
        imgsrc={IMAGES.banner}
        url='https://www.licruit.site'
      />

3-2. 문제점

[index.html]

[main.tsx] ⇒ home

  1. 초기 로드시 index.html의 메타 데이터가 먼저 노출
  2. react app이 로드되면서 메타 데이터 업데이트
    1. react와 react-helmet-async는 js가 실행된 후에 각 페이지의 동적인 메타 태그나 타이틀을 업데이트된다.
    2. 즉, index.html에서 기본 타이틀이 보여지고, 그 후 js가 실행된 후에야 메타데이터가 동적으로 변경

  1. 검색 엔진 크롤러는 js를 실행하여 동적으로 변한 메타 태그도 수집할 수 있다.
    하지만, js가 실행하지 않는 크롤러에서는 index.html의 기본 메타 태그 정보만을 수집한다.
    - 즉, react로 변경된 메타 데이터를 인식하지 못하고, 초기 Index.html에 있는 기본 메타 정보만을 가져가게 되기에 SEO가 불리할 수 있다.

문제점 해결 방안 : Prerenderer 사용

[참고자료1]
[참고자료2]
[참고자료3]
[참고자료4]

profile
큰 목표보단 꾸준한 습관 만들기
post-custom-banner

0개의 댓글