brunch

You can make anything
by writing

C.S.Lewis

by 에디의 기술블로그 Dec 26. 2018

Spring Reactive Elasticsearch

- 스프링 부트 환경에서 Elasticsearch 연동하기

이 글은, 엘라스틱서치(Elasticsearch) 에 대한 기본 개념을 정리하고 스프링 부트 환경에서 Elasticsearch를 연동하겠다. 참고로 Elasticsearch 는 필자가 거의 처음이다. 잘못된 내용이 포함될 수 있다. 이상한 내용이 있다면 피드백 해주길 바란다. 


Elasticsearch


필자가 Elasticsearch 를 잘 몰라서, 일단 Elasticsearch 가 뭔지 이해를 먼저 하기 위해서 Elasticsearch 설치, 특징 등 기본 개념을 먼저 정리하였다. 


Elasticsearch 설치


자세한 설치 과정은 생략한다. Elasticsearch 를 기본으로 설치하면 9200, 9300 두개의 포트가 바인딩된다. 9300포트는 Elasticsearch 의 기본 포트이고, Rest API 제공을 위해 기본으로 9200 포트가 바인딩한다. 필자는 포트 변경없이 그대로 9300, 9200 포트를 사용할 것이다.


Elasticsearch 특징


Elasticsearch는 NoSQL 기반의 검색엔진이다. 기존에 익숙한 RDBMS 와 Elasticsearch 용어를 비교하면 아래와 같다. 

요청 응답을 JSON 으로 주고 받을 수 있고, 개별 Document는 보통 "스키마리스" 하다고 부르는데, 스키마를 미리 정의하지 않아도 된다. 그래서 좀 더 유연하게 데이터를 구성할 수 있다. 


Elasticsearch Document, Index 생성


필자는 리눅스에서 Http 요청 테스트를 위해서, HTTPie 라는 툴을 사용하겠다. HTTPie 에 관련해서는 아래 링크를 참고하면 된다. 

https://httpie.org/

Elasticsearch는 인덱스를 미리 생성해도 되고, 안해도 된다. 필자는 아래와 같이 cafe 라는 인덱스(index)와 coffee 라는 타입(type) 을 동시에 생성하면서 하나의 Document 를 생성할 것이다. Document 에는 JSON 형식으로 {"title"="cappuccino", price="1500"} 를 입력할 것이다. HTTPie 를 사용해서 호출할 것이다. 

http POST localhost:9200/cafe/coffee/4 title=cappuccino price=1500

응답 결과는 아래와 같다.


Elasticsearch Document 조회


데이터를 조회해보자. URI 요청을 사용한 검색 API 는, 간단하게 파라미터와 쿼리 스트링으로 검색할 수 있다. 테스트 용도로 간단하게 사용하기 쉽다. 

참고 - https://d2.naver.com/helloworld/273788

자세한 내용은, 네이버 기술블로그를 참고하길 바란다. 

https://d2.naver.com/helloworld/273788


먼저,  검색 쿼리 없이 모든 데이터를 조회해보자. 

인덱스가 cafe 이고, 타입이 coffee 인 데이터를 모두 조회하면 아래와 같다. 

http GET http://localhost:9200/cafe/coffee/_search?


인덱스가 cafe 이고, 타입이 coffee 인 데이터 중에서!! title 이 latte or mocha 인 데이터를 조회하면 아래와 같다. q=title:latte,mocha 를 파라미터로 추가하면 된다.

http GET http://localhost:9200/cafe/coffee/_search?q=title:latte,mocha


정리


아주 기본적이지만, 필자가 전혀 모르는 내용들이라서 이번 기회에 간단하게 정리해봤다. 



Elasticsearch Query DSL


필자가 지금 공부 중이다. 나중에 따로 정리해서 글을 올릴 예정이다. 

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html


Spring 5 Webflux


필자가 예전에 작성한 글이 있는데, 이제는 추천하고 싶지가 않다. 그래도 아래와 같이 링크를 남겼다. 당시, 필자가 Webflux 를 급하게 공부하고 작성한 글이라서 깊이가 없다. 

https://brunch.co.kr/@springboot/96

카카오 기술블로그의 글을 참고하거나 Pivotal 의 projectreactor.io 를 방문해서 공부하길 바란다. 


레퍼런스

http://tech.kakao.com/2018/05/29/reactor-programming/

https://projectreactor.io/


