검색 엔진 최적화(SEO) 개념적 이해

최범수·2022년 1월 23일
54
post-thumbnail

검색 엔진 최적화는 프로덕트에서 굉장히 큰 역할을 한다고 생각합니다.
마케팅을 통해 사용자들을 유입시킬 수도 있지만, SEO를 잘 해놓으면 값을 지불하지 않고도 사용자들을 유입시킬 수 있습니다. 공짜 마케팅 역할을 할 수 있으니, 우리의 타켓 사용자들의 키워드들을 잘 파악하여 해당 키워드를 검색했을 때 우리의 프로덕트가 노출될 수 있도록 하는 것이 좋습니다.

SEO를 하는 방법은 생각보다 단순한 것도 있고, 컨텐츠적인 측면도 있어서 개발자 혼자서 작업하기 어려운 부분도 있습니다.
이 글에서는 SEO의 테크니컬적인 측면에 집중하고, 최적화를 진행하기 전에 어떤 개념을 알고 있으면 좋을지를 소개합니다.
또한 검색엔진마다 최적화하는 방법이 다를 수 있는데, 구글을 기준으로 작성된 글임을 알려드립니다!

글에 있는 오류는 댓글로 알려주시면 너무나 감사하겠습니다!! 🙏🙏🙏



SEO란?

검색엔진의 검색결과에 자신의 웹 페이지가 더 많이 노출되도록 최적화된 컨텐츠를 만드는 것



구글봇의 기본 동작 순서

Google Bot Working Flow

1. 크롤링

  • 구글은 막대한 수의 컴퓨터로 웹 페이지들을 크롤링하며, 이를 서치엔진봇, 크롤러, 구글봇이라고 함
    • 이 문서에서 크롤러, 구글봇을 혼용해서 사용하는데, 구글에 한정하여 같은 대상을 가리킴

  • 크롤링 대상 URL
    • 구글에 제출된 sitemap.xml
    • 크롤러가 진입한 페이지의 링크로 등록된 URL
      <a href="https://www.example.com">이 링크에 크롤러가 접근합니다.</a>

  • 크롤링에는 최신 버전의 크롬이 사용됨
  • 크롤러는 HTML 문서를 파싱하고 자바스크립트가 있으면 렌더링 대기열에 페이지를 추가

크롤링에서 특정 페이지를 제외하는 방법

  • Robots.txt에 크롤링에서 제외하고자 하는 URL을 넣어놔도, 다른 페이지에 링크로 들어가 있으면 크롤링 대상이 됨
  1. 로그인 후 사용할 수 있는 페이지는 크롤링 불가
    - 구글봇이 로그인을 하지는 않으므로 크롤러가 접근할 수 없음

  2. noindex를 적용하여 크롤링 대상에서 제외
    • head 태그 내에 meta 태그로 noindex를 설정하면 크롤러가 크롤링을 하지 않고, 다시 방문하지 않게 됨
<!-- 모든 크롤러에 대해 크롤링을 차단 -->
<meta name="robots" content="noindex">

<!-- 구글봇에 대해 크롤링을 차단 -->
<meta name="googlebot" content="noindex">

  1. a 태그에 rel="nofollow", rel="sponsored" 를 적용하여 링크 제외
    • 크롤러는 페이지의 링크가 발견되면 그 페이지도 크롤링을 진행한다.
    • 댓글, 포스트 등에 입력된 스팸 URL이 우리 사이트에 의해 크롤링되면 우리 사이트 SEO에 악영향
<!-- 유저로부터 만들어진 스팸 링크 -->
<a rel="nofollow" href="https://smap.com">저희 사이트도 방문해주세요 ^^</a>

<!-- 우리 사이트에서 표시되고 있는 광고 -->
<a rel="sponsored" href="https://sponsored.com">최저가 9,900원!!</a>


2. 렌더링

  • 구글봇은 헤드리스 크로미움 기반으로 자바스크립트를 실행하고 렌더링을 진행
  • 렌더링을 하여 HTML 문서를 완성해야 정확한 페이지 정보를 파악할 수 있음

