birchholt 직접 해보고 남기는 기록

글 목록을 여섯 편씩 끊었습니다 — 틀려도 조용한 것들

공개된 글이 일곱 편이 되면서 목록 페이지가 길어져 여섯 편씩 끊기로 했습니다. 설정 한 줄과 템플릿 몇 줄로 끝날 일로 봤는데, 걸린 것들이 대체로 오류를 안 냈습니다. 2026-09-03 작업입니다.

긴 모종 줄에서 여섯 칸짜리 트레이로 모종을 옮겨 담는 온실 작업대

지금 Hugo 에서 옛 키는 무시되는 게 아니라 기본값 10 으로 떨어집니다

낡은 설정 카드를 꽂은 기계가 견본보다 두꺼운 종이 묶음을 조용히 내놓는 인쇄소 작업대

최상위에 paginate = 6 을 적었는데 지금 문법은 [pagination].pagerSize 입니다. 제가 옛 문법을 그대로 적은 것입니다. 설정 키가 조용히 넘어가는 것 자체는 Hugo 로 갈아엎을 때 겪었고 다른 것은 넘어간 다음이었습니다.

설정 블록만 옛 키로 바꾸고 hugo --buildFuture 로 빌드했습니다. 아직 공개 전인 원고까지 함께 세는 옵션이라, 그때 기준으로는 11편이 대상이었습니다.

확인한 것[pagination].pagerSize = 6최상위 paginate = 6
/posts/ 1페이지의 글 카드6개10개
/posts/page/2/생깁니다생깁니다
빌드 출력에서 이 키에 대한 경고—0줄입니다(v0.156.0 이후)

