[React] SEO (Search Engine Optimization) - 검색 엔진 최적화

SEO (Search Engine Optimization) - 검색 엔진 최적화


Google
Naver
Bing 등..

보통 포털은 각 웹사이트의 정보를 가져와서 쌓아놓는데
웹사이트에서 정보를 가져오는 방식은 각 포털마다 조금씩 상이합니다.
또한 상위에 어떤 웹사이트를 노출시킬지 결정하는 알고리즘도 포털마다 다릅니다.

구글의 경우 검색 키워드에 맞는 링크중 다른 사이트로부터 링크를 많이 가져와지는 링크를 상위에 노출시킨다고 합니다.
구체적인 알고리즘은 추측만 할 수 있으나 이러한 방향성을 다양한 포털이 갖고 있습니다.


프론트엔드 개발자가 SEO 를 어떻게 할 것인가?

SEO 도 전문으로 하는 분들이 계시고, 대부분은 디지털마케팅하시는 분들이 하시게 되어 크게 프론트엔드 개발자가 해야할 것은 없지만
다만 포털이 웹사이트에서 정보를 가져오는 방식에 해당하는 부분은 프론트엔드 개발자가 신경써줘야 합니다.

(구글) https://support.google.com/webmasters/answer/79812?hl=ko (네이버) https://webmastertool.naver.com/guide/basic_optimize.naver

이 두 사이트에서 알려주는 최적화 가이드에 최대한 맞춰서 작업해주도록 합니다.

  1. meta tag 설정
<meta name="robots">
  1. robots.txt 설정
[robots.txt]

<!--네이버 검색로봇만 접근 가능하게 설정--!>

User-agent: Yeti
Allow: /

<!--모든 검색엔진의 로봇에 대하여 접근 가능하게 설정--!>

User-agent: *
Allow: /


Server-Side Rendering

크롤러들이 자바스크립트를 해석하지 못할 경우 자바스크립트를 실행시킨 뒤에 렌더링 된 결과를 긁어갈 수는 없습니다.
그래서 대게 리액트(자바스크립트)로 만들어진 사이트가 SEO 가 잘 안된다고 합니다.
JS 해석 못하는 크롤러가 정보를 수집하게 도와주기 위한 장치가 바로 Server-Side Rendering 입니다.

[기존 HTML,CSS,JavaScript]
검색엔진 -> 요청 -> 우리 웹사이트 -> 응답 -> 검색엔진

[Server-Side Rendering]
검색엔진 -> 요청 -> 우리 웹사이트 (Html 생성) -> 서버 (JS 해석) -> 우리 웹사이트 -> 응답 -> 검색엔진

기존 방식과 Server-Side Rendering 과 비슷해보이지만
큰 차이점은 요청을 받는 우리 웹사이트와 서버에서 JavaScript 를 해석해서 결과를 응답으로 준다는 것입니다.

이쯤되면 ‘크게 안 달라보이면 브라우저에서 렌더링할 필요없이 서버에서 하면 되지않을까?’ 라는 생각을 할 수 있습니다.
하지만 API 를 사용한다거나 많은 것들을 추가적으로 사용하게 된다면 엄척나게 복잡해지고 신경써야할 측면이 많아 어렵습니다.
그래서 나온 것이 미리 Server-Side Rendering 을 해놓은 코드를 사용하는 것입니다.
(React 의 경우 : Next.js, Vue 의 경우 : Nuxt.js)


Next.js 실습 - 환경 설치

  1. 프로젝트 파일 생성
$ mkdir hello-next
  1. 프로젝트 파일에 개발환경 설치
[npm init이 안되어 있다면 해주세요 - package.json이 필요합니다.]

hello-next> $ npm install --save next react react-dom
  1. package.json 에 스크립트 추가
{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}
  1. ./pages/indx.js 를 생성후 스크립트 입력하기
export default () => <div>Welcome to next.js!</div>;


Next.js - CSS 처리

Server-Side Rendering 에서도 CSS 가 필요합니다.

export default () => (
  <div>
    Hello world
    <p>scoped!</p>
    <style jsx>{`
      p {
        color: blue;
      }
      div {
        background: red;
      }
      @media (max-width: 600px) {
        div {
          background: blue;
        }
      }
    `}</style>
    <style global jsx>{`
      body {
        background: black;
      }
    `}</style>
  </div>
);


