(멋쟁이사자처럼_백엔드스쿨플러스) Day15 엘라스틱 서치
엘라스틱 서치
검색 알고리즘
1세대
- Sql의 like 연산자를 활용하여 검색
- 모든 컬럼의 값을 확인해야 하므로 검색 속도가 느림
1
2
3
4
5
6
SELECT * FROM post WHERE (
subject LIKE '%검색어%'
OR
content LIKE '%검색어%'
)
AND createdDate BETWEEN '2025-01-01' AND '2025-01-31';
2세대(해시태그)
- 중간에 브릿지 테이블을 만들어 검색어를 index화
- 중간 테이블을 직접 만들어야 한다.
- 해시태그와 같이 미리 테이블을 만들 경우 사용한다.
1
2
3
4
5
6
7
SELECT P.*
FROM postKeyword AS PK
INNER JOIN postTag AS PT
ON PK.id = PT.postKeywordId
INNER JOIN post AS P
ON P.id = PT.postId
WHERE PK.content = '검색어'
3세대(엘라스틱 서치)
- 엘라스틱 서치를 사용하여 검색
- 모든 단어를 index화하여 별도의 테이블에 저장한다.
- 모든 테이블을 검색하지 않아 검색속도가 빠르다.
엘라스틱 서치의 특징
- RESTful API를 통한 검색엔진
- 대용량 데이터 처리
- 실시간 검색
- 분산처리
엘라스틱 서치의 구성
클러스터의 구성요소
Document, Index, 노드
Document
- 단일 데이터의 단위를 document라고 한다.
관계형 DB의 row와 같은 개념
1 2 3 4 5 6
{ // Document 1 - 첫 번째 책 "id": "book1", "title": "해리포터와 마법사의 돌", "category": "판타지" }
index
- 도큐먼트의 집합
- 관계형 DB의 daatabase와 같은 개념
- 데이터를 저장하는 공간
하나의 인덱스가 여러 노드에 분산저장
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// books (Index) - 책들의 집합 { // Document 1 - 첫 번째 책 "id": "book1", "title": "해리포터와 마법사의 돌", "category": "판타지" } { // Document 2 - 두 번째 책 "id": "book2", "title": "해리포터와 비밀의 방", "category": "판타지" } { // Document 3 - 세 번째 책 "id": "book3", "title": "해리포터와 아즈카반의 죄수", "category": "판타지" }
Shard
index와 shard의 관계
엘라스틱 서치의 저장과정
Elasticsearch(검색에 최적화된 데이터 공간, DB)
- ELK에서 가장 중요한 역할을 하는 엘라스틱 서치
- 데이터를 저장하고 검색하는 역할
- 데이터를 저장할 때, 데이터를 index화하여 저장
- 데이터를 검색할 때, index화된 데이터를 검색하여 결과를 반환
Logstash(데이터동기화, 파이프라인)
- 다양한 소스에서 데이터를 수집하고, 변환하여 엘라스틱 서치에 전달
- DB에 저장된 데이터를 엘라스틱 서치에 전달하는 역할
Kibana의(데이터 시각화)
- 엘라스틱 서치에 저장된 데이터를 시각화하여 보여주는 역할
엘라스틱 서치 구동하고 접속하기
기본 프로젝트 구성
- 기본 프로젝트 구성을 한다.
Docker-compose.yml 파일 작성
- DockerCompose는 스프링부트가 실행될때 실행된다.
elasticsearch image를 넣고 실행 되면 elasticsearch가 실행된다.
1 2 3 4 5 6 7 8 9
services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.3.3 container_name: elasticsearch environment: - discovery.type=single-node - xpack.security.enabled=false ports: - "9200:9200"
Document, Repository, Service 생성
Entity와 유사한 방식으로 Document객체를 정의한다.
1 2 3 4 5 6 7 8 9 10 11
@Document(indexName="app1_posts") // indexName은 데이터베이스명 @Getter @Setter @Builder public class PostDoc { @Id private String id; private String title; private String content; }
Repository를 생성한다. 이때 JPARepository가 아닌 ElasticsearchRepository를 상속받는다.
1 2
public interface PostDocRepository extends ElasticsearchRepository<PostDoc, String> { }
Service 생성
Service단에서 Repository를 주입받아서 사용한다.
1 2 3 4 5 6 7 8 9
@Service @RequiredArgsConstructor public class PostDocService { private final PostDocRepository postDocRepository; public PostDoc save(PostDoc postDoc) { return postDocRepository.save(postDoc); } }
Elasticsearch 서버 접근 하기
- elasticsearch는 기본적으로 9200포트로 접속한다.
- localhost:9200으로 접속하여 확인한다.
elasticsearch는 RESTful API를 사용하여 데이터를 주고 받는다.
GET /_cat/indices : 모든 인덱스 목록 조회
GET /_search : 모든 인덱스에서 검색
GET /{인덱스명}/_search : 특정 인덱스에서 검색 * 예제에서는 app1_posts
PUT /{인덱스명} : 인덱스 생성
DELETE /{인덱스명} : 인덱스 삭제
POST /{인덱스명}/_doc : 문서 생성(ID 자동생성)
PUT /{인덱스명}/_doc/{ID} : 문서 생성(ID 지정)
GET /{인덱스명}/_doc/{ID} : 문서 조회
DELETE /{인덱스명}/_doc/{ID} : 문서 삭제
데이터를 조회하기
데이터를 조회하기 위해서는 API요청에 Json형식으로 Body에 담아 데이터를 전달한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
{ "query": { "match_all": {} } } # 검색어가 포함된 모든 문서 검색 { "query": { "match": { "title": "검색어" } } }
데이터 저장 및 조회 구조
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.