Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

RediSearch 2.0 시작하기: Redis 데이터베이스에서 강력한 검색 엔진 활용하기

RediSearch 2.0이 공개 프리뷰로 출시되었습니다! 이번 메이저 릴리스의 대부분의 기능은 사용자 여러분의 피드백을 바탕으로 개발되었으며, 개발자 경험 향상과 확장성 개선에 중점을 두었습니다. 이 글에서는 RediSearch 2.0의 새로운 데이터 인덱싱 기능과 인덱스를 생성하는 더 나은 방법을 중심으로 시작하는 방법을 안내합니다.

Redis 데이터베이스 안에 풍부한 쿼리 및 집계 엔진을 갖추면 캐싱을 넘어 다양한 새로운 애플리케이션의 문이 열립니다. 복잡한 쿼리로 데이터에 접근해야 하는 경우에도 데이터를 갱신하고 인덱싱하기 위한 복잡한 코드를 추가할 필요 없이 Redis를 주요 데이터베이스로 활용할 수 있습니다. 그것도 Redis 특유의 빠른 속도, 안정성, 확장성을 그대로 누리면서 말입니다!

새로운 기능에 대한 자세한 내용은 'Introducing RediSearch 2.0' 소개글을 참고하세요.

시작하기

사전 준비 사항

RediSearch 2.0을 시작하려면 다음 항목이 필요합니다.

  • Docker
  • Redis 명령줄 인터페이스(CLI). 크게 두 가지 옵션이 있습니다.
    • Redis에 기본 포함된 redis-cli
    • RedisInsight — Redis 애플리케이션 개발을 간소화해주는 무료 GUI 도구로, 명령줄 인터페이스도 함께 제공됩니다.

RediSearch가 활성화된 Redis 데이터베이스 준비

RediSearch 2.0은 다양한 방식으로 설치하여 사용할 수 있습니다.

  • Redis Enterprise Cloud
  • Redis Enterprise Software
  • RediSearch 바이너리
  • RediSearch 소스 코드
  • Docker 이미지

이 글에서는 설명의 편의를 위해 Docker 이미지를 사용합니다. (이미 RediSearch 2.0을 설치했다면 다음 섹션으로 건너뛰어도 좋습니다.) Docker로 Redis 인스턴스를 시작하려면 터미널을 열고 아래 명령어를 실행하세요.

> docker run -it --rm --name redis-search-2 \
   -p 6379:6379 \
   redis/redisearch:2.0.0

참고: 컨테이너는 종료 시 자동으로 삭제됩니다(–rm 파라미터).

Redis에 연결하고 데이터 삽입하기

선호하는 Redis 클라이언트를 사용해 RediSearch 데이터베이스에 연결합니다.

Docker로 Redis 인스턴스를 실행했다면 다음 명령어로 컨테이너에 내장된 redis-cli를 사용할 수 있습니다.

> docker exec -it redis-search-2 redis-cli

RedisInsight를 사용하려면 RediSearch 인스턴스를 추가한 뒤 CLI 화면으로 이동하면 됩니다.

데이터 삽입

이제 데이터를 삽입할 차례입니다. 이 예제에서는 Redis Hash 형태로 저장된 영화 데이터를 사용하므로, 몇 편의 영화를 삽입해 보겠습니다.

> HSET movie:11002 title "Star Wars: Episode V - The Empire Strikes Back" plot "Luke Skywalker begins Jedi training with Yoda." release_year 1980 genre "Action" rating 8.7 votes 1127635

(integer) 6

> HSET movie:11003 title "The Godfather" plot "The aging patriarch of an organized crime dynasty transfers control of his empire to his son." release_year 1972 genre "Drama" rating 9.2 votes 1563839

(integer) 6

이제 데이터베이스에는 두 개의 Hash가 저장되어 있습니다. 영화의 키(movie:11002)를 알고 있다면 다음 명령어로 간단히 정보를 조회할 수 있습니다.

> HMGET movie:11002 title rating

1) "Star Wars: Episode V - The Empire Strikes Back"
2) "8.7"

그런데 title, genre, release_year 같은 필드를 기준으로 영화 목록을 조회하려면 어떻게 해야 할까요?

기본("core") Redis 데이터 구조만 사용한다면, 예를 들어 장르와 영화 ID 목록을 연결하는 Set을 직접 관리하고, 인덱스를 구축·조회하는 코드를 애플리케이션에 상당히 많이 추가해야 합니다.

