티스토리 뷰

vue 를 이용하여 single page web app을 개발하고 server side rendering 을 사용하지 않은 경우,

검색엔진의 봇은 javascript로 구성된 사이트를 일종의 'fake website' 로 가정하여 스크롤링에서 제외할 수 있습니다.

(구글 같은 경우 개선되었거나 예정인듯 합니다.)


이럴때 사용가능한 방법은 아래와 같습니다.


1. SSR (server side rendering)

SSR은 클라이언트가 자바스크립트 코드를 실행하지 않을때 서버에서 페이지를 생성해 클라이언트에게 보내는 것입니다. SSR을 사용하는 것이 좋은 경우는 다음과 같습니다.

- 사용자마다 다른 컨텐츠를 보여주어야 할때

- 클라이언트와 실시간으로 상호작용을 해야할때 ( 채팅 서버 등 )

- 페이지가 너무 많아 빌드에 시간이 많이 걸리는 경우 (다음에서 설명할 prerendering을 사용하면 빌드 타임이 더 늘어납니다.)


저 같은 경우 AWS S3 - cloudfront 조합으로 (정적 페이지 호스팅) 페이지를 제공하여 SSR은 제외하였습니다.


2. Prerendering

프리렌더링은 웹사이트를 빌드할때 지정한 특정 페이지를 미리 렌더링해서 저장하는 기술입니다. 구현이 쉽고 빌드 타임에 모든 처리가 끝나므로 런타임에 추가로 부담이 들지 않습니다만, 빌드 타임은 당연스럽게 늘어나게 됩니다.


프리렌더링 적용방법은 아래 링크로 대신하겠습니다.

Vue (Single Page App)의 검색엔진 노출 방법- Prerendering


3. Vue-meta & sitemap 조합

Prerendering은 쉽긴 하지만 페이지가 추가될 때마다 빌드해야 하는 문제가 있습니다. 

제 경우 게시판의 글을 노출시킬려고 하는데 글은 DB에 저장되어 있어 Prerendering보다는 vue-meta와 sitemap 조합을 선택하였습니다.


우선 vue-meta로 봇이 가져갈 page title 및 description 을 글마다 변경되도록 적용하고 sitemap을 직접 작성후 upload하여 봇에게 저희 사이트에서 크롤링해야할 대상을 알려주었습니다.


- vue-meta의 적용은 아래와 같습니다. (https://alligator.io/vuejs/vue-seo-tips/)


npm i --save vue-meta

import Vue from 'vue'

...

import Meta from 'vue-meta'


Vue.use(Meta)

<template>
</template>
<script>
export default {

  metaInfo: {

    title: this.board.title,

    titleTemplate: '%s | www.ex.com', // title 뒤에 붙일 공통된 이름 (주로 사이트이름) 

    htmlAttrs: {

      lang: window.getApp.$i18n.locale // i18n 사용하지 않는 경우 직접 입력

    },

    meta: [

      { charset: 'utf-8'},

      // SEO setting

      { name: 'description', content: String(this.board.contents).slice(0, 320), vmid: 'description'},

      { name: 'keywords', content: this.board.keywords},

      { name: 'author', content: this.board.author},

      // SNS 용

      {

        property: 'og:title',

        content: this.board.title,

        template: chunk => `${chunk} | www.ex.com`,

        vmid: 'og:title'

      },

      // mobile

      { name: 'viewport', content: 'width=device-width, initial-scale=1'}

    ]

  }

}
</script>


위와 같이 작성하면 client에서 렌더링되는 페이지도 head 부분에 meta 정보가 추가됩니다.


- sitemap은 다음의 구조로 xml 로 작성후 구글 serch-console 에 업로드 합니다.  (파일을 직접 업로드 하는게 아니라 sitemap.xml을 먼저 홈페이지에 업로드 한 다음 홈페이지 주소를 업로드 합니다. https://www.xxxx.com/sitemap.xml )


* sitemap.xml 예시 (sitemap을 작성하는 xml 구조에 대해서는 https://www.sitemaps.org/ko/protocol.html 에서 자세히 설명되어 있습니다.)


<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://www.xxx.com/</loc> <lastmod>2019-12-18T01:21:12+00:00</lastmod> <changefreq>always</changefreq> </url>

<url> <loc>https://www.xxx.com/board/1</loc> <lastmod>2019-12-18T01:21:12+00:00</lastmod> <changefreq>always</changefreq> </url>

</urlset>


sitemap을 작성하였으면 홈페이지에 업로드 후 (저의 경우는 S3) 구글 서치콘솔에 주소를 등록 합니다. (서치콘솔 접속 후 sitemaps > 새 사이트맵 추가 ) 업로드 후에는 아래와 같이 sitemap에 대한 상태가 표시되며 상태가 '성공' 이면 정상적으로 처리된 것입니다.



이후 하루나 이틀 정도 지난 후 site:xxx.com 으로 구글에 검색해 보시면 구글에서 페이지를 잘 가져갔는지 확인 할 수 있습니다.


** 주의 ** 

보통 vue-router는 해시모드로 되어있습니다만 검색엔진 봇이 크롤링하기 위해서는 history 모드로 변경하셔야 합니다.

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

감사합니다.

댓글