Next.js - Head 태그

// Head 태그를 쓰기 위해 next/head에서 Head 컴포넌트를 import해야하는 것이 특징
import Head from "next/head";

export default () => (
  <div>
    <Head>
      <title>My page title</title>
      <meta name="viewport" content="initial-scale=1.0, width=device-width" />
    </Head>
    <p>Hello world!</p>
  </div>
);


Next.js 의 특이점

  1. Next.js 는 자체 라이프 사이클 메소드를 가지고 있기에 그 안에서 데이터 로딩작업을 해줘야 합니다.
// 서버에서도 요청을 보낼 수 있고, HTML을 만들 수도 있다는 점을 기억하도록 합니다.
import React from "react";
import axios from "axios";

export default class Posts extends React.Component {
  static async getInitialProps() {
    // 기존 react에서는 componentDidMount와 같은 라이프사이클 메소드를 사용했는데
    // Next.js에서는 getInitialProps란 자체 라이프 사이클 메소드를 사용합니다.
    const res = await axios.get("http://fds-json-server.glitch.me/posts");
    return {
      posts: res.data
    };
  }
  render() {
    return <ul>{this.props.posts.map(p => <li>{p.title}</li>)}</ul>;
  }
}
  1. Next.js 는 react-router 를 사용하지 못하기에 자체적인 router 를 사용합니다.
// CSS, 라이프사이클 메소드에 이어서 Router까지 자체적으로 지원하는 기능이 많습니다.
// 기본적인 Route 사용하기

import Router from "next/router";

export default () => (
  <div>
    Click <span onClick={() => Router.push("/about")}>here</span> to read more
  </div>
);


// react-router의 Link 기능 사용하기

import Head from "next/head";
import Link from "next/link";

export default () => (
  <div>
    <Head>
      <title>My page title</title>
      <meta name="viewport" content="initial-scale=1.0, width=device-width" />
    </Head>
    Hello world
    <p>scoped!</p>
    <ul>
      <li>
        <Link href="/about">
          <a>About</a>
        </Link>
      </li>
      <li>
        <Link href="/posts">
          <a>Posts</a>
        </Link>
      </li>
    </ul>
    <style jsx>{`
      p {
        color: blue;
      }
      div {
        background: powderblue;
      }
      @media (max-width: 600px) {
        div {
          background: blue;
        }
      }
    `}</style>
    <style global jsx>{`
      body {
        background: black;
      }
    `}</style>
  </div>
);

경우에 따라 (예를 들어 맞춤식 라우터를 사용하는 경우) 라우터가 작동하기 전에 popstate 를 듣고 반응 할 수 있습니다.
예를 들어,이를 사용하여 요청을 조작하거나 SSR 을 강제로 새로 고칠 수 있습니다.

import Router from "next/router";

Router.beforePopState(({ url, as, options }) => {
  // I only want to allow these two routes!
  if (as !== "/" || as !== "/other") {
    // Have SSR render bad routes as a 404.
    window.location.href = as;
    return false;
  }

  return true;
});


Server-Side Rendering 은 항상, 모든 부분에 필요한가요?

검색엔진에 걸릴 필요가 없는 웹 사이트 (개인화된 웹 사이트)의 경우에는 SSR(Server-Side Rendering)를 적용할 필요가 없습니다.
하지만 쇼핑몰, 게시판등 많은 사람들의 유입이 필요한 경우에는 SEO 를 해야하기에 거의 필수적으로 SSR 을 적용시켜줘야 합니다.

SSR 을 하면 구동속도가 빨라진다고 SSR 을 무작정 적용하기보다는 필요에 따라 적용시키는 자세가 필요할 것 같습니다.

만약에 개인화된 업무관리 서비스를 제공하는 웹 어플리케이션인데
소개페이지같은 경우에는 많은 사람들에게 노출되어야 하고,
서비스를 제공하는 페이지는 노출되어서 안될 경우에는
각각 별도의 도메인을 제공하여 소개페이지는 SSR 을 하여 SEO 를 하고
서비스를 제공하는 페이지는 SSR 을 하지 않도록 합니다.


Prerendering