1 of 68

Elasticsearch를 이용한 검색 개발

검색은 어떻게 작동하는가

18 박성훈

1

MEGACON 2023

2 of 68

1. 검색

2. Elasticsearch

3. Spring과 Elasticsearch

4. 기존 서비스에 검색엔진을 도입하기 위한 방법

2

MEGACON 2023

- 발표할 주제 -

3 of 68

검색

3

검색엔진이란

MEGACON 2023

검색설정

검색이란

김동현

구글

고려거란전쟁

4 of 68

4

MEGACON 2023

5 of 68

5

MEGACON 2023

6 of 68

6

MEGACON 2023

내가 운영하는 웹 사이트에 검색 기능을 넣고 싶다면?

7 of 68

7

MEGACON 2023

8 of 68

검색

검색어를 입력하면 그 단어에 적합한 내용이

담겨있는 자료를 데이터베이스 상에서 찾는 것

8

MEGACON 2023

9 of 68

9

MEGACON 2023

어떤 한 쇼핑몰에서 "나이키" 라는 단어를

포함하고 있는 상품 목록을 구하려면?

10 of 68

10

MEGACON 2023

SELECT * FROM 상품

WHERE 상품명 LIKE '%나이키%'

  • 모든 상품에 대해 "나이키" 가 포함된 상품명 조회 쿼리가 발생한다.
  • 하루에 수만개의 상품들이 등록된다.
  • 초당 수천명이 주기적으로 검색한다.

수백만 건의 데이터에 대해 이러한 검색 쿼리로 조회한다면?

11 of 68

11

MEGACON 2023

SELECT * FROM 상품

WHERE 상품명 LIKE '%나이키%'

  • LIKE '%나이키%' (그리고 LIKE '%나이키') 는 인덱스를 타지 않는다
  • LIKE '나이키%' 를 사용하면 검색 품질이 현저히 떨어진다.

12 of 68

12

MEGACON 2023

역 인덱스, Inverted Index

문서의 각 단어들을 추출하여

단어에 해당하는 문서들을 기록

단어(term)

Document id

메가브레인

1, 2, 3

최고

동아리

1, 2

1, 3

text

Document id

1

최고 동아리 메가브레인

2

3

메가브레인 최고

메가브레인 동아리

역 인덱스 생성

13 of 68

13

MEGACON 2023

역 인덱스 성능

'동아리'라는 단어가 포함된 문서를 검색한다면

단어(term)

Document id

메가브레인

1, 2, 3

최고

동아리

1, 2

1, 3

text

Document id

1

최고 동아리 메가브레인

2

3

메가브레인 최고

메가브레인 동아리

테이블 검색 O(n)

역 인덱스 검색 O(1)

14 of 68

14

MEGACON 2023

Term은 어떻게 만들어지는가?

- 검색엔진*은 특정 문서에서 여러 키워드로 쪼갠다.

- 문서를 term으로 나누는 것을 텍스트 분석 또는 처리한다고 한다

"Megabrain has the best technology in gimhae."

"There are several universities in Gimhae."

* 컴퓨터 시스템에 저장된 정보를 찾아주거나 웹 검색을 도와주도록 설게된 시스템 또는 프로그램

15 of 68

15

MEGACON 2023

Term은 어떻게 만들어지는가?

"Megabrain has the best technology in gimhae."

"There are several universities in Gimhae."

Token (term)

Doc

Token (term)

Doc

Megabrain

1

has

the

best

technology

in

There

1

1

1

1

1

2

are

2

1. 공백을 기준으로 텍스트를 쪼갠다.

several

2

universities

2

gimhae

2

gimhae

1

in

2

16 of 68

16

MEGACON 2023

Term은 어떻게 만들어지는가?

"Megabrain has the best technology in gimhae."

"There are several universities in Gimhae."

2. 대소문자를 소문자로 변환한다.

Token (term)

Doc

Token (term)

Doc

megabrain

1

has

the

best

technology

in

there

1

1

1

1

1

2

are

2

several

2

universities

2

gimhae

2

gimhae

1

in

2

17 of 68

17

MEGACON 2023

Term은 어떻게 만들어지는가?

"Megabrain has the best technology in gimhae."

"There are several universities in Gimhae."

3. 불용어*(stopword)를 제거한다.

*분석에 큰 의미가 없는 단어 (the, is, a, in, my 등)

Token (term)

Doc

Token (term)

Doc

megabrain

1

has

the

best

technology

in

there

1

1

1

1

1

2

are

2

several

2

universities

2

gimhae

2

gimhae

1

in

2

18 of 68

18

MEGACON 2023

Term은 어떻게 만들어지는가?

