React SEO 전략 및 모범 사례
게시 됨: 2022-03-11React는 선언적 , 모듈식 및 플랫폼 간 대화형 UI를 만들기 위해 개발되었습니다. 오늘날에는 성능이 뛰어난 프론트 엔드 응용 프로그램을 작성하기 위해 가장 인기 있는 JavaScript 프레임워크 중 하나입니다. 처음에 SPA(단일 페이지 응용 프로그램)를 작성하기 위해 개발된 React는 이제 본격적인 웹 사이트 및 모바일 응용 프로그램을 만드는 데 사용됩니다.
기존 웹 개발에 대한 광범위한 경험이 있고 React로 이동하면 HTML 및 CSS 코드가 JavaScript로 이동하는 양이 증가하는 것을 알 수 있습니다. React는 UI 요소를 직접 생성하거나 업데이트하는 것이 아니라 UI의 "상태"를 설명하는 것을 권장하기 때문입니다. 그런 다음 React는 가장 효율적인 방법으로 상태와 일치하도록 DOM을 업데이트합니다.
결과적으로 UI 또는 DOM에 대한 모든 변경은 React의 엔진을 통해 이루어져야 합니다. 개발자에게는 편리하지만 이는 사용자의 로딩 시간이 길어지고 검색 엔진이 콘텐츠를 찾고 색인을 생성하는 데 더 많은 작업이 필요하다는 것을 의미할 수 있습니다.
이 기사에서는 SEO 성능을 갖춘 React 앱과 웹 사이트를 구축하는 동안 직면한 문제를 해결하고 이를 극복하는 데 사용되는 몇 가지 전략을 간략하게 설명합니다.
Google이 웹페이지를 크롤링하고 색인을 생성하는 방법
Google은 모든 온라인 검색의 90% 이상을 받습니다. 크롤링 및 인덱싱 프로세스를 자세히 살펴보겠습니다.
Google 문서에서 가져온 이 스냅샷이 도움이 될 수 있습니다. 이것은 단순화된 블록 다이어그램입니다. 실제 Googlebot은 훨씬 더 정교합니다.
참고 사항:
- Googlebot은 앞으로 크롤링하고 색인을 생성하는 데 필요한 모든 URL이 포함된 크롤링 대기열을 유지합니다.
- 크롤러가 유휴 상태일 때 대기열에서 다음 URL을 선택하고 요청하고 HTML을 가져옵니다.
- HTML을 파싱한 후 Googlebot은 콘텐츠를 렌더링하기 위해 JavaScript를 가져와 실행해야 하는지 결정합니다. 그렇다면 URL이 렌더링 대기열에 추가됩니다.
- 나중에 렌더러는 페이지를 렌더링하기 위해 JavaScript를 가져와 실행합니다. 렌더링된 HTML을 처리 장치로 다시 보냅니다.
- 처리 장치는 웹페이지에 언급된 모든 URL
<a> tags를 추출하여 크롤링 대기열에 다시 추가합니다. - 콘텐츠가 Google 색인에 추가됩니다.
HTML을 구문 분석하는 Processing 단계와 JavaScript를 실행하는 Renderer 단계 사이에는 분명한 차이가 있습니다.
이러한 차이는 Googlebot이 130조 개 이상의 웹페이지를 살펴봐야 한다는 점을 감안할 때 JavaScript를 실행하는 데 비용 이 많이 들기 때문입니다. 따라서 Googlebot은 웹페이지를 크롤링할 때 HTML을 즉시 구문 분석한 다음 나중에 실행할 수 있도록 JavaScript를 대기열 에 넣습니다. Google 문서에는 페이지가 몇 초 동안 렌더링 대기열에 남아 있다고 언급되어 있지만 더 오래 걸릴 수 있습니다.
크롤링 예산의 개념도 언급할 가치가 있습니다. Google의 크롤링은 Googlebot 인스턴스의 대역폭, 시간 및 가용성에 따라 제한됩니다. 특정 예산 또는 리소스를 할당하여 각 웹사이트를 인덱싱합니다. 수천 개의 페이지가 있는 콘텐츠가 많은 대규모 웹사이트(예: 전자 상거래 웹사이트)를 구축 중이고 이러한 페이지에서 콘텐츠를 렌더링하는 데 많은 JavaScript를 사용하는 경우 Google은 웹사이트에서 더 적은 콘텐츠를 읽을 수 있습니다.
참고: 여기에서 크롤링 예산 관리에 대한 Google 가이드라인을 읽을 수 있습니다.
SEO를 위한 React 최적화가 어려운 이유
Googlebot, 크롤링 및 색인 생성에 대한 간략한 개요는 표면을 긁는 것일 뿐입니다. 그러나 소프트웨어 엔지니어는 검색 엔진이 React 페이지를 크롤링하고 인덱싱하려는 잠재적인 문제를 식별해야 합니다. 이제 React SEO를 어렵게 만드는 요소와 이러한 문제를 해결하고 극복하기 위해 개발자가 할 수 있는 일에 대해 자세히 알아볼 수 있습니다.
비어 있는 첫 번째 패스 콘텐츠
React 애플리케이션이 JavaScript에 크게 의존한다는 것을 알고 있으며 종종 검색 엔진에 문제가 발생합니다. React는 기본적으로 앱 셸 모델을 사용하기 때문입니다. 초기 HTML에는 의미 있는 내용이 포함되어 있지 않으며 페이지의 실제 내용을 보려면 사용자 또는 봇이 JavaScript를 실행해야 합니다.
이 접근 방식은 Googlebot이 첫 번째 단계에서 빈 페이지를 감지함을 의미합니다. 콘텐츠는 페이지가 렌더링될 때만 Google에 표시됩니다. 이렇게 하면 수천 페이지를 처리할 때 콘텐츠 인덱싱이 지연됩니다.
로딩 시간 및 사용자 경험
JavaScript 가져오기, 구문 분석 및 실행에는 시간이 걸립니다. 또한 JavaScript는 콘텐츠를 가져오기 위해 네트워크를 호출해야 할 수 있으며 사용자는 요청된 정보를 보기 전에 잠시 기다려야 할 수 있습니다.
Google은 순위 기준에 사용되는 사용자 경험과 관련된 웹 바이탈 세트를 마련했습니다. 로딩 시간이 길면 사용자 경험 점수에 영향을 주어 Google에서 사이트 순위를 낮추도록 할 수 있습니다.
다음 섹션에서 웹사이트 성능을 자세히 검토합니다.
페이지 메타데이터
메타 <meta> 태그는 Google 및 기타 소셜 미디어 웹사이트에서 페이지에 대한 적절한 제목, 미리보기 이미지 및 설명을 표시할 수 있도록 하기 때문에 유용합니다. 그러나 이러한 웹사이트는 이 정보를 얻기 위해 가져온 웹페이지의 <head> 태그에 의존합니다. 이 웹사이트는 대상 페이지에 대해 JavaScript를 실행하지 않습니다.
React는 메타 태그를 포함한 모든 콘텐츠를 클라이언트에 렌더링합니다. 앱 셸은 전체 웹사이트/어플리케이션에 대해 동일하기 때문에 개별 페이지에 대한 메타데이터를 적용하기 어려울 수 있습니다.
사이트맵
사이트맵은 사이트의 페이지, 동영상 및 기타 파일과 이들 간의 관계에 대한 정보를 제공하는 파일입니다. Google과 같은 검색 엔진은 이 파일을 읽고 사이트를 보다 지능적으로 크롤링합니다.
React에는 사이트맵을 생성하는 기본 제공 방법이 없습니다. React Router와 같은 것을 사용하여 라우팅을 처리하는 경우 약간의 노력이 필요할 수 있지만 사이트맵을 생성할 수 있는 도구를 찾을 수 있습니다.
기타 SEO 고려 사항
이러한 고려 사항은 일반적으로 좋은 SEO 관행을 설정하는 것과 관련이 있습니다.
- 사람과 검색 엔진에 페이지에서 예상되는 내용에 대한 좋은 아이디어를 제공하는 최적의 URL 구조를 갖습니다.
- robots.txt 파일을 최적화하면 검색 봇이 웹사이트에서 페이지를 크롤링하는 방법을 이해하는 데 도움이 됩니다.
- CDN을 사용하여 CSS, JS, 글꼴 등과 같은 모든 정적 자산을 제공하고 반응형 이미지를 사용하여 로드 시간을 줄이십시오.
우리는 서버 측 렌더링(SSR) 또는 사전 렌더링을 사용하여 위에서 설명한 많은 문제를 해결할 수 있습니다. 아래에서 이러한 접근 방식을 검토할 것입니다.
동형 반응 입력
isomorphic의 사전적 정의는 "형태가 일치하거나 유사한"입니다.
React 용어로 이것은 서버가 클라이언트와 유사한 형태 를 가짐을 의미합니다. 즉, 서버와 클라이언트에서 동일한 React 구성 요소를 재사용할 수 있습니다.
이 동형 접근 방식을 통해 서버는 React 앱을 렌더링하고 렌더링된 버전을 사용자와 검색 엔진에 보내 JavaScript가 백그라운드에서 로드 및 실행되는 동안 콘텐츠를 즉시 볼 수 있습니다.
Next.js 또는 Gatsby와 같은 프레임워크는 이 접근 방식을 대중화했습니다. 동형 구성 요소는 기존의 React 구성 요소와 상당히 다르게 보일 수 있습니다. 예를 들어 클라이언트 대신 서버에서 실행되는 코드를 포함할 수 있습니다. API 비밀을 포함할 수도 있습니다(서버 코드는 클라이언트로 전송되기 전에 제거되지만).
한 가지 주목해야 할 점은 이러한 프레임워크가 많은 복잡성을 추상화할 뿐만 아니라 독단적인 코드 작성 방식을 도입한다는 것입니다. 이 기사에서 성능 트레이드오프에 대해 자세히 알아볼 것입니다.
또한 렌더링 경로와 웹사이트 성능 간의 관계를 이해하기 위해 매트릭스 분석 을 수행할 것입니다. 그러나 그 전에 웹 사이트 성능을 측정하는 몇 가지 기본 사항을 살펴보겠습니다.
웹사이트 성능 측정항목
검색 엔진이 웹사이트 순위를 매기는 데 사용하는 몇 가지 요소를 살펴보겠습니다.
Google은 사용자의 쿼리에 빠르고 정확하게 응답하는 것 외에도 좋은 웹사이트에는 다음과 같은 속성이 있어야 한다고 생각합니다.
- 빨리 로드해야 합니다.
- 사용자는 너무 많은 대기 시간 없이 콘텐츠에 액세스할 수 있어야 합니다.
- 초기에 사용자의 행동과 상호작용해야 합니다.
- 사용자의 데이터나 배터리 소모를 방지하기 위해 불필요한 데이터를 가져오거나 값비싼 코드를 실행해서는 안 됩니다.
이러한 기능은 대략 다음 측정항목에 매핑됩니다.
- TTFB : Time to First Byte – 링크를 클릭한 후 콘텐츠의 첫 번째 비트가 들어오는 사이의 시간입니다.
- LCP : 가장 큰 내용이 포함된 페인트 – 요청한 기사가 표시되는 시간입니다. 이 값을 2.5초 미만으로 유지하는 것이 좋습니다.
- TTI : Time To Interactive – 페이지가 대화형이 되는 시간(사용자가 스크롤, 클릭 등을 할 수 있음).
- 번들 크기 – 페이지가 완전히 표시되고 대화형이 되기 전에 다운로드되고 실행된 코드의 총 바이트 수입니다.
다양한 렌더링 경로가 각각에 어떻게 영향을 미칠 수 있는지 더 잘 이해하기 위해 이러한 측정항목을 다시 검토할 것입니다.
다음으로 React 개발자가 사용할 수 있는 다양한 렌더 경로에 대해 알아보겠습니다.
렌더 경로
브라우저나 서버에서 React 애플리케이션을 렌더링하고 다양한 출력을 생성할 수 있습니다.
클라이언트 측 렌더링 앱과 서버 측 렌더링 앱 간에 두 가지 기능, 즉 라우팅 과 코드 분할 이 크게 변경됩니다. 아래에서 자세히 살펴보겠습니다.

