애플리케이션의 데이터가 커질수록 복잡한 검색 기능이 필요해집니다. 데이터베이스의 LIKE 검색만으로는 성능이 한계에 부딪히며, 특히 로그, 상품, 문서, 사용자 검색 같은 기능은 Elasticsearch를 통해 훨씬 빠르고 유연하게 구현할 수 있습니다.
Elasticsearch란?
Elasticsearch는 JSON 기반의 분산형 검색·분석 엔진으로, 실시간으로 대량의 데이터를 색인(Indexing)하고 빠르게 검색할 수 있습니다. Lucene을 기반으로 하며, 역색인(Inverted Index) 구조를 사용하여 텍스트 검색에 특화되어 있습니다.
- 대량의 데이터 검색에 탁월 (ms 단위 검색)
- RESTful API 기반 — HTTP 요청으로 데이터 CRUD 가능
- Spring Data Elasticsearch로 손쉽게 연동
- Kibana, Logstash 등과 함께 ELK Stack을 구성 가능
1. Elasticsearch 환경 준비
Docker로 Elasticsearch 실행
docker run -d \
--name elasticsearch \
-p 9200:9200 \
-e "discovery.type=single-node" \
docker.elastic.co/elasticsearch/elasticsearch:8.12.2
기본 포트는 9200이며, 브라우저에서 http://localhost:9200으로 접속해 실행 여부를 확인할 수 있습니다. 출력에 "tagline" : "You Know, for Search"가 나타나면 정상적으로 실행된 것입니다.
2. Spring Boot 프로젝트 설정
Gradle 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
Spring Data Elasticsearch는 Elasticsearch 클라이언트를 추상화하여, JPA와 유사한 방식으로 문서를 다룰 수 있게 해줍니다.
application.yml 설정
spring:
data:
elasticsearch:
cluster-nodes: localhost:9200
repositories:
enabled: true
elasticsearch:
uris: http://localhost:9200
버전에 따라 spring.data.elasticsearch.cluster-nodes 대신 spring.elasticsearch.uris를 사용하는 것이 일반적입니다. Elasticsearch 8 이상에서는 보안(SSL, 인증)이 활성화되어 있으므로, 필요 시 인증 비활성화 옵션을 설정하거나 API 키를 등록해야 합니다.
3. 도메인(Document) 정의
JPA의 Entity처럼 Elasticsearch에서도 데이터를 저장할 모델을 정의합니다.
@Document(indexName = "products")
public class Product {
@Id
private String id;
private String name;
private String description;
private double price;
@Field(type = FieldType.Keyword)
private String category;
// getters and setters
}
@Document 어노테이션은 Elasticsearch 인덱스 이름을 지정합니다. @Field를 이용하면 검색 필드 타입을 제어할 수 있습니다 (text, keyword, date 등).
4. Repository 정의
public interface ProductRepository extends ElasticsearchRepository<Product, String> {
List<Product> findByNameContaining(String name);
List<Product> findByCategory(String category);
}
Spring Data Elasticsearch는 메서드 네이밍 규칙을 기반으로 자동으로 쿼리를 생성합니다. 예를 들어, findByNameContaining("Phone")은 name 필드에 “Phone”이 포함된 문서를 검색합니다.
5. Controller 작성
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/products")
public class ProductController {
private final ProductRepository productRepository;
@PostMapping
public Product save(@RequestBody Product product) {
return productRepository.save(product);
}
@GetMapping("/search")
public List<Product> search(@RequestParam String name) {
return productRepository.findByNameContaining(name);
}
}
이제 POST /api/products 요청으로 데이터를 색인하고, GET /api/products/search?name=키워드로 검색할 수 있습니다.
6. REST API로 직접 테스트
Elasticsearch는 자체 REST API를 제공하므로, 직접 호출로 테스트할 수도 있습니다.
# 문서 색인
curl -X POST "localhost:9200/products/_doc/1" -H 'Content-Type: application/json' -d'
{
"name": "Galaxy S24",
"description": "Samsung flagship smartphone",
"price": 1200000,
"category": "mobile"
}
'
# 검색
curl -X GET "localhost:9200/products/_search?q=name:Galaxy"
Spring Boot 내부에서도 같은 요청이 Repository를 통해 수행됩니다.
7. 고급 검색 기능 구현
Spring Data Elasticsearch에서는 NativeSearchQueryBuilder를 통해 복합 쿼리를 작성할 수 있습니다.
SearchHits<Product> search = elasticsearchOperations.search(
new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("name", "Galaxy"))
.filter(QueryBuilders.rangeQuery("price").lte(1500000)))
.build(),
Product.class
);
이 코드는 “Galaxy”라는 키워드를 포함하면서 150만원 이하의 상품만 필터링하는 복합 검색을 수행합니다.
8. Elasticsearch 운영 시 고려사항
- Index Mapping 관리: 인덱스 생성 시 스키마를 명확히 정의해야 불필요한 매핑 충돌 방지
- Analyzer 설정: 한국어 검색 시 NoriAnalyzer, 형태소 분석기 활용
- Cluster 모니터링: Kibana, ElasticHQ, X-Pack으로 노드 상태 점검
- 성능 최적화: shard 개수, replica 수 조정 / refresh interval 관리
- 보안: Elastic 8.x 이상에서는 기본적으로 TLS와 인증이 활성화되어 있으므로 API Key 또는 SSL 설정 필요
9. Kibana를 통한 시각화
Kibana를 설치하면 Elasticsearch 데이터를 대시보드로 시각화할 수 있습니다.
docker run -d \
--name kibana \
-p 5601:5601 \
--link elasticsearch:elasticsearch \
docker.elastic.co/kibana/kibana:8.12.2
Kibana의 Dev Tools에서 인덱스, 매핑, 쿼리를 직접 실행하면서 결과를 시각적으로 확인할 수 있습니다.
주의할 점
- Elasticsearch 버전과 Spring Data Elasticsearch 버전을 반드시 호환시켜야 함
- 대용량 색인 시 Bulk API 사용으로 성능 향상
- 운영 환경에서는 Replica = 1 이상으로 설정해 데이터 안정성 확보
- 필드 타입 자동 매핑(“dynamic mapping”)은 의도치 않은 매핑 오류를 유발할 수 있으므로 주의
Spring Boot와 Elasticsearch를 연동하면 단순한 CRUD를 넘어 고성능 검색 서비스를 구현할 수 있습니다. 특히 JPA와 병행하여 사용하면 데이터 저장은 DB, 검색은 Elasticsearch로 분리해 성능과 확장성을 모두 확보할 수 있습니다.
'개발 > JAVA' 카테고리의 다른 글
| DDD(Domain Driven Design)와 Spring 적용 — 복잡한 비즈니스를 코드로 명확하게 표현하기 (0) | 2025.11.16 |
|---|---|
| 대규모 트래픽을 위한 캐싱 전략 — 성능과 안정성을 동시에 잡는 방법 (0) | 2025.11.15 |
| Spring Boot와 AWS S3 파일 저장하기 - 안전하고 확장 가능한 파일 스토리지 구축 (0) | 2025.11.13 |
| Spring Boot와 AWS RDS 연동하기 - 안정적인 클라우드 데이터베이스 환경 구축 (0) | 2025.11.12 |
| Spring Boot와 Jenkins CI/CD 파이프라인 구축 - 자동화된 배포 환경 만들기 (0) | 2025.11.11 |
