검색 결과 0건을 복구 가능한 상태로 설계하는 방법
검색 결과가 0건일 때 오타·필터 충돌·권한·검색 장애를 구분하고, 숨겨진 문서를 노출하지 않으면서 사용자가 다음 행동을 선택하게 만드는 복구 흐름을 정리합니다.
검색 화면이 비어 있다고 해서 항상 정상적인 0건 응답인 것은 아닙니다. 정상적으로 검색했지만 조건에 맞는 문서가 없는 경우, 필터가 결과를 모두 제외한 경우, 현재 사용자에게만 보이지 않는 경우, 검색 서비스가 실패한 경우를 먼저 나누어야 합니다. 그 다음에만 오타 제안·필터 완화·문의 안내 중 하나를 선택해야 사용자가 잘못된 원인을 고치느라 시간을 쓰지 않습니다.
이 글의 기준은 검색엔진을 빠르게 튜닝하는 방법이 아닙니다. 제품 화면에서 0건을 어떻게 설명하고 복구시킬지에 집중합니다. 검색어와 현재 필터는 복구 과정에서도 보존하고, 사용자가 볼 수 없는 문서의 제목이나 전체 개수를 제안 목록으로 흘리지 않는 것이 출발점입니다.
0건을 한 가지 화면으로 처리하지 않는다
응답에 hits.total이 0으로 보였다는 사실만으로 ‘데이터가 없다’고 확정하면 안 됩니다. 타임아웃이나 인덱스 오류는 오류 상태로 알려야 하고, 권한 필터로 제외된 문서는 존재 여부를 추측하게 만들지 않아야 합니다. 정상 응답의 진짜 0건만 검색어·필터·대체 행동을 안내하는 빈 상태로 보냅니다.

응답을 화면 상태로 바꾸는 판정 순서
요청이 끝까지 처리됐는지 확인한다. 타임아웃·5xx·인덱스 연결 오류면 0건으로 바꾸지 말고 재시도와 문의 경로를 표시한다.
현재 사용자가 읽을 수 있는 범위에서 검색했는지 확인한다. 권한 필터로 제외된 문서의 존재나 개수를 추론할 수 있는 메시지는 만들지 않는다.
정상 응답이고 현재 조건에서만 0건인지 확인한다. 검색어와 필터를 기록한 뒤 충돌 가능성이 있는 필터를 사용자에게 선택적으로 완화한다.
결과가 있으면 복구 제안을 숨기고 기존 검색어·필터·정렬을 유지한 목록을 보여 준다.
오타 제안은 이 판정 뒤에 제한적으로 붙입니다. Elastic 문서에서 term suggester는 토큰별 편집 거리를 기준으로 대안을 만들고, phrase suggester는 여러 토큰을 묶은 교정 문구를 선택합니다.Suggester 문서의 기능을 제품 복구 정책과 혼동하지 않아야 합니다. text·keyword 필드의 fuzziness도 Levenshtein 편집 거리로 해석된다는 설명이 있지만, 이는 후보 생성 능력을 말할 뿐 권한 범위까지 자동으로 보장하지 않습니다.fuzziness 옵션을 적용하더라도 최종 조회에는 원래 사용자의 필터와 접근 조건을 다시 적용해야 합니다.
복구 행동은 사용자가 선택한 범위에서만 넓힌다
자동으로 모든 필터를 제거하고 결과를 다시 보여 주면 사용자의 의도를 바꿉니다. 먼저 ‘현재 조건에서 일치하는 결과가 없습니다’라고 말하고, 충돌 가능성이 큰 필터 하나씩만 해제할 수 있게 제안합니다. 필터를 완화한 결과도 같은 권한 조건과 같은 검색어로 조회하고, 어떤 필터가 바뀌었는지 화면에 남겨야 원래 결과와 새 결과를 비교할 수 있습니다.