저장소 사본에서 설정 키만 바꿔 양쪽을 따로 빌드해 잰 값입니다. 글이 그동안 더 쌓인 뒤인 2026-09-22에 Hugo v0.165.0 으로 다시 해봐도 같았습니다 — 옛 키 쪽은 1페이지에 카드 10개, 지금 키 쪽은 6개였고 빌드 출력에 paginate 를 언급하는 줄은 없었습니다. 경고가 0줄인 것은 키가 제거된 v0.156.0 이후 이야기입니다 — 키가 아직 살아 있던 v0.128.0~v0.155.x 에서는 ERROR deprecated: site config key paginate was deprecated in Hugo v0.128.0 and will be removed in Hugo 0.141.0. Use pagination.pagerSize instead. 가 찍혔습니다(hugo-paper 이슈 #251, 보고 버전 v0.140.1, 2026-09-22에 열어 확인). 그 버전대에서 값이 반영됐는지까지는 확인하지 못했습니다. 경고문 자체가 함정이라는 점은 적어둘 만합니다 — 저 문장은 0.141.0 에서 없앤다고 예고하는데 실제로 목록에서 빠진 것은 v0.156.0 입니다(릴리스 노트 Site config 절에 paginate (use pagination.pagerSize) 로 실려 있습니다, v0.156.0, 2026-09-22에 열어 확인). 예고된 제거 버전을 그대로 믿고 경계를 잡으면 열다섯 릴리스를 틀립니다. 기본값 10 은 Hugo 설정 문서에 적힌 값입니다.

키가 제거된 v0.156.0 이후 옛 키는 pagerSize 를 내장 기본값 10 으로 떨어뜨립니다. 그래서 글이 열 편에 못 미치는 동안에는 페이징(목록을 여러 쪽으로 나누는 것)을 넣은 티가 안 납니다. 목록은 한 페이지에 다 나오고 열한 편째에야 2페이지가 생깁니다.

canonical 이 페이저를 모릅니다

첫 번째 문을 가리키던 두 번째 문의 화살표 표지판을 제 문 쪽으로 돌리는 사람

2페이지가 생긴 뒤 산출물을 열어봤습니다. 그때는 홈 목록까지 같이 끊고 있어서 홈의 2페이지인 /page/2/ 가 있었는데, 1페이지와 똑같은 두 줄이 박혀 있었습니다.

<title>birchholt — 직접 해보고 남기는 기록</title>
<link rel="canonical" href="https://birchholt.com/">

2페이지의 canonical(이 주소가 원본이라고 검색엔진에 알려주는 표시)이 1페이지를 가리키고 있었으니 1페이지의 복제로 표시된 셈입니다. .Permalink 가 페이저와 무관하게 그 Page 자신의 주소를 돌려주기 때문입니다. 페이저는 목록을 여러 쪽으로 나눠 주는 Hugo 의 장치입니다. 페이저 주소는 Pager 의 .URL 뿐입니다.

2026-09-22에 Hugo v0.165.0 으로 다시 확인했습니다. 저장소 사본에서 아래 치환을 빼고 빌드하면 2페이지 산출물의 canonical 이 그 목록 페이지 자신의 주소로 돌아옵니다.

{{- $canon := .Permalink -}}
{{- with .Store.Get "pager" -}}
  {{- if gt .PageNumber 1 -}}
    {{- $canon = .URL | absURL -}}
    {{- $title = printf "%s (%d페이지)" $title .PageNumber -}}
  {{- end -}}
{{- end -}}

고친 뒤에는 2페이지가 자기 주소를 canonical 로 들고 제목 끝에 「(2페이지)」 를 답니다. 이 글 뒤쪽에서 홈 페이징은 되돌렸으니 지금 남아 있는 2페이지는 글 목록 쪽입니다 — rel=canonical href=https://birchholt.com/posts/page/2/ 가 나옵니다 (--minify 로 공백을 지워 내보내기 때문에 따옴표가 없습니다). 색인이 실제로 어떻게 잡히는지는 아직 확인하지 못했습니다 — 등록하고 몇 주는 지나야 압니다. 색인은 검색엔진이 페이지를 검색 결과 목록에 넣어 두는 것입니다.

2026-09-22에 라이브에서 다시 받아본 값입니다. /posts/page/2/ 는 200 이고 canonical 이 자기 주소, 제목은 「운영 기록 — birchholt (2페이지)」 로 나옵니다.

「빌드가 죽는다」고 적어둔 자리 — 안 죽습니다

금 간 톱니 스케치에 줄을 긋는 사람과 멈추지 않고 도는 태엽 기계, 쓰이지 않은 두 번째 전표

위 코드가 .Store.Get 으로 읽는 이유가 여기 있습니다. head 는 main 블록보다 먼저 만들어지니, head 에서 .Paginator 를 부르면 그 시점에 기본값으로 페이저가 만들어집니다. 뒤이어 main 이 다른 값을 넘겨 .Paginate 를 부르면 어떻게 되는지를 저는 템플릿 주석과 커밋 메시지에 「빌드가 죽는다」고 적어뒀습니다. 인용까지 붙여놨습니다 — invoked multiple times with different arguments.

그 문자열을 찾아봤는데 지금 쓰는 실행 파일에 한 줄도 없었습니다.

$ strings $(which hugo) | grep -cE 'invoked multiple times|different arguments'
0

2026-09-22에 같은 실행 파일로 다시 셌습니다. 제가 인용해뒀던 문자열은 여전히 0건, invalid paginator state 는 1건입니다. Hugo 는 버전마다 메시지가 바뀌니 다른 버전에서는 달라질 수 있습니다.

v0.165.0 의 실제 페이저 오류 문자열은 invalid paginator state for %q 입니다. 그래서 재현했습니다. 복사본에서 baseof 의 페이저 생성을 지우고 head.html 이 .Paginator 를 먼저 부르게 한 뒤, section.html 에서 .Paginate (first 3 .Pages) 2 로 다른 값을 줬습니다.

WARN  HEAD paginator pages=6 totalpages=2
/posts/ 카드 수: 6

WARN 은 확인하려고 넣은 줄입니다. 빌드는 통과합니다. 먼저 만들어진 head 쪽 페이저가 이기고 main 이 준 값은 오류도 경고도 없이 버려져서 목록 개수만 달라집니다. 설계는 손댈 데가 없고 제가 적어둔 근거만 틀렸습니다.

재현은 저장소 사본에서만 했고 Hugo v0.165.0 기준입니다. 페이저를 한 번만 만들게 바꾸면 이 어긋남 자체가 생기지 않아, 고친 뒤에는 다시 잴 것이 없습니다.

{{- /* baseof.html — head 보다 위에서 한 번만 만든다 */ -}}
{{- if and (eq .Kind "section") (eq .Section "posts") -}}
  {{- .Store.Set "pager" (.Paginate .Pages) -}}
{{- end -}}

이유가 「죽으니까」가 아니라 「조용히 어긋나니까」였을 뿐입니다. 주석과 커밋 메시지는 재현이 끝난 그 자리에서 고쳤습니다.

홈을 페이징하지 않기로 했습니다

책 여섯 권을 올린 서점 앞 진열대와 천으로 덮이는 똑같은 두 번째 진열대

홈과 /posts/ 를 둘 다 끊었다가 산출물을 보고 되돌렸습니다.

확인한 것홈까지 페이징했을 때
/page/2/ 의 내용인트로 산문과 「두 개의 기록」 섹션이 통째로 반복됩니다
같은 글 목록의 주소/page/2/ 와 /posts/page/2/ — 두 벌이 됩니다

canonical 을 고쳐놨으니 2페이지가 색인에서 중복으로 합쳐지지는 않지만 읽는 사람에게는 홈의 재방송이 됩니다. 홈은 최신 6편과 「글 전체 보기」 링크로 바꿨습니다.

그 대가로 6 이 두 곳에 남았습니다

느슨한 끈과 빈 꼬리표로만 이어진 두 저울에서 같은 추를 들어 올리는 손

해결 못 한 채로 둔 것. hugo.toml 의 pagerSize = 6 과 home.html 의 $limit := 6 이 따로 적혀 있어서 한쪽만 고치면 경계가 어긋납니다.

한쪽에서 읽어올 수가 없습니다. home.html 에 site.Config.Pagination.PagerSize 를 넣으면 can't evaluate field Pagination in type page.SiteConfig 로 죽습니다 — Hugo 는 pagerSize 를 템플릿에 노출하지 않습니다. 한쪽이 다른 쪽에서 값을 읽어가게 하는 방법은 배포를 자동화할 때 썼는데 여기서는 읽어갈 곳이 없어 안 됐고, 두 파일 주석에 서로를 가리키는 경고를 박아두는 데 그쳤습니다. 주석으로는 강제할 수 없고 부탁만 할 수 있습니다.

2026-09-22에 Hugo v0.165.0 으로 다시 확인했습니다. 저장소 사본의 home.html 에 그 한 줄을 넣고 빌드하니 같은 문장으로 멈췄습니다.

나머지는 짧게 적습니다

기성품 널다리를 두고 손으로 징검돌을 놓으며 가운데를 조약돌 셋으로 표시한 개울

셋 다 2026-09-22에 다시 확인했습니다. 내장 템플릿 쪽은 Hugo v0.165.0 실행 파일에서 문자열을 뽑아 page-item·page-link 같은 Bootstrap 클래스가 그대로 들어 있는 것을 봤습니다. 대비는 라이트 --accent #5c7a5e 와 --bg #fbfaf7, 다크 --accent #8fae90 와 --bg #1a1815 로 WCAG 식에 넣어 나온 값이라 직접 다시 계산해볼 수 있습니다. alias 쪽은 /posts/page/1/ 을 받아보면 200 이되 본문 없이 noindex, follow 와 /posts/ 로 가는 canonical·새로고침만 들어 있습니다.

생략(…)은 pagerSize 를 1 로 낮춰 9페이지로 확인했습니다.

page 1: ← 이전 1 2 3 … 9 다음 →
page 9: ← 이전 1 … 7 8 9 다음 →

정리

코르크 보드에 여섯 장의 빈 카드를 나란히 꽂고 두 장을 느슨한 실로 이은 모습