본문 바로가기
개발/문제 해결

OpenSearch 페이징 문제 및 해결

by nineteen 2025. 2. 27.
반응형

안녕하세요. 이번에는 OpenSearch를 사용하면서 겪었던 페이징 관련 이슈와 그 해결 과정에 대해 공유드리고자 합니다.

문제 상황

OpenSearch를 통해 데이터를 페이징하는 과정에서 다음과 같은 문제가 발생하였습니다:

  1. 실제 데이터는 10,000개 이상 존재하나, size 10 기준으로 1,000 페이지(총 10,000개)까지만 데이터가 표시되었습니다.
  2. 10,000개 이상의 데이터는 조회가 불가능한 상황이었습니다.
  3. 결과적으로 페이징 처리 중 데이터 유실이 발생하였습니다.

문제 해결 과정

1차 시도: max_result_window 설정 확인

먼저 Elasticsearch의 기본 검색 제한인 10,000건 제한과 관련이 있을 것으로 판단하여 max_result_window 설정을 확인해보았습니다.

GET {index}/_settings
GET {index}/_settings?filter_path=**.max_result_window

확인 결과, 이미 max_result_window 값이 50,000으로 설정되어 있었습니다. 따라서 이 설정은 문제의 원인이 아니었습니다.

2차 시도: track_total_hits 옵션 검증

Elasticsearch 공식 문서를 통해 track_total_hits 옵션에 대해 알게 되었습니다. 이 옵션은 10,000건이 넘는 데이터의 정확한 개수를 출력하기 위해 필요한 설정이었습니다.

다음과 같이 직접 쿼리를 실행하여 검증해보았습니다:

GET {index}/_search
{
  "from": 0,
  "size": 10,
  "sort": [
    { "timestamp": "desc" }
  ],
  "query": {
    "match_all": {}
  },
  "track_total_hits": true
}

검증 결과:

  • track_total_hits: true 설정 시: 정확한 전체 문서 개수 출력
  • track_total_hits 미설정 시: 10,000개로 제한되어 출력

최종 해결: NativeSearchQuery 활용

Spring Data Elasticsearch Repository에서는 track_total_hits 옵션을 직접 설정할 수 없다는 한계가 있었습니다. (제가 못찾은 것일 수도 있습니다ㅜ)
이를 해결하기 위해 OpenSearchRestTemplateNativeSearchQuery를 활용하였습니다.

기존 코드

val pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "timestamp"))
val documentList = elasticsearchRepository.findAll(pageable)

개선된 코드

val pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "timestamp"))  

val searchQuery = NativeSearchQueryBuilder()  
    .withQuery(QueryBuilders.matchAllQuery())  
    .withPageable(pageable)  
    .withTrackTotalHits(true)  // 전체 문서 개수를 정확하게 추적하기 위한 설정
    .build()  

val searchHits = openSearchRestTemplate.search(searchQuery, Document::class.java)  
val totalElements = searchHits.totalHits  
val documentList = searchHits.searchHits.map { it.content }

// 페이징 처리
val documentsPage: Page<Document> = PageImpl(documentList, pageable, totalElements)

참고 문서

  1. 책에는 안나오는 ES 경험 맛보기 - Elasticsearch의 기본 검색 제한 관련
  2. Elasticsearch Guide - Track total hits - track_total_hits 옵션 공식 문서