"Megabrain has the best technology in gimhae."

"There are several universities in Gimhae."

4. 형태소 분석 과정을 거친다.

Token (term)

Doc

Token (term)

Doc

megabrain

1

best

technology

1

1

several

2

university

2

gimhae

2

gimhae

1

19 of 68

19

MEGACON 2023

Term은 어떻게 만들어지는가?

"Megabrain has the best technology in gimhae."

"Gimhae has the best university."

5. 중복된 token을 병합한다

Token (term)

Doc

Token (term)

Doc

megabrain

1

best

technology

1

1

several

2

university

2

gimhae

1, 2

20 of 68

20

MEGACON 2023

검색어도 동일하게 텍스트 분석한다.

"Is MegaBrain located in Gimhae?"

megabrain

locate

Doc

1

"Megabrain has the best technology in gimhae."

gimhae

"inje university located in gimhae"

2

Text

1

2

1, 2

21 of 68

21

MEGACON 2023

Elasticsearch

최신 릴리즈 : 8.11.1

컨트리뷰터 : 1,886

github stars : 66K

주요 구성 언어 : Java

라이센스 : Apache 2.0

출시일 : 2010년 2월 8일

Elastic Cloud Enterprise 기술 지원

"가장 대중적인 루씬 기반의 Java 오픈소스 분산 검색 엔진"

  • RESTFul 기반 APIs, 간단한 HTTP 인터페이스 제공
  • Scheme-Free JSON 문서를 사용한 데이터 저장 및 제공
  • 클러스터 분산을 이용한 대용량 트래픽, 데이터 병렬 처리
  • 무료 도구 및 플러그인 : 시각화 분석 도구 Kibana 제공, Beats 및 Logstash 통합으로 여러 데이터 로드
  • 다양한 언어 지원 : Java, Python, PHP, Javascript, Node.js, Ruby 등

이점 및 핵심

주요 사용 사례

  • 미국 승차 공유 서비스 Uber
  • 온라인 교육 플랫폼 Udemy
  • 깃 저장소 호스팅 서비스 Github
  • StackOverflow, Slack
  • 배달 플랫폼 Yogiyo
  • 국내 쇼핑물 쿠팡, 위메프, 무신사 등

22 of 68

22

MEGACON 2023

RESTFul APIs 제공, 시각화 대시보드 Kibana

23 of 68

23

MEGACON 2023

Scheme-Free JSON 문서

Scheme

24 of 68

24

MEGACON 2023

핵심 용어

indexing (색인)

원본 데이터

Index (인덱스)

Search (검색)

Query (질의)

25 of 68

25

MEGACON 2023

RDBMS 와 용어 비교

Elasticsearch

RDBMS

Index

Database

Document Type

Table

Document

Row

Field

Column

26 of 68

26

MEGACON 2023

시스템 구조 - 클러스터 구성

node 1

클라이언트

node 2

...

node N

서버

http : 9200

tcp: 9300

http : 9201

tcp: 9301

http : 92XN

tcp: 93XN

http 통신

27 of 68

27

MEGACON 2023

시스템 구조 - 클러스터 구성

node 1

클라이언트

node 2

...

node N

서버 1

http : 9200

tcp: 9300

http : 9201

tcp: 9301

http : 92XN

tcp: 93XN

http 통신

서버 N

28 of 68

28

MEGACON 2023

시스템 구조 - 인덱스와 샤드

도큐먼트 1

도큐먼트 N

...

인덱스

data1

data1

도큐먼트 : 단일 데이터 단위

도큐먼트 1

도큐먼트 N

...

인덱스

data1

data1

샤드 : 인덱스를 작은 단위로 분리한 것

샤드 1

샤드 2

샤드 N

인덱스 : 도큐먼트의 집합

29 of 68

29

MEGACON 2023

시스템 구조 - 인덱스와 샤드

Node 1

0

Node 2

1

Node 3

2

Node 4

3

Node 5

4

Primary Shard

0

Replica

  • 각 노드별로 단일 데이터(샤드)가 분산 저장
  • 주 샤드를 복제한 레플리카도 분산 저장

1

2

3

4

30 of 68

30

MEGACON 2023

Node 1

0

Node 2

1

Node 3

2

Node 4

3

Node 5

4

0

  • Node 3 이 시스템 다운이나 네트워크 이슈로 인해 작동 불능 시
  • 복제본이 사라져 1개만 남은 3번, 2번 샤드들을 복제

1

2

3

4

3

2

시스템 구조 - 인덱스와 샤드

주 샤드로 승격

샤드 복제

31 of 68

31

MEGACON 2023

시스템 구조 - 마스터 노드와 데이터 노드

