Turbo Drive 페이지네이션에서 URL과 canonical 지키기

목록 일부만 바꾸면 생기는 문제

페이지네이션 목록을 Turbo Frame으로 감싸면 화면 전환이 빠르게 느껴진다. 하지만 공개 블로그에서는 주소, canonical 링크, Open Graph 메타 정보가 현재 페이지와 일치해야 한다. body의 목록만 Frame으로 교체하면 브라우저 주소가 그대로이거나 <head>가 이전 페이지 상태로 남을 수 있다. 사용자는 2페이지를 보고 있는데 검색엔진과 공유 미리보기는 1페이지를 가리키는 상황이 생긴다.

공개 탐색의 핵심은 몇 밀리초를 줄이는 것보다 문서 정체성을 일관되게 유지하는 것이다. URL이 history에 남아야 하는 페이지네이션은 Turbo Drive가 전체 문서를 방문하도록 두는 편이 안전하다.

링크는 평범한 탐색으로 유지한다

목록 전체를 교체하는 별도 Frame을 만들지 않고 일반 링크를 출력한다. Turbo Drive는 서버가 보낸 새 <head><body>를 처리하고 history도 갱신한다.

<nav aria-label="글 페이지">
  <% if @page > 1 %>
    <%= link_to "이전", posts_path(page: @page - 1) %>
  <% end %>

  <% if @has_next_page %>
    <%= link_to "다음", posts_path(page: @page + 1) %>
  <% end %>
</nav>

링크에는 목적이 드러나는 텍스트와 nav label을 제공한다. 비활성 링크를 빈 href로 렌더링하지 말고 조건에 따라 요소 자체를 생략한다. 모바일에서도 링크의 클릭 영역이 최소 44px인지 확인한다.

정렬 순서를 DB에서 확정한다

페이지 이동 중 같은 시각에 발행된 글이 있으면 순서가 흔들릴 수 있다. published_at만 정렬 기준으로 쓰지 말고 id를 보조 기준으로 추가한다.

scope :recently_published, -> {
  published.order(published_at: :desc, id: :desc)
}

목록 조회는 항상 published scope에서 시작한다. 초안 필터링을 뷰에서 처리하면 페이지당 항목 수가 달라지고 다음 페이지 존재 여부도 틀릴 수 있다. 페이지 범위를 벗어난 값, 음수, 숫자가 아닌 입력은 controller에서 정규화하거나 404로 처리해 예측 가능한 응답을 만든다.

head 정보도 현재 URL에서 계산한다

canonical URL은 현재 페이지 번호를 반영해야 한다. 1페이지는 불필요한 ?page=1을 제거한 기본 URL을 사용하고, 2페이지부터 query parameter를 포함한다. Open Graph URL도 같은 규칙을 공유한다.

<% canonical = @page == 1 ? root_url : root_url(page: @page) %>
<link rel="canonical" href="<%= canonical %>">
<meta property="og:url" content="<%= canonical %>">

페이지 제목과 description은 중복을 피할 필요가 있다면 “개발 기록 · 2페이지”처럼 간단히 구분한다. 검색 결과 페이지도 query를 canonical에 어떻게 반영할지 정책을 명시해야 한다. 서로 다른 화면이 모두 루트 canonical을 가리키도록 무조건 통합하면 실제 탐색 구조를 검색엔진에 전달하지 못한다.

브라우저 뒤로가기를 회귀 테스트한다

request test만으로는 Turbo history와 <head> 교체를 검증하기 어렵다. system test에서 다음 순서를 실제로 수행한다.

  • 첫 페이지에서 다음 링크를 누른다.
  • 주소가 ?page=2로 바뀌고 2페이지 글만 표시되는지 확인한다.
  • DOM의 canonical과 og:url이 현재 주소와 일치하는지 검사한다.
  • 브라우저 뒤로가기로 1페이지에 돌아온다.
  • 목록, 주소, canonical이 모두 1페이지 상태인지 다시 확인한다.

같은 테스트에서 draft가 어느 페이지에도 나타나지 않는지와 동일한 발행 시각의 글 순서도 고정한다. 페이지네이션은 단순 목록 분할처럼 보이지만 URL, 정렬, SEO, 브라우저 history가 만나는 기능이다. 공개 페이지에서는 이 네 가지를 하나의 완료 조건으로 다루는 것이 실전에서 더 안전하다.

댓글

아직 댓글이 없습니다.

댓글 남기기