자바스크립트 페이지 제약 사항

  • 구글봇이 지원하는 수준의 자바스크립트 문법을 사용해야 함
  • 구글봇은 리소스 효율을 위해 장기간동안 캐싱을 하고, WRS(Web Rendering Service)는 캐싱 헤더를 무시할 수 있으므로 강제로 캐싱을 깨줘야 함
    • index-2s9djce23asdas.js 이렇게 파일/폴더명에 해시값, 날짜 등의 값을 넣어서 캐싱이 깨질 수 있도록 설계
  • 프레그먼트 대신 히스토리 API 사용
    • 구글봇이 페이지에서 링크를 찾을때 a href 만을 링크로 인식
    • 프레그먼트 방식으로 페이지 이동을 구현하면 크롤러가 링크를 인식하지 못함
    • History API를 사용하여 URL이 크롤러에게 인식될 수 있도록 함
<!-- href 속성값이 #이 들어간 해시태그 문자열 -->
<a href="#/list">상품 목록</a>

<!-- href 속성값이 정상적인 URL형식 -->
<a href="/list">상품 목록</a>

SSR이 CSR보다 SEO가 좋은 이유?

  • 모든 구글봇이 자바스크립트를 실행할 수 없음
  • 서버 사이드 렌더링이 더 빠르게 콘텐츠를 제공함

모두 구글봇의 리소스와 관련된 이야기! 아래 크롤러 관리 파트에서 자세히 소개



3. 인덱싱

페이지가 어떤 페이지인지 파악하고, 검색 결과로 노출될 수 있도록 페이지 정보를 저장하는 것

  • Meta 태그, Title, HTML 콘텐츠, 이미지, 비디오 등의 페이지 정보를 분석하여 페이지를 파악
  • 구글 데이터베이스에 페이지 정보를 저장

Document 개념

  • Document - 완전히 동일한 컨텐츠를 갖는 여러 개의 웹 페이지 모음

https://www.example.com/page/1
https://www.example.com?page=1
http://www.example.com?page=1

  • 위 주소 모두 동일한 HTML 콘텐츠를 갖는 페이지라고 가정하면, 1개의 문서에 3개의 페이지가 있다고 할 수 있음
  • 하나의 문서를 대표하는 페이지의 URL을 Canonical URL
  • Canonical URL이 아닌 페이지들의 URL을 Duplicates URL (Alternates URL)

다시 인덱싱으로

  • 인덱싱 과정에서 이 페이지가 중복이 되는지 검사
    • 중복되면 Document에 Duplicates URL이 추가되며, 동일한 페이지를 중복으로 크롤링했다고 판단 → 해당 사이트에 대한 크롤링 빈도가 감소할 수 있음
  • link 태그의 “rel=canonical” 속성을 설정
    • 크롤러에게 Canonical URL이 이미 존재하고 이 페이지는 크롤링할 필요가 없음을 명시
    • 중복 크롤링을 방지할 수 있음
	<!-- https://www.example.com?page=1 -->
	<link rel="canonical" href="https://example.com/page/1" />

	<!-- http://www.example.com?page=1 -->
	<link rel="canonical" href="https://example.com/page/1" />
  • noindex 태그 사용
    • 중복되는 페이지에 noindex를 선언하여 크롤링하지 않겠다고 명시하고, 중복 크롤링을 방지


4. 검색결과 게재



Sitemap

사이트에 있는 페이지, 동영상, 파일 등의 정보를 제공하는 파일

sitemap.xml example

  • 검색 엔진에 제출하여 더 효율적으로 크롤링될 수 있도록 하는 역할
  • Sitemap은 어떤 페이지가 중요한지 알려주는 일종의 제안으로, Sitemap에 등록된 URL이 모두 인덱싱될 것이라는 보장은 없음

Sitemap에 포함할 내용

  • 내 사이트에서 검색 결과로 노출시키고 싶은 페이지의 URL
  • 동영상의 영상 길이, 카테고리, 연령 등급
  • 이미지의 유형, 라이센스
  • 뉴스의 제목, 게시 날짜 등