Node 2

0

Node 1

1

Node 0

2

Node 3

Node 4

4

0

  • 마스터 노드 : 클러스터 상태 정보*를 관리하는 노드
  • 데이터 노드 : 인덱스된 데이터를 저장하고 있는 노드

1

3

4

3

2

*인덱스의 메타 데이터, 샤드의 위치 등

마스터 노드

32 of 68

32

MEGACON 2023

node-1

(master)

node-4

(data)

node-5

(data)

node-3

(master)

node-6

(data)

node-2

(master)

기본적인 클러스터 구조

시스템 구조 - 마스터 노드와 데이터 노드

33 of 68

33

MEGACON 2023

Spring과 Elasticsearch

34 of 68

34

MEGACON 2023

Spring과 Elasticsearch

- JDK 17

- Spirng Boot 3.1.5

- Spring Data JPA

- Spring Data Elasticsearch

- Elasticsearch (단일 노드)

- H2 Database

예제 프로젝트 구성

35 of 68

35

MEGACON 2023

Spring과 Elasticsearch

36 of 68

36

MEGACON 2023

Spring과 Elasticsearch

37 of 68

37

MEGACON 2023

Spring과 Elasticsearch

Controller

Service

Repository

Post Entity

Post Document

38 of 68

38

MEGACON 2023

Spring과 Elasticsearch

Post Entity

39 of 68

39

MEGACON 2023

Spring과 Elasticsearch

Post Document

40 of 68

40

MEGACON 2023

Spring과 Elasticsearch

41 of 68

41

MEGACON 2023

Spring과 Elasticsearch

42 of 68

42

MEGACON 2023

Spring과 Elasticsearch

43 of 68

43

MEGACON 2023

Spring과 Elasticsearch

44 of 68

44

MEGACON 2023

Spring과 Elasticsearch

45 of 68

45

MEGACON 2023

Spring과 Elasticsearch

Post 생성 API

Post 검색 API

46 of 68

46

MEGACON 2023

기존 서비스에 검색엔진을 도입하기 위한 방법

47 of 68

47

MEGACON 2023

기존 서비스에 검색엔진을 도입하기 위한 방법

RDBMS를 기존에 운영 중일 때

  • 기존 데이터들은 검색엔진에 저장되어야 한다.
  • 새로운 데이터가 RDB에 저장되면 검색 시 데이터가 조회되어야 한다.

MySQL 과 Elasticsearch를 동기화하는게 중요

1. 서비스 코드 단에서 MySQL 저장과 ES 저장 코드를 작성한다.

2. SQL 코드를 작성해서 주기적으로 데이터를 ES 에 저장한다.

48 of 68

48

MEGACON 2023

기존 서비스에 검색엔진을 도입하기 위한 방법

49 of 68

49

MEGACON 2023

"다양한 소스로 부터 데이터를 수집하고 변환하고 전송하는 데이터 처리 파이프라인 (ETL)"

Logstash

Elasticsearch

- RDB가 이미 운영되고 있는 서비스에 ES 도입할때 적합하다.

- 주기적으로 동기화 되면서 중복 데이터가 발생할 수 있다.

기존 서비스에 검색엔진을 도입하기 위한 방법

50 of 68

50

MEGACON 2023

Logstash

필요한 구성

- JDBC Input Plugin

- Mysql J Connector

기존 서비스에 검색엔진을 도입하기 위한 방법

51 of 68

51

MEGACON 2023

pipeline.yaml : input, filter, output 구성을 작성

기존 서비스에 검색엔진을 도입하기 위한 방법

52 of 68

52

MEGACON 2023

input {

}

filter {

}

output {

}

pipeline.conf

기존 서비스에 검색엔진을 도입하기 위한 방법

53 of 68

53

MEGACON 2023

input {

// mysql 데이터

}

filter {

// 데이터 처리

}

output {

// elasticsearch 로 전송

}

pipeline.conf

기존 서비스에 검색엔진을 도입하기 위한 방법

54 of 68

54

MEGACON 2023

input {

jdbc {

jdbc_driver_library => "mysql-connector-java-8.0.33.jar"

jdbc_driver_class => "com.mysql.cj.jdbc.Driver"

jdbc_connection_string => "jdbc:mysql://localhost:3306/db"

jdbc_user => "root"

jdbc_password => "root"

schedule => "* * * * *"

statement => "SELECT * FROM post"

}

}

1분마다 statement 쿼리를 실행해 데이터를 조회

기존 서비스에 검색엔진을 도입하기 위한 방법

55 of 68

55

MEGACON 2023