가상 사례: ‘예약 연동’ 검색과 ‘쇼핑몰’ 필터
가상 사례의 입력은 검색어 ‘예약 연동’과 활성 필터 ‘쇼핑몰’입니다. 정상 응답이지만 현재 조합의 결과가 0건이고, 사용자의 읽기 권한 안에는 필터를 제거했을 때 볼 수 있는 문서가 있다고 가정합니다. 첫 결정은 오타 교정이 아니라 필터 충돌을 설명하는 것입니다.
중간 산출물은 query=예약 연동, active_filter=쇼핑몰, zero_reason=filter_conflict, candidate_action=remove_filter, visible_scope=current_user라는 복구 기록입니다. 화면은 ‘쇼핑몰 조건에서는 결과가 없습니다’와 ‘쇼핑몰 필터 제거’라는 한 가지 명확한 행동을 함께 보여 줍니다. 사용자가 버튼을 눌렀을 때만 쇼핑몰 필터를 제거하고 같은 권한 범위로 재검색합니다.
기대 결과는 사용자가 명시적으로 필터를 제거한 뒤 결과 6건을 보고, 검색어 ‘예약 연동’과 제거된 필터를 다시 확인하는 것입니다. 결과 6건은 현재 사용자가 볼 수 있는 문서만 세어야 하며, 권한 밖 문서가 있었음을 암시하는 문구나 추천 제목을 추가하지 않습니다. 이 사례의 핵심은 0건을 결과 없음으로 끝내지 않고, 사용자가 원인을 확인한 뒤 한 단계만 되돌릴 수 있게 하는 데 있습니다.
실패 경로와 공개하면 안 되는 정보
타임아웃·인덱스 장애가 발생했는데 ‘검색 결과가 없습니다’라고 표시하는 실패 경로는 먼저 고쳐야 합니다. 검색 재시도는 같은 query와 필터로 한 번만 수행하고, 계속 실패하면 오류 추적 ID와 문의 경로를 제공합니다. 재시도 중에 빈 목록을 캐시하면 장애가 정상 0건처럼 굳어질 수 있으므로 오류와 빈 결과의 캐시 정책도 분리합니다.
권한 필터로 보이지 않는 문서의 제목·추천 검색어·전체 개수를 알려 주는 방식도 사용하지 않습니다. 오타 제안이나 phrase 후보를 만들더라도 현재 사용자의 검색 범위와 최종 필터를 통과한 후보만 검토 대상으로 삼는다는 제품 규칙을 서버와 화면에 함께 남깁니다. 이는 Elasticsearch가 자동으로 처리한다는 뜻이 아니라, 제품이 직접 지켜야 할 경계입니다.
상태 메시지의 접근성도 결과 수와 함께 점검합니다. W3C의 ARIA22는 role=status를 업데이트된 상태를 보조 기술에 알리는 기법으로 설명하고, 전체 문맥을 읽혀야 한다면 aria-atomic=true를 명시하는 예를 보여 줍니다. 이 문서는 WCAG 기법의 예시이지 모든 구현의 필수 조건은 아니므로, 실제 화면에서 ‘필터 제거 후 결과 6건’처럼 변화와 맥락이 함께 전달되는지 확인하는 기준으로 사용합니다.W3C ARIA22의 테스트 절차처럼 상태 컨테이너가 업데이트 전에 존재하고 변경된 메시지를 담는지도 확인합니다.
반례: 진짜 0건은 억지로 넓히지 않는다
검색어가 정상 처리됐고 필터 충돌도 없으며 현재 사용자의 가시 범위에 실제 문서가 없다면, 무관한 인기 문서를 끼워 넣거나 권한 밖 문서를 추천하지 않습니다. 검색어를 다시 입력하거나 지원팀에 문의할 수 있는 선택지를 남기되, 그것을 결과가 있는 것처럼 표현하지 않습니다. 자동 필터 완화가 업무상 금지된 화면이라면 완화 버튼을 제거하고 문의 흐름으로 바로 보냅니다.
결과 목록으로 돌아온 뒤에는검색 친화적인 페이지네이션 기준으로 조건을 이어가세요. 검색 실패율을 운영 지표로 쓴다면다음 행동을 정하는 대시보드 설계도 참고할 수 있습니다.
완료 조건을 응답과 화면에서 함께 확인한다
정상 0건·오류·권한 제외·결과 있음을 각각 재현한다. 정상 0건과 권한 밖 문서 제외는 사용자 화면과 HTTP 응답으로 구분하지 않고, 권한이 있는 운영자의 내부 판정 기록으로만 검증한다. 오류와 정상 응답은 구분한다.
필터 완화 전후의 query, 필터, 결과 수, 사용자 가시 범위를 판정 기록에서 대조한다.
오타 제안과 자동완성 후보에 권한 밖 제목·개수·식별자가 포함되지 않는지 검증한다.
스크린 리더에서 결과 수와 바뀐 필터가 함께 전달되고, 장애 재시도 실패에는 추적 ID와 문의 경로가 남는지 확인한다.
검색 결과 0건 복구가 완료됐다고 기록할 수 있는 상태는 성공 응답 한 건을 본 때가 아닙니다. 네 가지 상태를 같은 입력으로 재현하고, 사용자가 선택한 복구 뒤에도 권한과 필터가 보존되며, 화면·로그·판정 기록에서 기대한 결과를 확인하고 남겼을 때 검증 완료입니다.