공부
[React] 검색엔진 최적화(SEO)
hahihuree
2021. 9. 30. 17:38
React는 SPA로 HTML이 하나이며, CSR(클라이언트 사이드 렌더링)을 하기 때문에 렌더링(자바스크립트 실행)이 되기 전까지는 껍데기 HTML만 나오므로 검색 엔진 최적화가 어려움.
meta tag
- HTML의 head부분에 있는 <meta>를 활용.
- React는 정적 페이지가 index.html 하나이므로 페이지별로 메타태그를 적용하려면 라이브러리 사용.
- 라이브러리 react-helmet 설치. (yarn add react-helmet)
- 적용하고 싶은 페이지로 가서 Helmet import하고, <Helmet>안에 child로 넘겨주고 싶은 메타태그 작성.
-
// 예시 const One = () => { return ( <> <Helmet> <title>page one</title> <meta property="og:title" content="og page one"/> <meta property="og:description" content="hello"/> <meta property="og:image" content="이미지링크"/> </Helmet> </> ) }
pre-rendering
- 빌드 시 미리 특정 페이지를 렌더링 해서 html파일을 만들어 두는 것.
- 프로젝트에 바로 붙이지 말고 새 프로젝트를 만들어 사용할 것. (yarn create react-app 새프로젝트이름)
- react-snap과 react-router-dom 설치. (yarn add react-router-dom, yarn add --dev react-snap)
- 페이지 만들고 라우트 적용 후 yarn start해서 작 적용되었나 확인.
- package.json 가서 scripts아래에 "postbuild": "react-snap" 및 어떤 경로를 추가할지 작성.
-
// 예 "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "postbuild": "react-snap" }, ... "reactSnap": { "include": [ "/two", "/" ] }, ...
- index.js 가서 기존 코드 주석처리 하고 아래 코드 삽입.
-
// 예 import React from 'react'; import ReactDOM, { hydrate } from "react-dom"; ... const root = document.getElementById("root"); if (root.hasChildNodes()) { hydrate( <App />, root ); } else { ReactDOM.render( <App />, root ); ... }
- 결과물 확인
- yarn build
- 빌드한 프로젝트 로컬에서 실행
- package.json과 같은 위치에 serve.json파일 만들고 아래 코드 삽입. (소스는 프젝에 따라 변경)
-
{ "rewrites": [ // "/"경로로 들어오면 "/200.html"을 보여줌(경로 잡아준 것) { "source": "/", "destination": "/200.html" }, { "source": "/two", "destination": "/two/index.html" } ] }
- yarn global add serve
- serve -c serve.json build (serve.json 설정을 가지고 빌드에 있는 내용물을 실행함)
- build하고 postman으로 html내용 들어가는지 확인
* react-dom의 hydrate
- pre-rendering을 하는 것은 컴포넌트 트리를 그대로 가져가는게 아니고, html DOM을 index.js에 넣는 것.
- 이는 React의 컴포넌트가 아닌 DOM객체 일 뿐이라 React스럽게 쓸 수가 없음.
- 이에 따라 hydrate는 React의 컴포넌트로 쓸 수 없는 곳에 이벤트를 주입해 줌.
- hasChildNodes 라는 것은 자식 노드들이 있다는 것이고, 이는 미리 내용물이 들어가 있다는 뜻.
* 프로젝트에 바로 붙이지 말라는 이유
- react-snap은 firestore에서 요청하고 받아오는 정보를 읽을 줄 모름.
- firestore에서는 프리렌더링을 못하나?
- REST API방식으로 주고 받을 수 있지만, 데이터 구조를 다시 짜야 함.
- 즉, firestore를 사용하고 프리렌더링을 하려면 데이터 구조 먼저 잡고 시작해야 함.
SSR
- Next.js 라이브러리 사용.
- react-router와 loadable-component로 code-splitting 하기.
참고 https://github.com/stereobooster/react-snap
참고 https://mygumi.tistory.com/385