Like 검색의 한계, Elasticsearch 도입기

윤주원·2025년 9월 30일

서론

현재 진행중인 스터디 관리 프로젝트에서는 사용자들이 원하는 스터디를 빠르게 찾을수 있는 검색 기능이 있었다.
처음 도입한 단순한 SQL LIKE 검색으로는 한계가 명확했다.
정확한 단어를 입력하지 않으면 검색이 안되고, %가 앞에 붙은 패턴은 인덱스를 사용할수없어 전체 테이블 스캔이 발생해 성능 적인 문제도 있었다.

이런 문제들을 해결하기 위해 elasticsearch를 도입하려고 한다.
이번 글에서는 SQL 검색의 한계를 알아보고, elasticsearch가 어떻게 문제를 해결하여 더 나은 검색을 경험을 제공하는지 알아보겠다.

Like 검색의 한계

1️⃣ 정확한 패턴만 매칭

  • %와 _만 지원하므로 복잡한 정규식 패턴은 사용할 수 없다.
  • 예: LIKE '%apple%'는 "pineapple"은 찾지만 "apple pie"와 "Apple" 은 찾을수 없다. (사용하는 DB에 따라 대소문자 구분 여부는 다를수 있음)

2️⃣ 대소문자 구분 문제

  • 대부분의 DBMS는 기본적으로 대소문자를 구분하지 않지만, 일부는 구분한다.
  • 예: PostgreSQL은 기본적으로 대소문자를 구분함 → LIKE 'Apple'은 "apple"을 찾지 못함.

3️⃣ 성능 저하

  • %가 앞에 붙은 패턴 (LIKE '%keyword')은 인덱스를 사용할 수 없어 전체 테이블 스캔이 발생한다.
  • 대량의 데이터에서 검색 시 매우 느려질 수 있음.

4️⃣ 언어 및 형태소 분석 부족

  • 형태소 분석이나 자연어 처리를 하지 않기 때문에 "먹다", "먹었음", "먹고 있음" 같은 변형된 단어는 매칭되지 않음.
  • 한국어, 일본어 등 형태소가 중요한 언어에서는 특히 비효율적.

5️⃣ 복잡한 조건 처리 불가

  • LIKE는 단순 문자열 매칭만 가능하며, 문맥이나 의미 기반 검색은 불가능.
  • 예: "사과"를 검색했을 때 "과일"이라는 의미로 연결된 결과는 찾지 못함.

6️⃣ 보안 취약점

  • 사용자 입력을 그대로 LIKE에 넣으면 SQL Injection 위험이 있음.
  • 예: WHERE name LIKE '%${user_input}%' → 악의적인 입력으로 쿼리 조작 가능.

Elasticsearch 란?

Elasticsearch는 오픈소스 기반의 분산 검색 엔진으로, 텍스트 데이터를 빠르고 정밀하게 검색할 수 있도록 설계되었다.
데이터베이스의 LIKE 검색이 단순히 문자열 패턴을 찾는 방식이라면, Elasticsearch는 데이터를 토큰 단위로 색인(Inverted Index) 구조에 저장하여 검색을 수행한다.

쉽게 말해, 책의 맨 뒤에 있는 색인(Index)처럼 특정 단어가 어떤 문서에 포함되어 있는지를 미리 기록해 두는 것이다.
이 덕분에 사용자가 입력한 검색어와 관련된 결과를 매우 빠르게 찾아낼 수 있다.

특히, Elasticsearch는 단순 키워드 검색을 넘어서 형태소 분석, 유사도 기반 검색, 자동완성 등 고도화된 검색 기능을 지원하기 때문에, 한국어와 같이 검색이 어려운 언어에서도 강력한 성능을 발휘할 수 있다.

Elasticsearc의 특징

1️⃣ 역색인(Inverted Index) 구조

  • 일반적인 RDB는 레코드를 순차적으로 훑어보며 데이터를 찾는다
  • Elasticsearch는 미리 단어 -> 문서 위치 관게를 저장해두기 때문에, 특정 단어가 포함된 데이터를 즉시 찾을 수 있다.

2️⃣ 다양한 Analyzer 지원

  • 단순 문자열 비교가 아닌, 언어별로 의미 있는 단위로 나누어 저장할 수 있다.
  • 한국어의 경우 Nori 형태소 분석기를 통해 "공부하다" → ["공부", "하다"] 와 같이 토큰화할 수 있어, 보다 정확한 검색이 가능하다.

3️⃣ 실시간 검색 가능

  • 데이터가 인덱싱되는 즉시 검색 결과에 반영된다.
  • 나의 프로젝트에서도 스터디 생성 후 곧바로 검색이 가능하게 설계 되어 있음.