대략적으로, Elastisearch, Spring Webflux 에 대해서 정리가 되었다. 혹시... Elasticsearch 를 한번도 사용해 본적이 없거나, Webflux 의 개념을 잘 모른다면 간단하게 공부를 하고 오길 바란다. 필자가 초보라서 설명이 매끄럽지가 못하다.  



Spring Data Elasticsearch


Spring Data Elasticsearch 프로젝트를 사용하면 Elasticsearch 를 좀 더 심플하게 사용할 수 있지만, 버전이슈가 있으니 꼭 확인하길 바란다. 


버전 이슈


스프링 부트 환경에서, Spring Data Elasticsearch 와 Elasticsearch 버전을 잘 맞춰야 한다. 아래 링크를 보자. 

https://github.com/spring-projects/spring-data-elasticsearch

필자가, Elasticsearch 를 최근에 설치를 하였다. 그래서, 6.5.3 버전을 사용 중인데, Spring Data 에서 지원하는 버전은 아래와 같다. 

오늘, 2018년 12월23일(일요일) 기준으로 Spring-Data-Elasticsearch 의 3.2 버전은 M1 버전까지 나온 상황인데, 당장 실무에서 사용하기 어려울것 같다. Spring Data Elasticsearch 를 제대로 사용하기 위해서는 Elasticsearch 를 다운그레이드 하는게 좋겠다고 생각했지만, 일단 이 글에서는 Spring Data 를 사용하지 않을 예정이다. Spring Data 프로젝트는 추후 프로젝트 진행하게 되는 시점에서 다시 검토하겠다. Spring Data 프로젝트에 대해서 궁금하다면 아래 필자의 글을 참고하자.


https://brunch.co.kr/@springboot/107



Spring Reactive Elasticsearch


스프링 부트 환경에서, Reactive 하게 Elasticsearch 를 연동하겠다. 일단, 위에서 소개한 Spring Data 를 사용하지 않겠다. 또한, Elasticsearch 에서 제공하는 기능이 매우 많다. 이 글에서는, 몇개만 선택해서 검토하겠다. 


기본 설정


build.gradle

필자는 스프링 부트 2.0.7.RELEASE, gradle, Java8를 사용할 것이다. 디펜던시는 아래와 같이 추가한다. 

필자가 사용하는 Elasticsearch 의 버전의 6.5.3 이라서, 라이브러리도 맞춰서 디펜던시를 추가하였다. 참고로, spring-data-elasticsearch 는 사용하지 않는다. 


config

필자는, RestHighLevelClient 를 사용하기 위해 아래와 같이 정의하였다.  

기존에 많이 사용하던, TransportClient 는 7.0.0 버전에서 Deprecated 되었고, 8.0.X 버전에서는 아예 제거가 될 것이다. Elasticsearch 최신 버전을 사용한다면 TransportClient 사용은 자제하는 것이 좋을 것이다. 하지만, 대부분의 개발자들이 TransportClient 를 아직 많이 사용하고 있으리라 생각이 된다.  TransportClient 로 설정할 때는 클러스터 이름을 설정했었지만, RestHighLevelClient 에서는 따로 설정하지 않아도 된다. 또한, Port 를 9200 포트로 설정한다. TransportClient를 사용할 때는 기본 9300 포트로 연동을 하였는데, RestHighLevelClient를 사용하면서 Elasticsearch Rest API 기본 포트인 9200 으로 연동을 한다. 스프링 부트가 실행이 될 때 자동으로 @Bean 을 생성을 하는데, 이때 커넥션 체크를 하지 않는다.(추측) 실제로 쿼리 요청을 실행하는 시점에서 커넥션을 맺는다. 참고로 기존에 TransportClient 를 사용할 때는 @Bean 를 생성하는 시점에서 커넥션을 맺는다. 참고로, 현재 2018년12월23일(일) 기준으로 Spring Data 의 마일스톤 버전으로 현재 개발중인 3.2.0.M1 버전의 레퍼런스 문서를 확인해보면 역시 TransportClient 에 대해서 아래와 같이 설명하고 있다. 

추가해서, 주저리주저리 설명을 추가하자면, Spring Data Elasticsearch 3.2.0.M1 버전의 레퍼런스에서는 ReactiveElasticsearchClient 라는 클래스를 제공하는데, Elasticsearch 라이브러리에서 제공하는 건 아니고, Spring-Data 에서 제공하는 매핑 클래스인것으로 확인이 된다. 어쨋든, Spring Data Elasticsearch 3.2.X 버전에서 좀 더 Reactive 한 구현이 가능하겠지만, 일단 필자는 Spring Data 는 사용하지 않을 예정이므로 이정도로 검토하고 넘어가겠다. 