Sitemap 제약조건

  • 용량 50MB 이하, URL 5만개 이하 → 초과시 분할
  • Sitemap은 Sitemap의 상위 디렉토리의 하위 디렉토리에만 영향을 줌
    • 따라서 대부분의 Sitemap은 루트 디렉토리에 위치
    www.example.com/sitemap.xml
    -> www.example.com 하위 모든 URL에 대해 적용

    www.example.com/some/path/sitemap.xml
    -> www.example.com/some/path 하위에만 적용되며, www.example.com에는 미적용

Django Sitemap Generator

  • Sitemap에 URL을 하나씩 입력하기에는 너무 많기 때문에 동적으로 Sitemap을 만들어주는 라이브러리들이 존재
  • Django에서는 django.contrib.sitemaps를 사용하면 쉽게 만들 수 있음
    • 모든 Post, Interview 객체의 get_absolute_url 을 Sitemap에 등록해줌
    • urlpatterns에 만들어진 sitemaps 딕셔너리를 넣어줌
    from django.contrib.sitemaps import GenericSitemap
    from django.contrib.sitemaps.views import sitemap
    
    sitemaps = {
        "post": GenericSitemap({"queryset": Post.objects.all() }, priority=1),
        "interview": GenericSitemap({"queryset": Interview.objects.all() }, priority=1),
    }
    
    urlpatterns = [
        path("sitemap.xml/", sitemap, {"sitemaps": sitemaps}, name="sitemap"),
    ]


Robots.txt

크롤러가 사이트에 접근할 수 있는 URL, 접근 거부한 URL을 알려주는 파일

  • 검색엔진마다 Robots.txt를 대하는 구현이 다르므로, 검색엔진마다 다르게 적용될 수 있음

Robots.txt 형식

  • User-agent : 어떤 검색엔진에 대한 규칙인지 선언
  • Disallow : 해당 URL은 크롤링을 거부하겠다는 선언
  • Allow : 해당 URL은 크롤링을 허용하겠다는 선언 (기본적으로 모든 URL은 허용 상태)
  • Sitemap : Sitemap의 위치
User-agent: BaiDuSpider
Disallow: /

User-agent: BadBot
Disallow: /

User-agent: *
Disallow: /api
Allow: /

Sitemap: http://www.example.com/sitemap.xml
  • BaiDuSpider, BadBot 검색엔진 크롤러에 대해서는 모든 페이지를 허용하지 않음
  • 위 두 크롤러를 제외한 모든 크롤러에 대해 /api 로 시작하는 URL은 크롤링은 거부하고, 나머지 모든 주소에 대한 크롤링은 허용함

Robots.txt 에 접근 거부를 했음에도 계속 인덱싱이 되는 이유

  • Robots.txt에서 Disallow 했음에도 불구하고, 크롤러가 제외한 URL에 접근하는 경우가 있음
    → 크롤러가 방문하지 않을 것이라 생각하고 개발된 페이지면 크롤러 접근시 에러가 발생할 수 있는데, 에러가 발생하면 사이트에 대한 크롤링 빈도가 낮아질 수 있음
  • Robots.txt는 페이지를 숨기기 위한 목적이 아니고, 사이트에 부하가 덜 생기게 하기 위한 목적
    → 크롤러가 과도한 접근으로 인해 서버에 과부하가 걸리지 않도록, Robots.txt에 페이지 접근을 허용하지 않겠다 선언하면 크롤러 접근이 줄어듬
  • 크롤러는 Robots.txt에 접근 거부가 되어있으면 그 페이지는 방문하지 않지만, 다른 페이지에 링크로 존재하는 경우에는 크롤링을 진행
  • noindex, nofollow 설정을 하여 페이지에서 인덱싱 거절


크롤링 자원 관리

크롤링 예산 (Crawl Budget)