클라이언트 측 렌더링(CSR)
클라이언트 측 렌더링은 React SPA의 기본 렌더링 경로 입니다. 서버는 콘텐츠가 포함되지 않은 셸 앱 을 제공합니다. 브라우저가 포함된 JavaScript 소스를 다운로드, 구문 분석 및 실행하면 HTML 콘텐츠가 채워지거나 렌더링됩니다 .
라우팅 기능은 브라우저 기록을 관리하여 클라이언트 앱에서 처리합니다 . 이는 요청된 경로에 관계없이 동일한 HTML 파일이 제공되고 클라이언트가 렌더링된 후 보기 상태를 업데이트함을 의미합니다.
코드 분할은 비교적 간단합니다. 경로 또는 사용자 작업을 기반으로 필요한 종속성만 로드되도록 동적 가져오기 또는 React.lazy를 사용하여 코드를 분할할 수 있습니다.
페이지가 콘텐츠를 렌더링하기 위해 서버에서 데이터를 가져와야 하는 경우(예: 블로그 제목 또는 제품 설명) 관련 구성 요소가 탑재 및 렌더링된 경우에만 그렇게 할 수 있습니다.
사용자는 웹사이트에서 추가 데이터를 가져오는 동안 "데이터 로드 중" 기호 또는 표시기를 볼 가능성이 큽니다.
부트스트랩 데이터(CSRB)를 사용한 클라이언트 측 렌더링
CSR과 동일한 시나리오를 고려하지만 DOM이 렌더링된 후 데이터를 가져오는 대신 서버가 제공된 HTML 내부에 부트스트랩된 관련 데이터를 보냈다고 가정해 보겠습니다.
다음과 같은 노드를 포함할 수 있습니다.
<script type="application/json"> {"title": "My blog title", "comments":["comment 1","comment 2"]} </script>구성 요소가 마운트될 때 구문 분석합니다.
var data = JSON.parse(document.getElementById('data').innerHTML);우리는 서버까지 왕복하는 시간을 절약했습니다. 우리는 약간의 트레이드오프를 보게 될 것입니다.
SSRS(정적 콘텐츠에 대한 서버 측 렌더링)
HTML을 즉석에서 생성해야 하는 시나리오를 상상해 보십시오.
예를 들어 온라인 계산기를 만들고 사용자가 /calculate/34+15 (URL 이스케이프 제외)와 같은 쿼리를 실행하는 경우입니다. 쿼리를 처리하고 결과를 평가하고 생성된 HTML로 응답해야 합니다.
생성된 HTML은 구조가 매우 간단하며 생성된 HTML이 제공되면 DOM을 관리하고 조작하기 위해 React가 필요하지 않습니다.
그래서 우리는 HTML과 CSS 콘텐츠만 제공하고 있습니다. 이를 달성하기 위해 renderToStaticMarkup 메소드를 사용할 수 있습니다.
CDN 캐싱을 사용하여 응답을 더 빠르게 제공할 수 있지만 라우팅은 각 결과에 대해 HTML을 다시 계산해야 하므로 서버에서 완전히 처리됩니다. CSS 파일은 더 빠른 후속 페이지 로드를 위해 브라우저에서 캐시할 수도 있습니다.
Rehydration을 사용한 서버 측 렌더링(SSRH)
위에서 설명한 것과 동일한 시나리오를 상상해 보세요. 하지만 이번에는 클라이언트에서 완벽하게 작동하는 React 애플리케이션이 필요합니다.
서버에서 첫 번째 렌더링 을 수행하고 JavaScript 파일과 함께 HTML 콘텐츠를 다시 보낼 것입니다. React는 서버에서 렌더링된 마크업을 재수화 하고 애플리케이션은 이 시점부터 CSR 애플리케이션처럼 작동합니다.
React는 이러한 작업을 수행하는 내장 메서드를 제공합니다.
첫 번째 요청은 서버에서 처리하고 후속 렌더링은 클라이언트에서 처리합니다. 따라서 이러한 앱을 범용 React 앱 (서버와 클라이언트 모두에서 렌더링됨)이라고 합니다. 라우팅을 처리하는 코드는 클라이언트와 서버에서 분할(또는 복제)될 수 있습니다.
ReactDOMServer 는 React를 지원하지 않기 때문에 코드 분할도 약간 까다롭습니다. 게으르므로 Loadable Components와 같은 것을 사용해야 할 수도 있습니다.
또한 ReactDOMServer 는 얕은 렌더링만 수행한다는 점에 유의해야 합니다. 즉, 구성 요소에 대한 렌더링 메서드가 호출되지만 componentDidMount 와 같은 수명 주기 메서드는 호출되지 않습니다. 따라서 대체 방법을 사용하여 구성 요소에 데이터를 제공하려면 코드를 리팩터링해야 합니다.
NextJS와 같은 프레임워크가 등장하는 곳입니다. SSRH에서 라우팅 및 코드 분할과 관련된 복잡성을 숨기고 보다 부드러운 개발자 경험을 제공합니다.
이 접근 방식은 페이지 성능과 관련하여 혼합된 결과를 산출합니다.
정적 콘텐츠(PRS)로 사전 렌더링
사용자가 요청하기 전에 웹페이지를 렌더링할 수 있다면 어떨까요? 이는 빌드 시 또는 데이터가 변경될 때 동적으로 수행될 수 있습니다.
그런 다음 결과 HTML 콘텐츠를 CDN에 캐시하고 사용자가 요청할 때 훨씬 빠르게 제공할 수 있습니다.
이를 사전 사용자 요청인 콘텐츠를 렌더링하기 전에 사전 렌더링이라고 합니다. 이 접근 방식은 블로그 및 전자 상거래 애플리케이션에 사용할 수 있습니다. 블로그의 콘텐츠는 일반적으로 사용자가 제공한 데이터에 의존하지 않기 때문입니다.
Rehydration(PRH)을 사용한 사전 렌더링
클라이언트가 렌더링할 때 미리 렌더링된 HTML이 완전히 작동하는 React 앱이 되기를 원할 수 있습니다.
첫 번째 요청이 제공된 후 애플리케이션은 표준 React 앱처럼 작동합니다. 이 모드는 라우팅 및 코드 분할 기능 측면에서 위에서 설명한 SSRH와 유사합니다.
성능 매트릭스
기다리던 순간이 드디어 왔습니다. 결전의 시간입니다. 이러한 각 렌더링 경로가 웹 성능 메트릭에 어떤 영향을 미치는지 살펴보고 승자를 결정하겠습니다.
이 매트릭스에서는 성능 메트릭에서 얼마나 잘 수행되는지에 따라 각 렌더링 경로에 점수를 할당합니다.
점수 범위는 1에서 5까지입니다.
- 1 = 불만족
- 2 = 나쁨
- 3 = 보통
- 4 = 좋음
- 5 = 우수
| TTFB 첫 번째 바이트까지의 시간 | LCP 가장 큰 만족스러운 페인트 | 티티 대화형 시간 | 번들 크기 | 총 | |
|---|---|---|---|---|---|
| CSR | 5 HTML은 CDN에 캐시될 수 있습니다. | 1 HTML 및 데이터를 가져오기 위해 서버로 여러 번 이동 | 2 데이터 가져오기 + JS 실행 지연 | 2 모든 JS 종속성은 렌더링 전에 로드해야 합니다. | 10 |
| CSRB | 4 HTML은 요청 데이터에 의존하지 않는 경우 캐시할 수 있습니다. | 삼 데이터가 애플리케이션과 함께 로드됨 | 삼 인터랙티브하기 전에 JS를 가져와서 구문 분석하고 실행해야 합니다. | 2 모든 JS 종속성은 렌더링 전에 로드해야 합니다. | 12 |
| SSRS | 삼 HTML은 각 요청에 대해 생성되며 캐시되지 않습니다. | 5 JS 페이로드 또는 비동기 작업 없음 | 5 페이지는 첫 번째 페인트 직후 대화형입니다. | 5 필수 정적 콘텐츠만 포함 | 18 |
| SSRH | 삼 HTML은 각 요청에 대해 생성되며 캐시되지 않습니다. | 4 서버가 첫 번째 패스를 렌더링했기 때문에 첫 번째 렌더링이 더 빠릅니다. | 2 JS는 첫 번째 HTML 구문 분석 + 페인트 후 DOM을 수화해야 하기 때문에 느림 | 1 렌더링된 HTML + JS 종속성을 다운로드해야 합니다. | 10 |
| PRS | 5 HTML은 CDN에 캐시됩니다. | 5 JS 페이로드 또는 비동기 작업 없음 | 5 페이지는 첫 번째 페인트 직후 대화형입니다. | 5 필수 정적 콘텐츠만 포함 | 20 |
| PRH | 5 HTML은 CDN에 캐시됩니다. | 4 서버가 첫 번째 패스를 렌더링했기 때문에 첫 번째 렌더링이 더 빠릅니다. | 2 JS는 첫 번째 HTML 구문 분석 + 페인트 후 DOM을 수화해야 하기 때문에 느림 | 1 렌더링된 HTML + JS 종속성을 다운로드해야 합니다. | 12 |
주요 내용
정적 콘텐츠(PRS)로의 사전 렌더링 은 최고 성능의 웹사이트로 이어지는 반면 수화(SSRH)가 포함된 서버 측 렌더링 또는 클라이언트 측 렌더링(CSR)은 압도적인 결과로 이어질 수 있습니다.
웹사이트의 다른 부분에 대해 여러 접근 방식 을 채택하는 것도 가능합니다. 예를 들어, 이러한 성능 메트릭은 공개 웹 페이지에 중요할 수 있으므로 사용자가 로그인하고 개인 계정 데이터를 본 후에는 덜 중요할 수 있지만 보다 효율적으로 색인을 생성할 수 있습니다.
각 렌더 경로는 데이터를 처리할 위치와 방법에 대한 절충안을 나타냅니다. 중요한 것은 엔지니어링 팀이 이러한 절충안을 명확하게 보고 논의하고 사용자의 행복을 극대화하는 아키텍처를 선택할 수 있다는 것입니다.
추가 읽기 및 고려 사항
현재 인기 있는 기술을 다루려고 했지만 이것이 완전한 분석은 아닙니다. Google 개발자가 스트리밍 서버 렌더링, 삼동형 렌더링 및 동적 렌더링(크롤러 및 사용자에게 서로 다른 응답 제공)과 같은 기타 고급 기술에 대해 논의하는 이 기사를 읽는 것이 좋습니다.
콘텐츠가 많은 웹 사이트를 구축하는 동안 고려해야 할 몇 가지 다른 요소에는 작성자를 위한 우수한 콘텐츠 관리 시스템(CMS)의 필요성, 소셜 미디어 미리보기를 쉽게 생성/수정하고 다양한 화면 크기에 맞게 이미지를 최적화하는 기능이 있습니다.