하지만 RediSearch를 사용하면 데이터에 연결된 인덱스를 정의하기만 하면 되고, 나머지 관리는 데이터베이스가 알아서 처리합니다. 이후에는 보조 인덱스(secondary index)를 통해 쿼리 엔진으로 데이터를 조회·검색할 수 있습니다.

영화 데이터를 위한 RediSearch 인덱스 생성

인덱스를 생성하려면 먼저 스키마(schema)를 정의해야 합니다. 스키마는 인덱싱할 필드와 해당 필드의 타입을 나열하며, 쿼리에서 사용할 수 있는 필드를 결정합니다.

이 예제에서는 다음 네 가지 필드를 인덱싱합니다.

  1. Title (제목)
  2. Release year (출시 연도)
  3. Rating (평점)
  4. Genre (장르)

인덱스 생성은 FT.CREATE 명령어로 수행합니다.

> FT.CREATE idx:movie ON hash PREFIX 1 "movie:" SCHEMA title TEXT SORTABLE release_year NUMERIC SORTABLE rating NUMERIC SORTABLE genre TAG SORTABLE

OK

쿼리를 실행하기 전에 FT.CREATE 명령어를 좀 더 자세히 살펴보겠습니다.

  • idx:movie: 인덱스 이름으로, 쿼리를 실행할 때 사용됩니다.
  • ON hash: 인덱싱할 구조의 타입입니다. (현재 RediSearch 2.0은 Hash 구조만 지원하지만, 이 파라미터 덕분에 향후 다른 구조도 인덱싱할 수 있도록 확장될 예정입니다.)
  • PREFIX 1 "movie:": 인덱싱할 키의 접두사입니다. 이 값은 목록 형태이며, movie:* 키만 인덱싱하려 하므로 개수는 1입니다. 동일한 필드로 영화와 TV 쇼를 모두 인덱싱하고 싶다면 PREFIX 2 "movie:" "tv_show:"처럼 작성하면 됩니다.
  • SCHEMA ...: 인덱싱할 필드와 타입을 정의합니다. 위 명령어에서 TEXT, NUMERIC, TAG 타입과 SORTABLE 파라미터를 사용했습니다.

RediSearch 2.0 엔진은 PREFIX 값을 기준으로 데이터베이스를 스캔하고, 스키마 정의에 따라 인덱스를 갱신합니다. 덕분에 Hash를 사용하는 기존 애플리케이션에도 코드 변경 없이 손쉽게 인덱스를 추가할 수 있습니다.

인덱스 정보는 다음 명령어로 확인할 수 있습니다.

> FT.INFO idx:movie

 1) index_name
 2) idx:movie
 ...
46) 1) global_idle
    2) (integer) 0
...

이제 인덱스를 활용해 데이터베이스를 조회할 준비가 되었습니다.

영화 데이터베이스 조회하기

이 섹션에서는 FT.SEARCH 명령어와 그 문법을 사용합니다. 이 글의 목적은 기본기를 익히는 것이므로 핵심 내용만 다루고 세부 사항까지 깊이 들어가지는 않겠습니다. RediSearch에 대해 더 알아보려면 공식 문서와 튜토리얼을 참고하세요.

전문(Full-text) 검색 쿼리

RediSearch는 전문 검색 엔진으로, Google처럼 강력한 쿼리를 애플리케이션에서 실행할 수 있습니다. 예를 들어 "war" 관련 정보가 포함된 모든 영화를 검색하려면 다음 명령어를 실행합니다.

> FT.SEARCH idx:movie "war" RETURN 3 title release_year rating

1) (integer) 1
2) "movie:11002"
3) 1) "title"
   2) "Star Wars: Episode V - The Empire Strikes Back"
   3) "release_year"
   4) "1980"
   5) "rating"
   6) "8.7"

결과를 보면 검색어로 "war"라는 단어 하나만 사용했는데도 제목의 "Wars"와 일치하여 Star Wars: Episode V—The Empire Strikes Back 영화가 조회되었습니다. 제목이 텍스트(TEXT)로 인덱싱되었기 때문에 해당 필드는 토크화(tokenize)되고 어간 추출(stemming) 처리되기 때문입니다.

또한 명령어에서 필드를 지정하지 않았으므로 "war"(및 관련 단어)는 인덱스의 모든 텍스트 필드에서 검색됩니다. 특정 필드만 검색하려면 @field 표기법을 사용합니다.

> FT.SEARCH idx:movie "@title:war" RETURN 3 title release_year rating

