안녕하세요, 프론트엔드 개발자 엄성준입니다.
React 기반 SPA 환경에서 SEO 최적화를 위해 react-helmet이나 react-helmet-async는 사실상 표준처럼 사용되어 왔습니다. 저 역시 개인 프로젝트와 사내 서비스에서 이 라이브러리들을 꾸준히 활용해 왔습니다.
하지만 실제 서비스 환경을 운영하며, index.html에 정의한 초기 메타 태그와 페이지 이동 시 동적으로 생성되는 메타 태그가 중복되는 문제를 발견했습니다. 이 글에서는 기존 라이브러리의 한계와 이를 해결하기 위해 직접 react-head-safe를 개발하게 된 과정을 공유합니다.
1. SPA 환경에서 SEO가 여전히 까다로운 이유
React SPA는 초기 로딩 시 서버로부터 빈 HTML(root div만 존재하는)을 전달받습니다. 이후 JavaScript가 실행되며 콘텐츠와 메타 태그가 렌더링되는데, 여기서 두 가지 문제가 발생합니다.
- 크롤러의 한계: 일부 크롤러는 JS 실행 전의 정적 HTML만 수집합니다.
- 초기 정보 부재: JS 실행 전까지 title이나 og 태그가 비어 있어 소셜 공유 시 정보가 누락됩니다.
이를 방지하기 위해 보통 index.html에 기본적인 메타 태그를 미리 작성해 두는 방식을 병행하게 됩니다.
2. react-helmet-async 사용 시 발생하는 중복 이슈
index.html에 기본 태그를 두고 react-helmet-async로 동적 관리를 시도하면 다음과 같은 상황이 벌어집니다.
- 현상: title 태그는 정상 교체되지만, meta나 og 태그는 기존 태그 뒤에 새로운 태그가 계속 누적됩니다.
- 원인: react-helmet-async는 자신이 직접 생성하고 관리하는 태그(데이터 속성이 붙은 태그)만 제어합니다. 즉, index.html에 이미 존재하는 정적 태그는 건드리지 않습니다.
결과: <head> 내부에 동일한 property를 가진 메타 태그가 2개 이상 존재하게 되며, 크롤러는 어떤 정보를 신뢰할지 알 수 없게 됩니다. (보통 가장 먼저 발견된 정적 태그를 우선시함)
3. 해결을 위한 선택 직접 만들기
이 문제를 해결하기 위해 두 가지 선택지를 고민했습니다.
- 기존 오픈소스에 기여(PR)하기
- 문제를 명확히 정의하여 나만의 라이브러리 구축하기
저는 평소 목표였던 "실제 문제를 해결하는 오픈소스 배포"를 실천하기 위해 두 번째 길을 택했고, 그렇게 react-head-safe를 개발하게 되었습니다.
4. react-head-safe 안전한 헤드 관리
react-head-safe는 SPA 환경에서 메타 태그를 예측 가능하게 관리하는 데 초점을 맞췄습니다.
핵심 설계 원칙
- 충돌 방지: index.html에 정의된 초기 태그가 있더라도, 라이브러리가 실행되는 순간 해당 속성(name, property)을 찾아 제거합니다.
- 단일화(Singleton): 현재 페이지에 해당하는 메타 태그만 <head>에 존재하도록 보장합니다.
- 예측 가능성: CSR 환경에서 페이지 이동 시 useLayoutEffect를 사용하여 DOM 반영 우선순위를 높였습니다.
| 구분 | react-helmet-async | react-head-safe |
| 정적 태그 대응 | 무시 (중복 발생) | 감지 후 즉시 교체/제거 |
| 태그 관리 | 관리 대상 태그만 제어 | 동일 속성 기준 전체 제어 |
| 설정 복잡도 | Context Provider 필요 | Provider 없이 즉시 사용 |
5. 간단 사용 방법
사용법은 매우 직관적입니다. 별도의 Provider 설정 없이 필요한 컴포넌트 내에서 선언적으로 사용하면 됩니다.
import { ReactHeadSafe } from 'react-head-safe';
function MyPage() {
return (
<>
<ReactHeadSafe
title="My Page Title"
description="This is the page description for SEO."
keywords="react,seo,meta tags"
ogTitle="My Page Title for Social Media"
ogDescription="This is the description for social media."
ogImage="https://example.com/image.jpg"
/>
<div>Your page content...</div>
</>
);
}
6. 프로젝트 확인하기
react-head-safe는 오픈소스로 공개되어 있습니다. SPA 환경에서 메타 태그 중복 문제로 고민하고 계신다면, 아래 링크에서 자세한 사용법을 확인하고 프로젝트에 적용해 보세요!
피드백이나 버그 리포트, 그리고 Star는 프로젝트를 유지하고 발전시키는 데 큰 힘이 됩니다.
- NPM: react-head-safe
- GitHub: umsungjun/react-head-safe
GitHub - umsungjun/react-head-safe: A CSR-only React head manager that prevents duplicate meta tags and safely manages document
A CSR-only React head manager that prevents duplicate meta tags and safely manages document head elements. - umsungjun/react-head-safe
github.com
마치며
react-head-safe는 초기 진입 시에는 index.html의 기본 정보를 노출하여 크롤러에 대응하고, 페이지 전환 후에는 안전하게 새로운 정보로 교체하는 가장 현실적인 SEO 전략을 취합니다.
아직 초기 단계이지만, 실무에서 겪은 불편함을 직접 해결했다는 점에서 뜻깊은 작업이었습니다. 저와 비슷한 고민을 하시는 분들께 작은 도움이 되길 바랍니다.
'지식 정리 📝' 카테고리의 다른 글
| Autowini 프론트엔드 분리 프로젝트 CI/CD 파이프라인 구축 (Bitbucket 기반) 2 (0) | 2026.01.19 |
|---|---|
| 필터 변경 시 메뉴가 접히던 문제, TanStack Query placeholderData로 해결 (2) | 2026.01.15 |
| React i18n 다국어 처리 빌드 크기 최적화 2 (0) | 2025.12.30 |
| Autowini 프론트엔드 분리 프로젝트 CI/CD 파이프라인 구축 (Bitbucket 기반) 1 (1) | 2025.11.27 |
| GitHub Copilot을 활용한 사용하지 않는 번역 키 제거 (0) | 2025.11.13 |