본문 바로가기
python/Django

Django sitemap 분할 관리하기

by Redking

Django 웹 프로젝트를 운영하게 되면 검색엔진 최적화(SEO, Search Engine Optimization)를 위해서 sitemap.xml 파일을 만들어 robot.txt에 올려야 하는 일이 발생하게 됩니다. 

 

구글 검색 센터에서는 sitemap의 규칙으로 아래와 같이 설명하고 있습니다.

 형식과 관계없이 사이트맵은 1개당 50MB(압축하지 않은 파일 기준)와 URL 50,000개로 제한됩니다. 파일이 더 크거나 URL이 더 많은 경우, 목록을 여러 개의 사이트맵으로 나눠야 합니다. 

색인 파일(사이트맵 목록과 연결된 파일)을 만들어 Google에 색인 파일 하나만 제출하는 방법도 있습니다(선택사항). 즉, Google에 여러 개의 사이트맵을 제출하거나 사이트맵 색인 파일을 제출하면 됩니다.

일반 적인 경우 1개의 sitemap.xml을 만들어 관리하는 것으로 충분하지만 예를 들어 상품의 개수 만큼 sitemap이 생기는 쇼핑몰을 운영한다 했을때 초기에는 문제가 없지만 sitemap에 노출시켜야 할 페이지가 5만건이 넘고 및 용량이 50mb가 초과하는 순간 문제가 발생합니다. 그래서 이번 글에서는 sitemap을 분할하여 관리하는 방법을 설명합니다.

 

우선 가장 기초부터 들어가게 된다면 robots.txt를 생성하여 view를 만들고 sitemap의 경로를 알려줘야 합니다. 크롤링 봇은 일반적으로 사이트에 접속하고 난 후에 robots.txt를 먼저 찾게됩니다. nginx를 사용하고 있다면 nginx단에 바로 적용이 가능하니 참고해 주세요.

# urls.py
re_path(r'^robots\.txt$', views.robots, name='robots'),

# robots.txt
User-agent: *
Disallow: /

Sitemap: localhost:8000/sitemap.xml

# views.py
def robots(request):
    return render(request, 'pages/robots.txt', content_type='application/txt')

위와 같이 robots.txt에 대한 기본적인 세팅이 되었다면 이제는 sitemap을 생성하여 /sitemap.xml 경로에 추가할 차례입니다. 근데 이번 글에서는 여러개의 sitemap을 관리하는 방법을 소개하는 글이니 바로 여러개의 sitemap을 올리는 것까지 보여드리겠습니다.

# urls.py
re_path(r'^sitemap\.xml$', views.sitemap_xml, name='sitemap_xml'),
re_path(r'^sitemap-main\.xml$', views.sitemap_service_xml, name='sitemap_main_xml'),
re_path(r'^sitemap-items-(?P<page>\d+)\.xml$', views.sitemap_items_xml, name='sitemap_items_xml'),

# views.py
def sitemap_xml(request):
    items_count = Item.objects.count()
    items_range = range(math.ceil(items_count / 25000))
    context = {
        'items_range': items_range
    }
    return render(request, 'pages/etc/xml/sitemap.xml', context, content_type='application/xml')


def sitemap_main_xml(request):
    url_list = ['/', '/users']
    context = {
        'items_range': items_range
    }
    return render(request, 'pages/etc/xml/sitemap-public.xml', context, content_type='application/xml')


def sitemap_items_xml(request, page):
    url_list = []
    items_slice = int(page)
    slice_to = items_slice * 25000
    slice_from = items_slice - 25000
    items = Item.objects.order_by('-id')[slice_from:slice_to]
    for item in items:
        url_list.append('/item/{}/'.format(item))

    context = {
        'url_list': url_list,
    }
    return render(request, 'pages/etc/xml/sitemap-public.xml', context, content_type='application/xml')
    
# sitemap.xml
{% spaceless %}
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc>localhost:8000/sitemap-main.xml</loc>
    </sitemap>
    {% for items in items_range %}
        <sitemap>
            <loc>localhost:8000/sitemap-items-{{ items|add:1 }}.xml</loc>
        </sitemap>
    {% endfor %}
</sitemapindex>
{% endspaceless %}

# sitemap-public.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    {% for url in url_list %}
        <url>
            <loc>localhost:8000{{ url }}</loc>
        </url>
    {% endfor %}
</urlset>

내용을 쭉 훑어보면 sitemap.xml에 대한 url과 view를 설정해 주고 html파일을 생성하여 sitemap을 관리합니다. 여기서 주의깊게 볼 점은 sitemap_items_xml 뷰인데요 보시면 25000개 단위로 슬라이스 하여 노출하고 있습니다 25000개로 슬라이스 한 이유는 구글의 권장 사항이기 때문이고 이 로직을 참조하여 sitemap_xml 뷰에서도 items의 개수를 count한 뒤에 이를 25000으로 나누어 올림해주고 있습니다. 올림을 한 이유는 나머지가 있을 경우 나머지를 보여줄 페이지를 구현하기 위해서 입니다.

 

sitemap.xml은 이제 여러개의 sitemap을 관리하는 색인 파일이 되었고 이제 robot은 이를 읽어 seo가 유리하게 작동하도록 돕게 됩니다.

'python > Django' 카테고리의 다른 글

Django JSONField (Postgresql)  (0) 2022.12.06
Django bulk_create/bulk_update  (0) 2022.11.16
Django annotate management  (0) 2022.10.12
Django Database Functions - Text functions  (0) 2022.10.11
Django csv streaminghttpresponse  (0) 2022.08.31

댓글