보통 사이트의 경우, 크롤링 예산을 신경써야하는 일은 극히 드물다고 함
구글 기준 "100만개의 페이지가 일주일에 한번 변경되는 수준" or "1만개 페이지가 하루에 한번 변경되는 수준"이 아니면 예산에 영향이 없음

→ 유저로부터 받은 콘텐츠를 SEO 페이지로 등록되어, 기하급수적으로 페이지가 생기는 프로덕트라면 신경써야할 가능성이 있다. (Dynamic SEO)

  • 크롤러의 개수는 한정적인데에 반해, 웹 페이지의 수는 계속해서 늘어남
  • 이미 인덱싱된 페이지라 할 지라도 최신 내용을 유지하기 위해 다시 크롤링이 필요하기도 함
  • 구글은 효율적으로 크롤러를 운용하기 위해서, 하나의 사이트에 크롤링할 시간과 크롤러의 수를 제한하고 이를 Crawl Budget (크롤링 예산) 이라고 함
  • 크롤링 예산은 “크롤러가 얼만큼 서버에 부하를 주는가”“얼만큼 크롤링이 필요한 사이트인가”에 의해 결정

크롤링 용량 한도 (Crawl Capacity Limit)

크롤러가 얼만큼 서버에 부하를 주는가? (== 크롤러가 얼만큼 크롤링을 해도 되는가?)

  • 구글은 크롤링이 서버 부하에 심각한 영향을 주지 않을 수 있도록 크롤링 빈도를 조절함

  • 아래 요소에 의해 크롤링을 얼마나 진행할지 결정됨

  1. 크롤링 상태
    • 크롤러가 페이지에 접근하면 당연하게도 서버에 요청이 보내짐
    • 요청에 대한 응답 Status가 OK가 아니라면 크롤링 빈도를 낮춤
    • 응답속도가 빠를수록 크롤링을 많이 시도하고, 느릴수록 크롤링 적게 시도함
  2. 구글의 크롤링 한도
    • 구글봇의 수가 한정되어 있기 때문에 우리 사이트에 많은 구글봇을 배정해주지 못 할수도 있음
  3. 사이트 소유자의 크롤링 한도 설정
    • 크롤러의 진입이 서버 부하로 이어지면, 사이트 소유자는 구글 서치 콘솔에서 크롤링 제한을 직접 걸 수 있음
  • 결론적으로 아래 상황을 유지해야 우리 사이트가 크롤링을 더 많이 받을 수 있다.
    • 서버의 응답속도를 빠르게 유지하고, 400대, 500대 응답코드가 나오는 페이지를 크롤링 대상에서 제외한다.
    • 서버 부하에 영향이 크지 않다면 크롤링 한도를 제한하지 않는다.

크롤링 수요 (Crawl Demand)

얼만큼 크롤링이 필요한 사이트인가?

  • 구글은 사이트의 품질, 업데이트 빈도, 관련성 등을 고려하여 사이트에 크롤링 시간은 분배 (한 사이트에 계속 시간을 쓸 수 없으므로)

  • 주어진 시간에 효율적으로 크롤링되도록 해야함

  • 아래 요소에 의해 얼마나 크롤링이 필요한지 결정됨

  1. 인식된 크롤링 대상 URL
    • 사용자는 크롤러에게 Sitemap과 Robots.txt, noindex 설정 등으로 크롤링 대상 페이지의 정보를 알려줄 수 있음
    • 사용자가 크롤링하지 않겠다고 명시하지 않으면, 크롤러는 기본적으로 사이트의 모든 URL을 크롤링
    • 크롤링하고 싶지 않은 페이지가 크롤링되면, 그만큼 다른 페이지가 크롤링될 수 없음
    • 크롤링 제외 방법
      1. Canonical 설정으로 중복 크롤링 방지
      2. 크롤링하고 싶지 않은 페이지에 noindex 설정
      3. 크롤링하고 싶지 않은 페이지 robots.txt 에서 Disallow 시키기
  2. 인기도
    • 페이지의 인기가 높을수록 구글은 해당 페이지의 콘텐츠를 최신화하기 위해 자주 크롤링을 시도

