여러분이 당근마켓 같은 중고 거래 플랫폼을 만들었다고 가정해 봅시다. 데이터베이스(MySQL)에 등록된 상품 제목이 1,000만 개입니다. 사용자가 검색창에 "시원한 여름용 원피스"라고 검색했습니다. 일반적인 자바 개발자는 무심코 SELECT * FROM product WHERE title LIKE '%시원한 여름용 원피스%'라는 쿼리를 날립니다. 이 쿼리(퍼지 검색)는 인덱스(Index, 색인)를 타지 못하고 1,000만 개의 테이블 전체를 처음부터 끝까지 하나하나 스캔(Full Table Scan)해야 하므로 결과가 나오기까지 5초~10초가 걸리며 DB CPU가 터져버립니다. 게다가 사용자가 "여름 원피스"라고 띄어쓰기를 조금만 다르게 해도 결과가 0건으로 안 나옵니다! 관계형 데이터베이스(RDB)는 인간 언어의 '형태소'를 분석하는 '풀텍스트 검색(Full-Text Search)'에 태생적으로 치명적인 약점을 가지고 있습니다. 이 한계를 완벽하게 박살 내고 구글이나 네이버처럼 0.01초 만에 검색 결과를 뱉어내는 미친 속도의 전용 검색 엔진이 바로 Elasticsearch(엘라스틱서치)입니다.
이번 [Spring Boot 실무 완벽 가이드] 시리즈에서는 "초고속 검색 아키텍처의 필수품!" Elasticsearch의 역인덱스(Inverted Index) 원리와 Spring Data 연동 실무에 대하여 다뤄보겠습니다.

📖 1. Elasticsearch의 핵심: 역인덱스(Inverted Index)의 마법
책에서 특정 단어를 찾을 때, 첫 페이지부터 끝까지 다 읽는 바보는 없습니다. 맨 뒤에 있는 '찾아보기(색인, Index)' 페이지에서 단어를 찾아 그 옆에 적힌 페이지 번호를 폅니다. Elasticsearch는 모든 데이터를 저장할 때 이 '찾아보기 사전'을 미리 만들어 둡니다.

