페이징 전략 정리 (실무 중심)
✅ 1. 기본 페이징: from + size
🔹 개념
SQL의 OFFSET, LIMIT처럼 특정 위치부터 몇 개를 가져옴.
{
"query": { "match_all": {} },
"from": 0,
"size": 10
}
✅ 특징
- 가장 기본적인 방법
- from=0, size=10 → 1페이지, from=10, size=10 → 2페이지
⚠️ 주의사항
- from이 클수록 성능이 나빠짐 (deep pagination)
- 기본 최대는 10,000 (index.max_result_window 초과 시 에러)
💡 실무 팁
- 리스트 조회에는 적합
- 대용량 페이징에는 search_after 또는 scroll 사용
✅ 2. 안정적인 순차 페이징: search_after
🔹 개념
정렬된 필드 기준으로 커서를 넘겨 다음 페이지 요청
{
"query": { "match_all": {} },
"size": 10,
"sort": [{ "created_at": "desc" }, { "_id": "desc" }],
"search_after": ["2024-01-01T00:00:00", "abc123"]
}
✅ 특징
- sort 필수
- search_after는 이전 문서의 마지막 sort 값
⚠️ 주의사항
- from과 병행 불가
- 정렬 필드는 고유한 값 포함 필요 (예: created_at + _id)
💡 실무 팁
- 무한 스크롤 또는 next 버튼 기반 페이지에 적합
- 실시간 데이터 변동에도 일관성 유지
✅ 3. 대용량 전체 조회: scroll
🔹 개념
scroll context를 유지하면서 반복적으로 대량 조회
{
"scroll": "1m",
"size": 100,
"query": { "match_all": {} }
}
✅ 특징
- 정렬 없이 사용 가능
- 전체 데이터를 순차적으로 조회
⚠️ 주의사항
- 실시간성 없음 (스냅샷 기반)
- 메모리 리스크 → 오래 유지 ❌
💡 실무 팁
- 백업, ETL, 로그 수집 등에 사용
- UI 페이징에는 적합하지 않음
✅ 4. 최신 방식: Point In Time (PIT) + search_after
🔹 개념
스냅샷 기준으로 안정적인 페이징 제공 (8.x 이상)
// PIT 열기
POST /my-index/_pit?keep_alive=1m
// PIT 기반 search
{
"size": 10,
"query": { "match_all": {} },
"pit": { "id": "<PIT_ID>", "keep_alive": "1m" },
"sort": [{ "created_at": "desc" }, { "_shard_doc": "desc" }]
}
✅ 특징
- PIT 유지하며 search_after 사용
- 동일한 기준으로 정확한 페이징 가능
💡 실무 팁
- 정밀하고 정확한 페이지 조회 필요할 때 사용
- 사용 후 close 권장
✅ 페이징 전략 비교표
전략 | 장점 | 단점 | 사용 시점 |
---|---|---|---|
from + size | 구현 쉬움 | deep pagination 시 성능 저하 | 소규모 조회 |
search_after | 커서 방식, 빠름 | 중간 페이지 이동 불가 | 무한 스크롤 등 |
scroll | 전체 조회 | 실시간성 없음, 리소스 큼 | 백업, 배치 처리 |
PIT + search_after | 정확도 최고, 최신 방식 | 8.x 이상, 관리 필요 | 고정된 검색 기준 페이징 |