만족

[React] 검색엔진 최적화(SEO):: Prerendering (react-snap) 본문

[React] 검색엔진 최적화(SEO):: Prerendering (react-snap)

FrontEnd/React Satisfaction 2020. 8. 6. 02:39

주의

 

이 라이브러리를 사용 중 알 수 없는 오류로 사용이 어려울 경우

아래 링크를 참조해서 새로운 라이브러리를 사용해 보세요.

 

react-snap은 유지보수가 중단된 프로젝트이므로 오류 수정 업데이트가 없습니다.

https://satisfactoryplace.tistory.com/348

 

[React] 검색엔진 최적화(SEO):: Prerendering (react-hydratable)

https://satisfactoryplace.tistory.com/131 [React] 검색엔진 최적화(SEO):: Prerendering (react-snap) React는 대표적인 SPA제작 라이브러리이다. SPA가 사용감이나 개발적인 측면에서는 유리하지만, 빌드된 결..

satisfactoryplace.tistory.com

 

개요

 

React는 대표적인 SPA제작 라이브러리이다.

 

SPA가 사용감이나 개발적인 측면에서는 유리하지만,

빌드된 결과물을 보면 <body></body>는 텅 비어있고

js가 body를 바꾸기 때문에 검색엔진은 이 사이트를 비어있는 사이트로 인식한다.

(물론 구글은 js로 렌더링하는 사이트도 크롤링할 수 있게끔 개선했으나, 네이버나 다음과 같은 곳에선 그렇지 않다)

 

 

create-react-app으로 만든 프로젝트의 빌드 결과물

 

 

따라서 검색엔진과는 아주 상극에 있는 개발방법이라고 할 수 있다.

 

이번 포스트에서는 js의 도움 없이도 사이트의 내용물을 보여줄 수 있게 하는 라이브러리를 소개한다.

 

https://github.com/stereobooster/react-snap

 

stereobooster/react-snap

👻 Zero-configuration framework-agnostic static prerendering for SPAs - stereobooster/react-snap

github.com

react-snap은 지정한 페이지의 렌더링이 끝나면 html만을 크롤링해 static 파일로 만들어주는 역할을 한다.

(렌더링이 끝난다기보단 실제로는 일정 시간이 지나면 크롤링한다. 다만 이해를 돕기 위해 렌더링이 끝난다고 하겠다)

 

 

 

 

해당 페이지에서 F12하고 element누르면 보이는 바로 그것이다.

 

설치 및 사용

yarn add react-snap --dev

react-snap을 devDependencies 에 추가한다.

 

{
	//... some data
    "scripts": {
    	//... some scripts
        "postbuild": "react-snap"
    },
    //... some data
}

빌드가 완료된 후 크롤링을 할 수 있도록, 

postbuild 스크립트에 react-snap을 추가한다.

 

import { hydrate, render } from "react-dom";

const rootElement = document.getElementById("root");
if (rootElement.hasChildNodes()) {
  hydrate(<App />, rootElement);
} else {
  render(<App />, rootElement);
}

이제 index.js에서 위처럼 코드를 변경한다.

 

hydrate는 이미 존재하는 돔 구조를 초기화하지 않고

React가 이어서 사용할 수 있도록 해 주는 함수이다.

 

이 과정은 생략해도 작동에는 문제가 없지만 로딩 시간이 조금 더 길어진다.

 

여기까지가 기본 설정은 끝이다.

매우 쉽다.

 

하지만 이대로 하면 첫 페이지만 크롤링한다.

 

크롤링 페이지 추가

 

package.json으로 가서 reactSnap을 추가한다

{
	//... some data
    "scripts": {
    	//... some scripts
        "postbuild": "react-snap"
    },
    "reactSnap": {
    	"include": []
    },
    //... some data
}

 

"include": []에는 크롤링할 대상 url들을 적는다

 

{
	//... some data
    "scripts": {
    	//... some scripts
        "postbuild": "react-snap"
    },
    "reactSnap": {
    	"include": [
            "/", "/home", "/search"
        ]
    },
    //... some data
}

 

가령 이런식으로 적으면 된다.

 

이후 yarn build를 실행하면 빌드를 완료한 후 react-snap이 실행되고 해당 작업이 끝나면 /build에서 다음과 같은 모습을 볼 수 있다

 

 

 

기존의 build에서는 index.html만이 결과물로 나왔는데

package.json의 "include": [] 에서 명시한 url들을 크롤링한 결과물들이 함께 나온다.

 

 

 

실제로 포스트맨으로 확인해 본 결과 위에서와 달리 body의 내용물이 존재한다.

 

+++++

 

prerendering은 server-side-rendering(SSR)과는 명백히 다르다.

 

react-snap을 이용한 prerendering은 단순히 빌드 시점에 렌더링된 화면을 마치 스크린샷을 찍듯이 크롤링한 것 뿐이고

(어떤 동작도 하지 않는다. 검색엔진이 바라보았을 때 '이 사이트에는 이런 컨텐츠가 있구나' 정도를 알려준다고 보면 된다)

 

SSR은 그 시점에 실제 유저에게 표시되는 정보를 서버에서 제공하는 것이다.

 

Vercel로 배포 시 react-snap 오류가 발생할 경우

  "reactSnap": {
    "include": [
        "/", "/home", "/search"
    ]
    "puppeteerArgs": [
      "--no-sandbox",
      "--disable-setuid-sandbox"
    ]
  },

package.json에서 reactSnap부분에 puppeteerArgs 속성과 값을 넣어 주어야 정상적으로 빌드가 완료될 수 있다.

 

+++++++++

 

다만 의미없는 태그들을 html에 추가하는 과정에서

당연히 클라이언트는 필요없는 내용을 로드해야 하기 때문에 로딩 속도에는 좋지 않다.

 

꼭 필요한 상황에서만 사용할 것.



Comments