개발 slecs

블로그 전체 페이지에 canonical 태그 추가로 SEO 중복 URL

목차

블로그 base 템플릿에 canonical 태그를 추가했다.

SEO 작업 중에서도 canonical 처리는 늘 "이미 돼 있겠지" 하고 나중에 확인해 보면 빠져 있는 경우가 많다. 이번에도 base 템플릿을 열어보니 canonical link 태그가 없었다. 작은 수정이지만 영향 범위는 블로그 전체 페이지라 우선순위를 높게 잡았다.

왜 canonical이 필요한가

canonical 태그는 검색엔진에게 "이 페이지의 대표 URL은 여기야"라고 명시적으로 알려주는 힌트다. 없으면 크롤러가 임의로 대표 URL을 선택하는데, 이게 생각보다 잘못된 결과로 이어진다.

흔하게 발생하는 문제 패턴을 정리하면 이렇다.

상황 canonical 없을 때 리스크
?utm_source= 쿼리 파라미터 붙은 URL 원본과 별개의 URL로 인식, 중복 페이지 처리
http / https 혼재 두 URL에 PageRank 분산
www / non-www 혼재 마찬가지로 신호 분산
페이지네이션 (/page/2) 1페이지와 중복 콘텐츠로 판단 가능
소셜 공유 시 short URL 경유 원본 URL로 크롤러가 귀결되지 않을 수 있음

블로그는 특히 SNS 유입 트래픽이 많아서 UTM 파라미터가 잔뜩 붙은 URL이 검색엔진에 노출되기 쉽다. canonical이 없으면 그 URL들이 전부 개별 페이지처럼 취급될 수 있다.

변경 내용

app/templates/base.html 한 파일 수정. 모든 페이지가 이 base 템플릿을 상속받는 구조라서 한 곳만 건드려도 전 페이지에 태그가 붙는다. 변경 자체는 핀포인트다.

<!-- app/templates/base.html -->
<head>
  ...
  <link rel="canonical" href="{{ request.url }}" />
  ...
</head>

기본 구현은 이렇게 현재 요청 URL을 그대로 넣는 방식이다. 다만 이 방식이 항상 정답은 아니다. 쿼리 파라미터 처리나 trailing slash 정규화까지 고려하면 canonical 값을 좀 더 가공해서 넣어야 하는 경우도 있다. 예를 들면 아래처럼.

# 뷰 혹은 context processor에서 canonical URL을 별도로 정제
from urllib.parse import urlparse, urlencode, parse_qs

def get_canonical_url(request):
    parsed = urlparse(request.url)
    # utm_*, fbclid 등 트래킹 파라미터 제거
    excluded = {'utm_source', 'utm_medium', 'utm_campaign', 'fbclid'}
    qs = {k: v for k, v in parse_qs(parsed.query).items() if k not in excluded}
    clean_query = urlencode(qs, doseq=True)
    return parsed._replace(query=clean_query).geturl()

이 수준까지 할지는 서비스 상황에 따라 트레이드오프다. 지금 단계에서는 일단 태그를 붙이는 것 자체가 목표였고, 파라미터 정제는 다음 단계로 남겨뒀다.

팀 리뷰 포인트

이런 base 템플릿 수정은 코드 자체는 간단해도 리뷰할 때 몇 가지를 반드시 확인한다.

  • canonical URL이 https로 고정되는지, 아니면 환경에 따라 http가 박히는지
  • 개발/스테이징 환경에서 production URL이 canonical로 박히는 실수는 없는지
  • 템플릿 변수가 None이 되는 경우는 없는지 (렌더링 오류로 빈 canonical 출력 방지)
  • og:url과 canonical URL이 일치하는지 (OGP 태그와 불일치하면 소셜 크롤러 혼란)

특히 세 번째가 의외로 자주 나오는 실수다. base 템플릿에 변수 하나 추가하는 건 쉬운데, 모든 뷰에서 그 변수가 항상 채워진다는 보장을 확인하는 걸 놓치면 일부 페이지에서 빈 태그가 나온다. 검색엔진은 빈 canonical을 그냥 무시하지만, 모니터링 툴에서 워닝으로 잡히면 노이즈가 된다.


작은 수정이지만 base 템플릿 건드리는 작업은 항상 범위가 넓다. 영향 범위가 넓을수록 "간단하다"는 이유로 리뷰를 가볍게 넘기지 않는 게 팀 컨벤션이다. SEO 개선은 성과가 바로 안 보여서 우선순위에서 밀리기 쉬운데, 기반 태그 하나가 6개월 뒤 유입 지표에 영향을 준다고 생각하면 미루기 어렵다.

끝.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.