← 전체 글로 돌아가기

Next.js

검색 결과에 개발 노트가 중복 노출된 뒤 canonical과 sitemap을 정리한 순서

쿼리스트링과 태그 URL이 같은 글을 여러 주소로 노출하던 문제를 점검한 순서

같은 글에 주소가 세 개였다

/posts/deploy, /posts/deploy?ref=home, /posts/deploy?tag=linux가 모두 접근 가능했다. 본문은 같았고 추적 파라미터도 필요했지만 대표 URL 신호가 흩어질 수 있는 구조였다.

canonical을 첫 기준으로 삼았다

게시물 head에 정규 주소를 넣고 도메인과 trailing slash 정책을 통일했다.

export function generateMetadata({ params }: Props): Metadata {
  const url = `https://blog.turin.my/posts/${params.slug}`
  return { alternates: { canonical: url } }
}

canonical만으로 끝내지 않고 내부 링크는 쿼리 없는 URL을 가리키게 했다. sitemap에는 공개 글의 정규 주소만 넣었다.

확인 순서

  1. 최종 HTML에 canonical link가 있는지 확인한다.
  2. sitemap URL이 200이고 공개 글만 포함하는지 본다.
  3. robots 설정이 sitemap 위치를 알려 주는지 확인한다.
  4. 제목·설명·canonical의 slug가 같은 글을 가리키는지 비교한다.
  5. 내부 링크가 불필요한 쿼리 URL을 대표로 만들지 않는지 본다.
curl -s https://blog.turin.my/posts/deploy | grep -o 'rel="canonical"[^>]*'
curl -s https://blog.turin.my/sitemap.xml | grep -o 'https://blog.turin.my/posts/[^<]*'

성공 기준을 바꿨다

검색 결과는 바로 바뀌지 않는다. 당장의 기준은 새 페이지가 일관된 canonical과 sitemap을 내보내고 내부 링크가 한 주소를 사용하는지로 잡았다. SEO도 결국 URL 계약을 관리하는 웹 개발 작업이었다.