<aside> 📌

목차

검색 시스템 🔍

개요

검색 시스템은 Elasticsearch로 구동되는 고성능 풀텍스트 검색 엔진을 제공합니다. 사용자는 한국어 형태소 분석, 고급 필터링(장르, 지역), 커스터마이즈 가능한 정렬(정확도, 인기도)을 통해 밴드, 공연, 게시물을 탐색할 수 있습니다. 시스템은 이벤트 기반 재인덱싱 파이프라인을 통해 관계형 데이터베이스와 검색 인덱스 간의 데이터 정합성을 유지합니다.

Document Index Name 주요 검색 필드
BandDocument bands name, description, genre, region
PerformanceDocument performances title, bandName, venue, description
PostDocument posts title, bandName, tags, description

검색 서비스 — 쿼리 · 정렬 · 최근 검색어

쿼리 로직 및 스코어링

SearchService는 데이터 조회를 위한 ElasticsearchOperations와 이력 관리를 위한 RecentSearchService를 연결하는 주요 조율자 역할을 하며, NativeQuery를 사용하여 복잡한 Elasticsearch DSL을 구성합니다.

정렬 모드(SearchSortType)

정렬 모드 정렬 기준
ACCURACY _score(내림차순) → date(내림차순) → docId(내림차순)
POPULAR popularity(내림차순) → _score(내림차순) → docId(내림차순)

POPULAR의 popularity 정의는 밴드는 팔로워 수, 공연은 관심 표시 수, 게시물은 소속 밴드의 팔로워 수입니다(SearchSortType.java 5~6번째 줄).

페이지네이션과 SearchCursor

단일 타입 검색의 경우 search_after 페이지네이션을 사용합니다. API를 무상태로 유지하고 내부 구조를 불투명하게 감추기 위해, SearchCursor 유틸리티는 마지막 문서의 정렬 값들을 Base64URL 문자열로 인코딩합니다.

최근 검색어 이력

RecentSearchService는 FanModeRecentSearch 엔티티에 저장된 사용자 검색어 이력을 관리합니다.

응답 DTO

Field ALL 모드 단일 타입 모드
totalCount 모든 섹션의 합계 특정 타입의 개수
bands / performances / posts 각각 최대 3건 페이지네이션된 목록
nextCursor null 인코딩된 search_after 토큰
hasNext null 추가 결과가 있으면 true

검색 인덱싱 — Elasticsearch 문서 · 이벤트 파이프라인

Elasticsearch 문서 모델

한국어 Nori 분석기 설정

이벤트 기반 인덱싱 파이프라인

flowchart LR
    A["도메인 변경"] --> B["ApplicationEventPublisher\n(BandChangedEvent 등)"]
    B --> C["SearchIndexEventListener"]
    C --> D["SearchIndexReader\n(읽기 전용 트랜잭션)"]
    D --> E["SearchIndexService\n(upsert / delete)"]
    E --> F["Elasticsearch"]

이러한 단계 분리는 느린 Elasticsearch HTTP 호출이 DB 커넥션을 계속 점유하지 않도록 보장합니다.

도메인 간 검색 어댑터

Port 구현체 책임
search.port.PerformancePort performance.adapter.SearchAdapter 밴드 조인과 관심 표시 수를 포함하여 활성 공연을 조회합니다.
search.port.PostPort post.adapter.SearchAdapter 밴드 및 태그 조인을 포함하여 게시물을 조회합니다.
search.port.FollowPort follow.adapter.SearchAdapter 인기도 스코어링을 위해 팔로워 수를 집계합니다.