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에는 공개 글의 정규 주소만 넣었다.
확인 순서
- 최종 HTML에 canonical link가 있는지 확인한다.
- sitemap URL이 200이고 공개 글만 포함하는지 본다.
- robots 설정이 sitemap 위치를 알려 주는지 확인한다.
- 제목·설명·canonical의 slug가 같은 글을 가리키는지 비교한다.
- 내부 링크가 불필요한 쿼리 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 계약을 관리하는 웹 개발 작업이었다.