만약 1번 상품: "나이키 검정 원피스", 2번 상품: "시원한 여름 원피스"가 등록되면, 내장된 형태소 분석기가 글자를 다 찢어발겨서 다음과 같은 사전(역인덱스)을 만듭니다.
- 나이키 -> [1]
- 검정 -> [1]
- 원피스 -> [1, 2]
- 시원한 -> [2]
- 여름 -> [2]
이제 유저가 "원피스"를 검색하면? 테이블 전체를 뒤질 필요 없이, 그냥 사전에서 '원피스'를 찾아 그 옆에 있는 [1, 2]번 문서를 0.01초 만에 바로 던져줍니다! 이것이 엘라스틱서치가 미친 듯이 빠른 이유입니다.
⚙️ 2. Spring Data Elasticsearch 세팅과 Document 정의
스프링 부트 진영은 JPA와 완벽하게 똑같은 경험(인터페이스)을 제공하는 Spring Data Elasticsearch를 지원합니다. 개발자는 @Entity 대신 @Document만 달아주면 끝납니다.
// 1. 의존성 추가 (build.gradle)
implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
// 2. Document 클래스 생성 (JPA의 Entity와 똑같은 역할!)
@Getter
// indexName은 RDB의 Table 이름과 같습니다. (소문자 필수)
@Document(indexName = "products")
public class ProductDocument {
@Id
private String id; // 엘라스틱서치의 ID는 기본적으로 문자열(String) 타입입니다.
// 형태소 분석기를 적용하여 검색을 위해 단어를 쪼갤 필드 (Text)
@Field(type = FieldType.Text, analyzer = "nori")
private String title;
@Field(type = FieldType.Text)
private String description;
// 단순 필터링용(정렬, 통계) 필드 (Keyword - 쪼개지 않음)
@Field(type = FieldType.Keyword)
private String category;
}
🪄 3. JpaRepository와 똑같은 마법: ElasticsearchRepository
앞서 10단계에서 배웠던 Spring Data의 '메서드 이름으로 쿼리 생성(QueryMethod)' 마법이 엘라스틱서치에서도 100% 똑같이 동작합니다! 개발자는 복잡한 JSON 검색 쿼리(DSL)를 짤 필요가 없습니다.
public interface ProductSearchRepository extends ElasticsearchRepository<ProductDocument, String> {
// 🌟 메서드 이름만 적으면, 스프링이 알아서 엘라스틱서치 풀텍스트 검색 API(Match Query)를 호출해 줍니다!
// "title 필드 안에 keyword가 포함되어 있는 문서를 찾아줘!"
List<ProductDocument> findByTitleMatches(String keyword);
// 카테고리로 필터링하고 가격순 정렬까지!
List<ProductDocument> findByCategoryAndTitleMatchesOrderByPriceDesc(String category, String keyword);
}
※ 실무 아키텍처 꿀팁: CQRS 패턴
"그럼 이제 MySQL은 버리고 엘라스틱서치만 쓰면 되나요?" 절대 아닙니다. 엘라스틱서치는 검색엔진이지 트랜잭션(ACID)이나 무결성을 보장하는 데이터베이스가 아닙니다. 실무에서는 '저장/수정/결제(Command)'는 안전한 MySQL에서 처리하고, 상품이 등록될 때 Kafka(메시지 큐)나 Logstash를 통해 데이터를 엘라스틱서치로 동기화(복사)한 뒤, 프론트엔드의 '검색(Query)' 요청은 엘라스틱서치로 쏘는 CQRS(명령과 조회의 분리) 아키텍처를 구축하는 것이 글로벌 스탠다드입니다.
🎯 4. 마무리 및 다음 단계
지금까지 디스크를 벅벅 긁어대는 관계형 데이터베이스(RDB)의 끔찍한 LIKE 검색의 한계를 타파하고, 형태소 분석기와 역인덱스(Inverted Index)를 통해 포털 사이트 부럽지 않은 초고속 검색 기능을 앱에 장착해 주는 Elasticsearch와 Spring Data 연동 실무 아키텍처에 대해 아주 치밀하게 다루어 보았습니다. 이제 여러분의 서비스는 어떤 모호한 키워드가 입력되어도 0.01초 만에 답을 찾아낼 것입니다.
엘라스틱서치를 세팅해 둔 김에, 이 미친듯한 검색 능력을 다른 곳에 써먹을 수는 없을까요? 여러분이 MSA로 쪼개놓은 50대의 서버가 하루 100GB씩 뱉어내는 시커먼 로그(Log) 파일들을 생각해 봅시다. 어떤 에러가 났을 때 리눅스 서버 50대를 일일이 들어가서 grep 명령어로 에러 로그를 찾는 것은 미친 짓입니다. "50대 서버의 로그를 1초 만에 싹 다 흡수해서, 엘라스틱서치에 저장해 두고, 화려한 웹 대시보드(Kibana)에서 클릭 한 번으로 에러를 검색해 보자!" 이어지는 36단계 포스팅에서는 "전 세계 모든 백엔드 기업의 표준 로그 수집 인프라!" ELK 스택 (Elasticsearch, Logstash, Kibana) 기반의 중앙 집중형 로깅 파이프라인 구축 완벽 가이드에 대해 아주 뼈 때리게 파헤쳐 보겠습니다!
'Framework > Spring Boot' 카테고리의 다른 글
| [Spring Boot] Spring Cloud Gateway (0) | 2026.08.05 |
|---|---|
| [Spring Boot] ELK 스택 (Elasticsearch, Logstash, Kibana): 중앙 집중형 로그 파이프라인 (0) | 2026.08.05 |
| [Spring Boot] Spring Batch Chunk 지향 처리: 1,000만 건 메모리 최적화의 꽃 (0) | 2026.08.05 |
| [Spring Boot] Spring Batch 입문: 1,000만 건의 데이터를 씹어 삼키다 (0) | 2026.08.05 |
| [Spring Boot] STOMP와 RabbitMQ: 엔터프라이즈급 실시간 채팅의 완성 (0) | 2026.08.05 |