이 간단한 데이터셋으로 전문 검색 쿼리를 다양하게 시도해 볼 수 있습니다. (문서를 간결하게 유지하기 위해 쿼리 결과는 생략합니다.)

접두사(Prefix) 매칭:

> FT.SEARCH idx:movie "emp*" RETURN 3 title release_year rating

퍼지(Fuzzy) 검색:

> FT.SEARCH idx:movie "%gdfather%" RETURN 3 title release_year rating

유니온(Union):

> FT.SEARCH idx:movie "war | %gdfather%" RETURN 3 title release_year rating

쿼리 문법에 대한 자세한 내용은 RediSearch 공식 문서에서 확인할 수 있습니다.

태그(Tag) 필드 검색

태그 필드인 "genre"를 사용해 "drama" 장르의 모든 영화를 찾아보겠습니다.

> FT.SEARCH idx:movie "@genre:{Drama}" RETURN 3 title release_year rating

1) (integer) 1
2) "movie:11003"
3) 1) "title"
   2) "The Godfather"
   3) "release_year"
   4) "1972"
   5) "rating"
   6) "9.2"

@field:{value} 문법은 태그 필드를 대상으로 검색한다는 의미입니다. 태그 필터에 대한 자세한 내용은 RediSearch 공식 문서를 참고하세요.

데이터베이스 갱신 후 쿼리하기

지금까지 조회한 데이터는 모두 인덱스 생성 이전부터 존재했던 것으로, 인덱스 생성 과정에서 함께 색인되었습니다. 이번에는 새 영화를 추가하면서 상황을 바꿔 보겠습니다.

> HSET "movie:11005" title "Star Wars: Episode VI - Return of the Jedi" plot "The Rebels destroy the Empire's Death Star." release_year 1983 genre "Action" rating 8.3 votes 906260

(integer) 6

앞서 사용했던 쿼리를 다시 실행해 보면:

> FT.SEARCH idx:movie "war" RETURN 3 title release_year rating

1) (integer) 2
2) "movie:11005"
3) 1) "title"
   2) "Star Wars: Episode VI - Return of the Jedi"
   3) "release_year"
   4) "1983"
   5) "rating"
   6) "8.3"
4) "movie:11002"
5) 1) "title"
   2) "Star Wars: Episode V - The Empire Strikes Back"
   3) "release_year"
   4) "1980"
   5) "rating"
   6) "8.7"

새로 추가된 영화가 자동으로 인덱싱된 것을 확인할 수 있습니다.

마찬가지로 영화를 삭제하거나 만료(expire)시키면 인덱스도 자동으로 갱신됩니다.

> EXPIRE "movie:11002" 15

(integer) 1

15초 뒤에 검색 쿼리를 다시 실행하면 해당 영화가 인덱스에서 제거된 것을 확인할 수 있습니다.

일시적(ephemeral) 검색이 필요한 경우 데이터와 인덱스의 만료 관리를 데이터베이스에 맡길 수 있다는 점에서 매우 강력한 기능입니다. 일시적 검색에 대한 자세한 내용은 'The Case for Ephemeral Search' 블로그 포스트를 참고하세요.

다음 단계는?

이 글에서는 RediSearch의 기본적인 내용을 살펴보고, 데이터 인덱싱이 애플리케이션 코드와 무관하게(투명하게) 이루어지는 방법을 확인했습니다. 이 기능은 RediSearch 2.0에서 새롭게 도입된 것으로, RediSearch 1.x에서는 개발자가 FT.ADD 명령어를 직접 호출해 데이터를 인덱싱해야 했습니다.

이 글에서 다룬 검색 및 인덱싱 기능 외에도 RediSearch는 강력한 데이터 집계(aggregation) 기능을 제공합니다. 관련 내용은 RediSearch 공식 문서, 튜토리얼, 온라인 강좌에서 확인할 수 있습니다.

튜토리얼에는 이 글과 동일한 데이터가 사용되지만, 더 큰 데이터셋과 더 많은 샘플 쿼리 및 집계 예제가 포함되어 있습니다. 또한 Java, Python, Node.js 같은 프로그래밍 언어에서 RediSearch를 사용하는 방법을 보여주는 애플리케이션도 담겨 있습니다. 더 자세히 알아보려면 아래 리소스를 확인하세요.

  • RediSearch 웹 페이지
  • RediSearch 2.0 튜토리얼
  • Rediscover: 사용 사례와 프로젝트