OpenSearch search_after에서 문서가 누락되거나 중복되는 이유
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
deep pagination에서 sort 기준과 tie-breaker가 왜 중요한지 실제 실수 예시로 설명한다. 여러 선택지를 한 번에 적용하기보다 ‘정렬값 중복’부터 확인합니다. timestamp 하나로 정렬하면 같은 값을 가진 여러 문서의 상대 순서가 안정적으로 정해지지 않습니다. 모든 문서에서 값이 존재하는 고유한 tie-breaker를 두 번째 정렬 키로 추가합니다.
이 글의 범위
실제 경험이나 측정 결과를 가정하지 않고, 공식 문서로 확인 가능한 개념과 적용 순서를 일반 가이드로 설명합니다. 제품 버전과 서비스 정책은 바뀔 수 있으므로 적용 전 연결된 공식 문서를 다시 확인하세요.
처음 확인할 경계
search_after 자체가 문서를 잃어버리는 것이 아니라 불완전한 정렬과 실시간 데이터 변경이 페이지 경계를 흔드는 경우가 많습니다. ‘정렬값 중복’에서 시작해 ‘실시간 변경’와의 경계를 정하면 구현할 범위와 실패했을 때 확인할 지점을 구분하기 쉬워집니다.
페이지 경계를 흔드는 실수
- 중복이 많은 timestamp만 정렬 키로 사용하기
- 다음 요청에서 sort 순서나 query 조건을 바꾸기
- 실시간 변경이 많은 인덱스에서 PIT 없이 고정 결과를 기대하기
- 마지막 문서의 _source 값을 search_after에 넣고 sort 배열을 쓰지 않기
OpenSearch search_after에서 문서가 누락되거나 중복되는 이유 핵심 판단 흐름 설명용 개념도
그림 1. OpenSearch search_after에서 문서가 누락되거나 중복되는 이유의 핵심 판단 순서를 정리한 설명용 개념도입니다. 실제 서비스 화면, 운영 로그 또는 측정 결과가 아닙니다.
안정적인 deep pagination 구성
- 업무상 필요한 정렬 기준과 고유 tie-breaker 필드를 정합니다.
- 두 필드에 모든 문서가 유효한 값을 갖는지 매핑과 데이터를 확인합니다.
- 일관된 결과가 필요하면 충분하지만 짧은 keep_alive로 PIT를 만듭니다.
- 각 페이지의 마지막 sort 배열을 다음 요청의 search_after로 그대로 사용합니다.
- 작업이 끝나면 PIT를 삭제하고 고유 ID 수와 예상 count를 비교합니다.
두 정렬 키를 사용하는 예
GET logs/_search
{
"size": 1000,
"sort": [
{ "@timestamp": "asc" },
{ "event_id.keyword": "asc" }
],
"search_after": ["2026-07-15T01:02:03Z", "evt-00991"],
"query": { "match_all": {} }
}
누락과 중복이 생기는 두 원인
정렬값 중복
timestamp 하나로 정렬하면 같은 값을 가진 여러 문서의 상대 순서가 안정적으로 정해지지 않습니다. 모든 문서에서 값이 존재하는 고유한 tie-breaker를 두 번째 정렬 키로 추가합니다.
실시간 변경
search_after는 상태를 보관하지 않는 live cursor이므로 페이지를 넘기는 동안 문서가 추가·수정·삭제되면 순서가 달라질 수 있습니다. 이것은 버그가 아니라 방식의 특성입니다.
PIT
Point in Time은 특정 시점의 데이터 상태를 고정합니다. OpenSearch 공식 문서는 깊은 페이지네이션에 PIT와 search_after 조합을 선호하는 방식으로 안내합니다.
정렬 일관성
첫 요청과 다음 요청의 query, sort 순서, 오름·내림차순, PIT ID가 같아야 합니다. 마지막 hit의 sort 배열을 수정하지 않고 그대로 전달합니다.
누락 검증
페이지별 개수 합계만 보지 말고 문서 ID의 중복 수, 고유 ID 수, 예상 조건의 전체 count를 비교합니다. 테스트 중에도 쓰기 작업을 분리해 원인을 명확히 합니다.
실제 적용과 설명을 대조하기
| 확인 항목 | 질문 |
|---|---|
| 첫 기준: 정렬값 중복 | 변경 전에 전제와 목적을 확인했는가? |
| 분리 대상: 실시간 변경 | 다른 책임과 섞이지 않게 경계를 정했는가? |
| 피할 패턴: 중복이 많은 timestamp만 정렬 키로 사용하기 | 본문에서 경고한 패턴이 남아 있지 않은가? |
| 오류와 복구 | 정상 경로뿐 아니라 실패와 되돌리기도 확인했는가? |
적용 순서 요약
search_after 자체가 문서를 잃어버리는 것이 아니라 불완전한 정렬과 실시간 데이터 변경이 페이지 경계를 흔드는 경우가 많습니다. 고유 tie-breaker와 PIT, 동일한 요청 조건을 사용하면 깊은 페이지네이션을 훨씬 안정적으로 만들 수 있습니다.
참고한 공식 문서
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
댓글
댓글 쓰기