Crawl Budget 결론

  • 크롤링이 서버 부하에 영향을 주지 않을수록 좋다.
  • 크롤러가 더 많은 페이지를 크롤링할 수 있도록, 중복 페이지를 차단시켜주는 것이 좋다.
  • 인기가 많고 콘텐츠가 좋을수록, 최신 정보를 유지하기 위한 크롤링이 더 자주 진행된다.


한정된 Crawl Budget에 의해 생기는 일

1. 중복된 페이지 크롤링시 해당 사이트 크롤링 빈도 감소

  • 중복으로 크롤링하면 크롤러의 시간을 낭비한 것으로 간주
  • 해당 사이트에 대한 크롤링 빈도가 감소하게 됨

2. CSR(Client Side Rendering)보다 SSR(Server Side Rendering)이 SEO에서 더 유리

  • CSR의 경우 콘텐츠가 완성될 때까지의 시간이 오래걸림
    • 첫 시점에 콘텐츠가 없음
    • 자바스크립트를 실행하며, 렌더링이 진행되어야 함
  • 반면 SSR은 이미 완성된 HTML 컨텐츠를 크롤러에게 바로 줄 수 있으므로, 더 많이 크롤링되고 속도가 빠른 것으로 인식됨
  • 크롤러는 시간이 한정되어 있으므로, 더 효율적인 크롤링을 할 수 있으므로 SSR이 더 유리할 수 밖에 없음

3. Dynamic Rendering 개념 등장

Dynamic Rendering

  • 웹 서버에서 크롤러를 식별하여
    • 크롤러에게는 완성된 Static HTML 문서를 반환
    • 일반 클라이언트에게는 원래대로 클라이언트 사이드 렌더링을 진행
  • 크롤러는 자바스크립트를 실행할 필요없이 콘텐츠를 받을 수 있으므로, 더 효율적으로 크롤링이 진행됨
  • 크롤러에게 제공하는 HTML 문서와 클라이언트에서 렌더링된 HTML 문서가 유사하면 클로킹으로 취급되지 않음

클로킹이란, 크롤러에게 보여주는 페이지와 일반 클라이언트에게 보여주는 페이지를 다르게 하는 SEO 어뷰징의 일종

  • 다이나믹 렌더링을 사용할 때에는 클로킹으로 오해받지 않도록 Static HTML 문서와 클라이언트 사이드에서 렌더링된 문서가 유사하도록 신경써야함


마무리

SEO(Search Engine Optimization)에 대한 개념적 이해를 도움이 될 수 있는 내용을 쓰려고 노력

  • 검색 엔진, 특히 구글이 어떤 방식으로 동작하는지
  • Sitemap, Robots.txt가 의미하는바가 무엇인지
  • 크롤러는 효율적으로 움직이고자 하는데, 여기서 우리는 어떤 시도를 할 수 있는지

그래서 최적화는 어떻게 하는건데?

SEO 스코어를 측정해주는 사이트를 사용하면 좋다.

SEO Checker | Test your website for free with Seobility

  • 특정 페이지의 URL을 입력하면 SEO가 얼만큼 잘 되어 있는지, 보완해야할 점은 무엇이 있는지 추천해줌
  • 실질적인 개선사항을 알려주는데, 이 개선작업을 왜 하는지 이해하고 보면 작업이 더 즐거워질 수 있다!


References

Advanced SEO Techniques and Strategies | Google Search Central | Google Developers

profile
프론트엔드 개발자

4개의 댓글

comment-user-thumbnail
2022년 1월 25일

우왕 , 마침 찾고 있던 내용인데 이렇게 잘 설명해주시다 .

감사합니다.

1개의 답글
comment-user-thumbnail
2022년 2월 2일

측정 스코어를 보여주는 사이트가 있군요.(아무래도 구글의 영업비밀인듯할텐데)
그래도, 더 좋은 방향으로 만들 수 있겠네요. 감사합니다.

1개의 답글