filter {

mutate {

copy => { "post_id" => "[@metadata][_id]"

remove => [ "post_id" ]

}

}

유의미한 데이터를 추출하거나 처리한다.

기존 서비스에 검색엔진을 도입하기 위한 방법

56 of 68

56

MEGACON 2023

output {

elasticsearch {

hosts => ["localhost:9200"]

user => "elastic"

password => "..."

ssl_enabled => true

index => "post"

document_id => "%{[@metadata][_id]}"

}

}

가공한 데이터를 검색엔진으로 보낸다.

기존 서비스에 검색엔진을 도입하기 위한 방법

57 of 68

57

MEGACON 2023

기존 서비스에 검색엔진을 도입하기 위한 방법

58 of 68

58

MEGACON 2023

input {

jdbc {

jdbc_driver_library => "mysql-connector-java-8.0.33.jar"

jdbc_driver_class => "com.mysql.cj.jdbc.Driver"

jdbc_connection_string => "jdbc:mysql://localhost:3306/db"

jdbc_user => "root"

jdbc_password => "root"

schedule => "* * * * *"

statement => "SELECT * FROM post"

}

}

기존 서비스에 검색엔진을 도입하기 위한 방법

59 of 68

59

MEGACON 2023

post_id

content

updated_time

1

2

abcd

hi

2023-12-04 15:00

2023-12-04 15:05

1000

mega

2023-12-04 17:05

...

SELECT * FROM post

기존 서비스에 검색엔진을 도입하기 위한 방법

60 of 68

60

MEGACON 2023

post_id

content

updated_time

1

2

abcd

hi

2023-12-04 15:00

2023-12-04 15:05

1040

mega40

2023-12-04 17:10

...

SELECT * FROM post

기존 서비스에 검색엔진을 도입하기 위한 방법

61 of 68

61

MEGACON 2023

post_id

content

updated_time

1

2

abcd

asdgd1123

2023-12-04 15:00

2023-12-04 17:10

1000

mega

2023-12-04 17:05

...

SELECT * FROM post

기존 서비스에 검색엔진을 도입하기 위한 방법

62 of 68

62

MEGACON 2023

SELECT *, UNIX_TIMESTAMP(updated_time) AS unix_ts_in_secs

FROM post

WHERE UNIX_TIMESTAMP(updated_time) > :sql_last_value

AND updated_time < NOW()

SELECT * FROM post

기존 서비스에 검색엔진을 도입하기 위한 방법

63 of 68

63

MEGACON 2023

post_id

content

updated_time

1

2

abcd

hi

2023-12-04 15:00

2023-12-04 15:05

1000

mega

2023-12-04 17:05

...

SELECT *, UNIX_TIMESTAMP(updated_time) AS unix_ts_in_secs

FROM post

WHERE UNIX_TIMESTAMP(updated_time) > :sql_last_value

AND updated_time < NOW()

기존 서비스에 검색엔진을 도입하기 위한 방법

64 of 68

64

MEGACON 2023

post_id

content

updated_time

1

2

abcd

hi

2023-12-04 15:00

2023-12-04 15:05

1010

새로운글!

2023-12-04 17:07

...

SELECT *, UNIX_TIMESTAMP(updated_time) AS unix_ts_in_secs

FROM post

WHERE UNIX_TIMESTAMP(updated_time) > :sql_last_value

AND updated_time < NOW()

1000

mega

2023-12-04 17:05

기존 서비스에 검색엔진을 도입하기 위한 방법

65 of 68

65

MEGACON 2023

post_id

content

updated_time

1

2

abcd

수정

2023-12-04 15:00

2023-12-04 17:10

1000

mega

2023-12-04 17:05

...

SELECT *, UNIX_TIMESTAMP(updated_time) AS unix_ts_in_secs

FROM post

WHERE UNIX_TIMESTAMP(updated_time) > :sql_last_value

AND updated_time < NOW()

기존 서비스에 검색엔진을 도입하기 위한 방법

66 of 68

66

MEGACON 2023

input {

jdbc {

...

statement => "SELECT *, UNIX_TIMESTAMP(updated_time) AS unix_ts_in_secs

FROM post

WHERE UNIX_TIMESTAMP(updated_time) > :sql_last_value

AND updated_time < NOW()"

use_column_value => true

tracking_column => unix_ts_in_secs

tracking_column_type => "numeric"

last_run_metadata_path => "/usr/share/logstash/data/last-run"

}

}

기존 서비스에 검색엔진을 도입하기 위한 방법

67 of 68

67

MEGACON 2023

기존 서비스에 검색엔진을 도입하기 위한 방법

68 of 68

감사합니다�QnA

68

MEGACON 2023

현업 수준의 기술력은 김해 유일 Megabrain