4️⃣ 확장성과 분산 처리

  • 노드를 여러 대 운영하여 데이터를 분산 저장하고 검색할 수 있다.
  • 데이터가 많아져도 서버를 확장하기 쉬워 장기적으로 안정적인 성능을 보장 할 수 있다.

내가 적용한 검색 전략

스터디 관리 프로젝트에서는 검색의 정확성과 사용 편의성을 모두 잡는 것이 목표였다.
이를 위해 Elasticsearch가 제공하는 다양한 기능 중에서 몇 가지 전략을 선택해 적용했다.

1️⃣ 한글 형태소 분석 (Nori Analyzer)

  • 한국어는 영어와 달리 단어가 다양한 형태로 변형된다.
    예를 들어 "공부하다", "공부함", "공부중"은 모두 같은 의미지만, 단순 문자열 검색으로는 서로 매칭되지 않는다.
  • Nori 형태소 분석기를 적용하면 문장을 의미 단위로 잘게 나누어 색인할 수 있어, 변형된 단어라도 검색이 가능하다.
  • 다른 방법으로는 단순 Whitespace Tokenizer(공백단위)나 Standard Analyzer(영어 중심)를 사용할 수 있지만, 한국어에서는 의미 단위가 분리되지 않아 부정확한 결과가 나온다.
    → 그래서 한국어 전용 분석기인 Nori를 선택했다.

2️⃣ 부분 일치 검색 (Edge N-gram + Nori)

  • 사용자가 단어를 끝까지 다 입력하지 않아도 검색이 되어야 한다.
    예를 들어 "스터"만 입력해도 "스터디"를 찾을 수 있어야 한다.
  • 이를 위해 Edge N-gram Tokenizer를 적용해 단어의 앞부분을 쪼개 저장했다.
    → "스터디" → ["스", "스터", "스터디"]
  • 다른 대안으로는 Wildcard Query나 Prefix Query가 있지만, 이들은 성능상 불리하거나 인덱스를 제대로 활용하지 못한다.
    → 따라서 Edge N-gram 기반 색인이 더 효율적인 전략이었다.

3️⃣ 커스텀 Analyzer 설계

  • 저장 시에는 최대한 다양한 토큰을 생성하고, 검색 시에는 의미 중심으로 맞추는 방식이 필요했다.
  • 그래서 색인 과정에서는 Nori + Edge N-gram을 적용하여 단어를 최대한 많이 쪼갰고,
    검색 시에는 Nori만 적용해 불필요하게 잘린 토큰을 배제하고 의미 단위 매칭에 집중하여 불필요한 과매칭 을 방지했다.
  • 이 방식 덕분에 "스터" 같은 짧은 입력도 매칭되면서, "스터디" 전체 단어 입력 시에도 의미 있는 검색 결과를 반환할 수 있었다.

4️⃣ 실시간 재인덱싱 기능

  • 검색은 정적 데이터가 아닌, 사용자 활동과 밀접하게 연결된다.
  • 새로운 스터디가 생성되면 곧바로 검색할 수 있어야 했기 때문에, 실시간 인덱싱 전략을 도입했다.
  • 일반적으로 배치(batch) 단위로 인덱싱하는 방법도 있지만, 이는 최신성이 떨어진다.
    → 내 프로젝트에서는 이벤트 기반 인덱싱을 통해 새로운 데이터가 생성되면 즉시 검색 결과에 반영되도록 했다.

이러한 전략을 종합적으로 적용함으로써, 단순 문자열 매칭에 그쳤던 SQL LIKE 검색과 달리,
사용자 경험 중심의 빠르고 정밀한 검색 시스템을 구현할 수 있었다.

결론

이번 글에서는 SQL LIKE 검색의 한계를 살펴보고, Elasticsearch를 도입하여 어떤 방식으로 개선했는지를 정리했다.
단순 단어 비교 검색에서 벗어나, 형태소 분석과 부분 검색을 결합한 커스텀 전략을 통해 속도, 정확도, 사용자 경험을 동시에 끌어올릴 수 있었다.

앞으로는

  • 자동완성: 사용자가 검색어를 입력하는 즉시 후보를 제시해 더 빠른 탐색을 지원.
  • 추천 검색어: 인기 검색어나 오타 교정 등을 제공해 사용성을 높임.
  • 유사도 기반 추천: 단순 키워드 일치가 아닌, 문맥과 의미를 고려한 결과 제공.

이러한 기능들을 단계적으로 추가해, 단순한 검색을 넘어 사용자 친화적인 검색 경험을 제공하는 것이 목표다.

profile
백엔드 개발자 윤주원 입니다.

0개의 댓글