글 하나에 URL 열두 개
이 글의 내용
이 블로그의 모든 글은 주소 열두 개에 삽니다. 열하나는 언어 접두사를 지니고 — /en/blog/…, /de/blog/… 그리고 아홉 개 더 — 열두 번째는 접두사가 아예 없습니다. 그것은 브라우저의 Accept-Language 헤더를 읽고 열하나 가운데 알아본 언어로 답합니다.
8월 27일과 28일에 크롤러가 이 사이트에서 블로그 페이지 1,609개를 가져갔습니다. 독자는 628개를 가져갔습니다.
페이지들이 이미 서로에게 말하고 있는 것
열둘 모두 자기 머리에서 같은 세 가지를 말하고, 오늘 코드를 믿는 대신 셋 다 확인했습니다.
각 페이지의 정규 링크는 자기 자신을 가리킵니다. hreflang 줄 열하나가 언어판 형제들을 이름 붙이고, 열두 번째가 접두사 없는 주소를 x-default로 이름 붙입니다. 그 주소는 어느 한 언어에도 속하지 않기 때문입니다. 접두사 없는 주소는 Vary: Accept-Language, Accept-Encoding로 답하므로, 그 앞에서 캐시하는 무엇이든 본문이 요청 헤더에 달렸다는 것을 압니다.
협상은 작동합니다. 같은 URL을 Accept-Language: de로 청하면 lang="de"로 표시된 페이지가 오고, ja로 청하면 일본어가, 아무도 쓰지 않는 코드로 청하면 영어가 옵니다. 네 언어를 오가며 열두 번 요청하니 옳은 본문 넷이 세 번 되풀이해 왔고, 그러니 페이지 캐시는 경로만이 아니라 언어로도 열쇠가 걸려 있습니다.
이것이 명세가 청하는 바입니다. 모든 구성원이 자기 자신과 모든 형제를 이름 붙이는 완전하고 상호적인 묶음 말입니다. 검색 엔진이 주소 열둘을 서로 겨루는 글 열둘이 아니라 열두 언어로 된 글 하나로 다룰 수 있게 하는 얼개입니다.
그렇다고 누가 덜 가져가지는 않습니다
가져가기를 줄이지도 않고, 접근 로그가 해석의 여지를 별로 남기지 않고 그렇게 말합니다.
ClaudeBot은 글 36편에 걸쳐 블로그 요청 396건을 했습니다 — 정확히 언어판 11.0개씩, 모든 언어를, 매번입니다. bingbot은 글 37편에 평균 8.7, PetalBot은 6.0, Applebot은 4.3이었습니다. SemrushBot은 1.8이었습니다. Googlebot은 글 42편에 걸쳐 요청 72건을 했고 글마다 평균 언어판 1.5개이며, 여섯 가운데 유일하게 그 표시가 자기에게 닿은 것처럼 구는 크롤러입니다.
모든 크롤러를 통틀어 글 76편 가운데 73편이 적어도 한 번 건드려졌고, 그 가운데 68편은 한 언어보다 많이 건드려졌습니다. 평균은 열하나 가운데 언어판 7.84개였습니다.
이 가운데 위반은 없습니다. hreflang는 페이지들이 어떻게 관계되는지에 대한 힌트이고, 어느 결과를 보여 줄지 정하는 검색 엔진의 부분에 건네는 말입니다. 무엇을 내려받을지 정하는 부분에 대한 지시가 아닙니다. /uk/blog/…를 한 번도 본 적 없는 크롤러는 그것을 가져와 머리를 읽기 전에는 번역이라는 것을 알 길이 없습니다 — 그 표시는 아꼈을지도 모를 바로 그 요청 뒤에야 효력을 낼 수 있습니다.
값은 얼마인가
위 문단이 짐작하게 하는 것보다 적습니다. 글 페이지 1,609개에 블로그의 목록 페이지와 태그 페이지를 더하면, 크롤러가 /blog 아래로 보낸 요청은 1,689건입니다. 이는 이 가상 호스트가 이틀 동안 답한 373,019건의 0.5퍼센트이고, 보낸 4,363MB 가운데 19.9MB입니다. 블로그 페이지는 10분의 1초쯤에 돌아오므로, 열한 배 크롤링 전체가 하루에 프로세서 시간 여든 초쯤 듭니다.
사이트맵은 제가 생각한 것보다 조금 더 듭니다. 주소 3,136개와 거기 붙은 대체 언어 표시 13,248개를 담고, XML 1.85MB, 압축하면 35KB입니다. 많아야 여섯 시간마다 다시 만들어지고, 그래서 오후 1시 10분에 나온 글이 몇 시간 뒤에야 온전히 거기 나타나고 곧바로는 아닙니다.
그 숫자 가운데 바꿀 값어치가 있는 것은 없습니다. 가져가기를 줄일 유일한 지렛대는 그 주소들을 두지 않는 것이고, 그 주소들이 바로 요점입니다.
독자와 크롤러는 다른 것을 원합니다
같은 이틀을 언어로 나누어 보면 사뭇 다른 두 습관이 드러납니다.
크롤러는 거의 고르게 퍼집니다. 블로그 요청의 5.5퍼센트에서 10.5퍼센트 사이가 접두사가 붙은 열한 판 각각으로 갔고, 접두사 없는 것에 16퍼센트가 갔습니다. 목록을 훑는 무언가의 모양입니다.
독자는 고르게 퍼지지 않습니다. 요청의 38퍼센트가 접두사 없는 주소로, 또 18퍼센트가 /en/로 갔으니, 절반 넘게가 영어로 오거나 협상으로 왔습니다. 나머지는 열 개 언어로 나뉘고, 가장 큰 독일어가 7퍼센트, 가장 작은 프랑스어가 2퍼센트입니다.
남은 그 44퍼센트가 언어 경로가 존재하는 까닭 전부입니다. 그리고 언어 경로를 없애자고 주장하기 쉬울 만큼 작기도 합니다 — 그것은 크롤러 칸을 읽고 페이지가 인기 있다고 결론짓는 것과 같은 잘못입니다.
무엇이 일반화되는가
옳은 힌트는 지시가 아닙니다. 이 페이지들의 머리에 있는 모든 것이 옳고, 상호적이고, 확인할 수 있으며, 여섯 크롤러 가운데 다섯은 그런 것이 없는 양 가져갑니다. 명세는 그 표시가 무엇을 뜻하는지 설명하지, 어떤 프로그램이 그것을 보고 무엇을 할지 설명하지 않습니다.
그러니 쓸모 있는 물음은 마크업이 옳은가가 결코 아니었습니다. 가져가는 쪽이 실제로 몇 번 오는가였고, 그것은 로그만이 답할 수 있는 물음입니다 — 그리고 답하고 나면 정직한 결론은 열한 배 크롤링이 0.5퍼센트를 치르며 그대로 두어야 한다는 것입니다.