[북잡 프로젝트] 구글 상위 노출을 위한 메타 태그 설정 가이드 (feat. React-Helmet)

송수빈송수빈
3 min read

이번 프로젝트에서는 react-helmet을 활용해 메타 태그를 설정하고 구글에 '북잡'을 검색했을 때 상위에 노출되는 것을 목표로 하고 있다. 🙌🏻

일단 React-Helmet무엇인지 + 사용하는 이유대해 알아보는 것이 좋을 것 같아서 정리해봤다 ✨

React-Helmet이 뭔데 ? 🧐

  • react-helmetReact 앱에서 <head> 태그의 내용을 동적으로 변경할 수 있게 도와주는 라이브러리이다.

  • 즉 HTML 문서의 <title>, <meta> 태그, <link> 태그 등을 컴포넌트 안에서 코드로 쉽게 설정할 수 있게 해주는 도구

React를 사용할 때 특히 필요한 이유 설명해줄게 ✅

1. SPA의 구조 때문

  • React 앱은 기본적으로 SPA이기 때문에 페이지를 이동해도 브라우저는 HTML 파일을 새로 요청하지 않는다

  • 그래서 일반적인 HTML <head> 내용이 고정되어 있어서 SEO나 공유 미리보기(OG 태그)가 페이지별로 다르게 적용되지 않는 한계가 있다.

react-helmet은 이 문제를 해결해준다. (페이지 단위로 <title>, <meta>, <og:...> 정보를 설정할 수 있게 해줌)


2. 검색 엔진 최적화(SEO)를 위해

  • 검색엔진은 페이지의 <title><meta description>을 보고 해당 페이지의 내용을 판단한다

  • react-helmet을 쓰면 페이지마다 고유한 정보를 제공할 수 있어서 검색에 더 잘 노출될 수 있는 장점이 있다.


3. 소셜 미디어 공유 시 미리보기 설정 가능

  • 페이스북, 트위터 등에서 링크를 공유할 때 뜨는 미리보기 정보는 대부분 <meta property="og:...">를 기반으로 한다.

  • react-helmet으로 공유용 썸네일, 설명, 제목 등을 페이지별로 설정 가능하다는 장점이 있다.

사용 방법 ✍🏻

//설치 방법 
yarn add react-helmet-async

index.html

<!doctype html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />

    <title>북잡</title>

    <meta
      name="description"
      content="출판업계 종사자를 위한 구인·구직 플랫폼, 북잡. 채용 정보부터 자유게시판까지 업계 사람들과 소통하세요."
    />
    <meta
      name="keywords"
      content="book-job, 북잡, 출판업계, 구인, 구직, 채용, 출판 채용, 출판 구직, 자유게시판, 커뮤니티"
    />
    <meta name="author" content="book-job" />

    <meta property="og:title" content="북잡" />
    <meta
      property="og:description"
      content="출판업계 종사자를 위한 구인·구직 플랫폼, 북잡. 채용 정보부터 자유게시판까지 업계 사람들과 소통하세요."
    />
    <meta property="og:image" content="/metatag.png" />
    <meta property="og:url" content="https://book-job.co.kr" />
    <meta property="og:type" content="website" />

    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="북잡" />
    <meta
      name="twitter:description"
      content="출판업계 종사자를 위한 구인·구직 플랫폼, 북잡. 채용 정보부터 자유게시판까지 업계 사람들과 소통하세요."
    />
    <meta name="twitter:image" content="/metatag.png" />

    <script>
      window.global = window
    </script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

이렇게 되어있다 …!

하지만 SPA의 한계로 index.html에서 메타 태그를 정적으로 지정하면 SNS나 검색엔진은 index.html의 태그만 인식하는 문제가 있다.

이를 보완하기 위해 이제 공통 컴포넌트를 만들었다.

SeoHelmet.jsx

import { Helmet } from 'react-helmet'

const SeoHelmet = ({ title, description, image, url }) => (
  <Helmet>
    <title>{title}</title>
    <meta name='description' content={description} />
    <meta property='og:title' content={title} />
    <meta property='og:description' content={description} />
    <meta property='og:image' content={image} />
    <meta property='og:url' content={url} />
    <meta property='og:type' content='website' />
    <meta name='twitter:card' content='summary_large_image' />
    <meta name='twitter:title' content={title} />
    <meta name='twitter:description' content={description} />
    <meta name='twitter:image' content={image} />
  </Helmet>
)

export default SeoHelmet

MainPage.jsx

     <SeoHelmet
        title='북잡 - 출판인을 위한 구인·구직 플랫폼'
        description='출판업계 채용/구직 정보와 자유게시판을 북잡에서 확인해보세요.'
        image='https://book-job.co.kr/metatag.png'
        url='https://book-job.co.kr'
      />

JobMainPage.js

    <SeoHelmet
        title='북잡 | 출판업계 자유게시판'
        description='출판 업계의 자유게시글을 한눈에 확인해보세요. 실시간으로 업데이트됩니다.'
        image='https://book-job.co.kr/metatag.png'
        url='https://book-job.co.kr/job'
    />

CommiunityMainPage

      <SeoHelmet
        title='북잡 | 출판업계 채용·구직 게시판'
        description='출판 업계의 구인·구직 게시글을 한눈에 확인해보세요. 최신 채용 공고와 구직 글이 실시간으로 업데이트됩니다.'
        image='https://book-job.co.kr/metatag.png'
        url='https://book-job.co.kr/job'
      />

공통 컴포넌트를 활용해서 설정해주니 정말 편하다 !

여기서 주의할 점 !

  1. <HelmetProvider>로 앱을 감싸야 한다

main.jsx

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { HelmetProvider } from 'react-helmet-async'
import './index.css'
import App from './App.jsx'
import './styles/font.css'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <HelmetProvider>
      <App />
    </HelmetProvider>
  </StrictMode>,
)

📌 왜 필요한가요?

  • react-helmet-async는 내부적으로 Context API를 사용한다.

  • 그래서 <Helmet> 컴포넌트가 정상적으로 작동하려면 최상위에서 <HelmetProvider>로 감싸야 한다

  • 감싸지 않으면 <title>, <meta> 설정이 작동하지 않거나 콘솔에 경고가 뜰 수 있다.

2. <Helmet>컴포넌트 가장 위에서 선언해야 한다

📌 왜 가장 위에서 선언하나요?

  • 사실 아래에 있어도 동작은 하지만 SEO 측면에서는 선언 시점이 빠를수록 좋기 때문에 가장 위에서 선언하는 것이 좋다!

  • <Helmet>은 렌더링 시 <head> 태그를 업데이트하므로 페이지 진입 시점에 가장 먼저 실행되도록 구성하는 것이 안전하다

    (크롤러가 메타 정보를 놓치지 않고 읽도록 도와주는 중요한 팁✨)

0
Subscribe to my newsletter

Read articles from 송수빈 directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

송수빈
송수빈