해 프로젝트는 대량의 상품 검색과 필터링 속도를 확보하고, RAG 기반 AI 추천을 위한 벡터 검색 데이터를 저장하기 위해 Elasticsearch를 사용합니다. Spring Data Elasticsearch를 활용하여 도메인 객체를 인덱스에 매핑하며, 복잡한 형태소 분석(Nori) 설정은 인프라 레벨에서 처리되므로 개발자는 Document 정의, Repository 인터페이스 구현 두 가지만 신경 쓰면 됩니다.
application.yml에 정의된 주요 설정입니다.
| 구분 | 설정 항목 | 설정값 (Class/Value) | 설명 |
|---|---|---|---|
| 공통 | uris | localhost:9200 |
Elasticsearch 서버 주소입니다. (환경 변수 주입 권장) |
| 인덱스 | shards | 1 |
데이터를 분산 저장하는 단위입니다. 초기 단계는 1개로 충분합니다. |
| 인덱스 | replicas | 0 |
데이터 복제본 수입니다. 로컬/테스트 환경은 리소스 절약을 위해 0으로 설정합니다. |
| Mapping | write-type-hint | false |
문서 저장 시 _class 필드가 자동으로 추가되는 것을 방지하여 용량을 최적화합니다. |
Elasticsearch에 저장될 데이터 구조를 정의합니다. ****AI 추천을 위한 벡터 필드를 미리 고려하여 설계합니다.
@Document(indexName = "products") // ✅ 인덱스 이름 (반드시 소문자)
@Setting(shards = 1, replicas = 0)
@Getter @NoArgsConstructor
public class ProductDocument {
@Id // ✅ ES의 _id 필드와 매핑 (RDB의 PK와 동일하게 유지)
private Long id;
@Field(type = FieldType.Text, analyzer = "nori") // 한글 형태소 분석 적용
private String productName;
@Field(type = FieldType.Keyword) // 필터링, 정렬, 집계용
private String category;
@Field(type = FieldType.Keyword) // AI 필터링용 (ENDED 등)
private String auctionStatus;
@Field(type = FieldType.Long)
private Long finalPrice;
// ✅ AI 추천 핵심: 상품 설명을 벡터화하여 저장 (1536차원 예시)
@Field(type = FieldType.Dense_Vector, dims = 1536)
private float[] descriptionVector;
}
Spring Data JPA와 동일한 인터페이스 방식으로 검색 쿼리를 구현합니다.
@Repository
public interface ProductSearchRepository extends ElasticsearchRepository<ProductDocument, Long> {
// ✅ 키워드 검색
List<ProductDocument> findByProductNameContaining(String keyword);
// ✅ 카테고리 및 상태 필터 검색 (AI 추천 대상 추출 시 사용)
List<ProductDocument> findByCategoryAndAuctionStatus(String category, String status);
}
save() 메소드는 ID가 존재하지 않으면 생성, 존재하면 수정으로 동작합니다.
@Service
@RequiredArgsConstructor
public class SearchService {
private final ProductSearchRepository searchRepository;
public void indexProduct(ProductDocument doc) {
searchRepository.save(doc);
}
}
refresh_interval)이 발생할 수 있습니다. "방금 저장했는데 왜 검색이 안 되지?"는 오류가 아닙니다.- , _만 허용됩니다.