search_after — from/size가 무너지는 깊은 페이지네이션의 대안
Elasticsearch Completion Suggester 및 search_after 공식 문서 종합 (웹 리서치, 2026) — Elastic 공식 문서(reference/elasticsearch/rest-apis/search-suggesters, reference/elasticsearch/rest-apis/paginate-search-results) Elastic 공식 문서 Paginate search results
이 모듈을 다 읽으면
- from/size가 깊은 페이지에서 왜 성능·메모리 문제와 하드 리밋에 부딪히는지 설명할 수 있다
- search_after가 커서 기반으로 이 문제를 회피하는 방식과 그 대가(임의 페이지 점프 불가)를 설명할 수 있다
elasticsearch-learn-05에서 다룬 일반적인 검색 결과 반환을 전제로, 결과가 아주 많을 때 from/size 방식의 근본적인 한계와, 그 대안으로 커서처럼 동작하는 search_after를 정리한다.
from/size의 한계 — 매 요청마다 이전 페이지 전부를 다시 로드
from과 size로 페이지를 넘기는 방식은, 각 샤드가 요청받은 순위까지의 결과를 전부 메모리에 올려야 한다 — 즉 100페이지째를 요청하면 그 앞의 99페이지 분량까지 전부 다시 계산·로드해야 한다는 뜻이다. 페이지가 깊어질수록 이 메모리·CPU 부담이 커져 성능 저하나 노드 장애로 이어질 수 있고, 이를 막기 위해 index.max_result_window(기본 10000)라는 하드 리밋이 걸려 있어 from+size가 이 값을 넘으면 애초에 요청 자체가 거부된다.
핵심 포인트
- from/size는 각 샤드가 요청 순위까지의 결과를 전부 메모리에 로드 — 페이지가 깊어질수록 메모리/CPU 부담 급증
- index.max_result_window(기본 10000) 하드 리밋으로 그 이상 깊은 from+size 자체가 거부됨
search_after — 이전 결과를 다시 안 읽고 커서로 이어간다
search_after는 이전 페이지의 정렬(sort) 값을 다음 요청에 그대로 실어 보내는 방식으로 동작한다 — '이 정렬 값 다음부터 결과를 달라'는 요청이라, 이전 페이지들을 다시 로드할 필요가 없다. 다만 이 방식이 정확히 동작하려면 모든 요청에 걸쳐 정렬 기준이 일관돼야 하고, 동점(tie)이 나는 정렬 기준만 쓰면 페이지 경계에서 결과가 누락되거나 중복될 수 있어 _id처럼 고유값을 보장하는 타이브레이커 필드를 정렬 기준에 반드시 포함해야 한다.
핵심 포인트
- search_after는 이전 페이지의 정렬 값을 커서처럼 넘겨 이전 결과를 다시 로드하지 않고 결과 크기와 무관하게 확장 가능
- 모든 요청에 걸쳐 일관된 정렬 기준 필요, _id 같은 타이브레이커 필드를 포함하지 않으면 결과 누락/중복 위험
대가 — 순차적으로만 넘어갈 수 있고, 임의 페이지로 점프 불가
search_after는 '다음 페이지로 이어가는' 순차적 페이지네이션만 지원한다 — from/size처럼 '10번째 페이지로 바로 점프'하는 것은 할 수 없고, 반드시 이전 페이지의 마지막 결과값을 알아야 다음 페이지를 요청할 수 있다. 그래서 사용자가 임의 페이지 번호를 직접 클릭해 이동하는 전통적인 페이지네이션 UI보다는, '더 보기(load more)'나 무한 스크롤처럼 순차적으로만 다음 데이터를 가져오는 UX에 자연스럽게 맞는다.
핵심 포인트
- search_after는 순차적 페이지네이션만 지원 — 임의 페이지 번호로 바로 점프 불가
- '더 보기'/무한 스크롤처럼 순차적으로 다음 데이터를 가져오는 UX에 자연스럽게 맞음