org.springframework.data:spring-data-elasticsearch:3.2.0.M1

properties


정리

필자가 어제,오늘 검토해본 결과 스프링 환경에서 Elasticsearch 를 연동할 때 버전 이슈가 꽤 많은 것으로 확인이 되었다. 가능하면, 클라이언트 버전을 현재 사용하는 Elasticsearch 과 동일하게 맞추기를 바란다. 또한, 버전에 따라서 Client 연동하는 코드가 많이 다를 수 있다. 반드시 버전에 맞는 연동 방법으로 구현하길 바란다. 구글링을 통해서 찾은 코드로 애플리케이션을 실행해보면 바로 연동이 안될 가능성이 크다. 



Document 생성


코드 작성 - Service

Coffee 를 파라미터로 받아서, Elastisearch 에 저장하는 메서드를 구현하기 전에 인터페이스를 정의한다. 

인터페이스의 구현체인, ElasticsearchProvider 클래스에서 addDocument 메서드를 구현하자. 일단,  RestHighLevelClient 를 주입해야 한다. 참고로, restHighLevelClient 라는 Bean은 ElasticsearchConfig 클래스에서 생성한다.  

코드는 아래 공식 레퍼런스를 참고하여 작성하였다. 


코드 작성 - Controller

테스트 요청


레퍼런스

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-document-index.html



Document 검색


코드 작성 - Service

인터페이스에, title 로 검색을 하는 두개의 메서드를 정의한다. 

메서드를 구현하는, 구현체를 만들자.


searchTermQueryByTitle : 변수로 넘기는 title 값이, Elasticsearch 에 저장된 문서 중 title 필드에 일치하는 단어가 있으면, Document 를 리턴

searchMatchPhraseQueryByTitle : 변수로 넘기는 title 값이, Elasticsearch 에 저장된 문서 중 title 필드 전체 구문과 일치하면, Document 를 리턴


즉, Elasticsearch 에 title 에 iced 라는 단어가 포함되는 문서가 두개라고 가정해보자. 필자가 iced americano 라는 문서와 iced cafe latte 라는 문서 두개를 미리 넣어놨다. 

코드 작성 - Controller

title 에 iced 가 포함 된 문서를 모두 찾아보자. 위에 설명했듯이, searchTermQueryByTitle 메서드를 사용할 것이다. 간단하게 아래와 같이 요청을 해보면...

호출을 해보면 아래와 같이 데이터를 조회할 수 있다. 

이번에는, iced cafe latte 라는 타이틀이 전부 일치하는 문서를 검색해보자. 이번에는, 필자가 구현한 searchMatchPhraseQueryByTitle 메서드를 사용하면 된다. 

호출을 해보면 아래와 같이 데이터를 조회할 수 있다. 


샘플 코드는 아래 github 에서 확인하길 바란다. 

https://github.com/sieunkr/spring-reactive-elasticsearch


마무리


이 글에서는, 스프링 부트 환경에서 Elasticsearch 를 연동하였다. 주로 사용하던 Spring Data 프로젝트는 사용하지 않고, Elasticsearch 에서 제공하는 라이브러리를 직접 사용하였고, Spring Webflux 를 사용해서 비동기 프로세스로 작업을 하였다. 사실, 필자가 Elasticsearch 에 대해서 공부한지 하루이틀 밖에 되지 않았기 때문에 정확한 개념을 모르고 있다. Elasticsearch 의 색인, 매핑 등 아주 중요한 개념들에 대한 이해를 선행하지 않고, 이렇게 바로 연동을 해보는 일이 옳다고 생각하지는 않다. 시간이 부족해서 급하게 이렇게밖에 진행하지 못했지만, 조만간 Elasticsearch 의 매핑, 색인 등 기본적인 중요 개념에 대해서 따로 공부를 진행할 예정이다. 또한, 검색 쿼리가 매우 다양한데, 필자가 검토했던 몇개의 사례는 극히 일부일 뿐이다. 더 다양한 쿼리 조회 방법을 공부를 해야 할 것이다. 그럼. 이만 마치겠다. 


레퍼런스


https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-query-builders.html

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-search.html#java-rest-high-search

매거진의 이전글 Thread Dump 분석하기
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari