Files
spring-boot-examples/docs/full text search.md
2025-04-08 19:56:24 +09:00

13 KiB

MariaDB 풀 텍스트 검색 (Full-Text Search) 완벽 가이드

**풀 텍스트 검색(Full-Text Search, FTS)**은 일반적인 LIKE 연산자보다 강력한 검색 기능을 제공하는 MariaDB의 주요 기능 중 하나입니다.
대량의 텍스트 데이터를 빠르게 검색할 수 있도록 인덱스를 활용한 고속 검색, 랭킹(관련성 점수) 기반 정렬, 논리 연산자 지원 등의 기능을 제공합니다.

이 글에서는 MariaDB의 풀 텍스트 검색 개념, 설정 방법, 사용법, 고급 기능까지 단계별로 설명하겠습니다.


1. 풀 텍스트 검색(Full-Text Search)란?

📌 풀 텍스트 검색의 특징

  • 일반적인 LIKE 검색보다 훨씬 빠름 (전문 검색 인덱스를 사용)
  • 단어 단위 검색이 가능 (LIKE '%word%'는 문자열 전체에서 검색하지만, FTS는 단어를 인식)
  • 복잡한 검색 연산 지원 (MATCH ... AGAINST를 이용한 자연어 검색, 불리언(Boolean) 검색)
  • 인덱스를 활용하여 검색 성능 최적화 (FULLTEXT 인덱스 사용)
  • 정렬 기준을 제공 (관련성 점수를 반환하여 가장 연관성 높은 결과부터 출력 가능)

2. 풀 텍스트 검색을 위한 기본 설정

1. 테스트용 테이블 생성

MariaDB에서 풀 텍스트 검색을 사용하려면, TEXT 또는 VARCHAR 컬럼에 FULLTEXT 인덱스를 추가해야 합니다.

CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255),
    content TEXT,
    FULLTEXT (title, content)  -- 풀 텍스트 인덱스 추가
) ENGINE=InnoDB;

FULLTEXT (title, content)title과 content 컬럼을 대상으로 풀 텍스트 검색 지원
ENGINE=InnoDBMariaDB 10.0.5 이상부터 InnoDB에서도 지원 (기존에는 MyISAM 전용)


2. 테스트 데이터 삽입

INSERT INTO articles (title, content) VALUES 
('MariaDB 풀 텍스트 검색', 'MariaDB의 FULLTEXT 검색은 강력한 검색 기능을 제공합니다.'),
('MySQL과 MariaDB 비교', 'MariaDB는 MySQL의 오픈소스 버전이며, 여러 기능을 개선했습니다.'),
('MariaDB 성능 튜닝', 'MariaDB의 성능을 향상시키는 방법에 대해 설명합니다.');

3. 기본적인 풀 텍스트 검색 사용법

1. MATCH ... AGAINST를 이용한 검색

MariaDB에서 풀 텍스트 검색을 수행하려면 MATCH(컬럼명) AGAINST ('검색어') 구문을 사용합니다.

SELECT id, title, MATCH(title, content) AGAINST ('MariaDB') AS relevance
FROM articles
WHERE MATCH(title, content) AGAINST ('MariaDB');

MATCH(title, content) AGAINST ('MariaDB')"MariaDB"를 포함하는 레코드 검색
relevance (관련성 점수) 반환 → 높은 점수를 가진 데이터가 더 관련성이 높음

📌 실행 결과 예시:

id title relevance
1 MariaDB 풀 텍스트 검색 1.2
3 MariaDB 성능 튜닝 0.8

장점:

  • 일반적인 LIKE '%검색어%'보다 훨씬 빠른 검색 속도
  • 관련성 점수를 기준으로 정렬 가능

2. 불리언(Boolean) 모드 검색

불리언 모드를 사용하면 논리 연산자(+,-,*,~ 등)를 이용해 복잡한 검색 조건을 적용할 수 있습니다.

SELECT id, title 
FROM articles 
WHERE MATCH(title, content) AGAINST ('+MariaDB -MySQL' IN BOOLEAN MODE);

+MariaDB"MariaDB"가 반드시 포함된 문서만 검색
-MySQL"MySQL"이 포함된 문서는 제외

📌 주요 연산자 정리

연산자 설명
+ 반드시 포함 (예: +MariaDB)
- 포함되면 제외 (예: -MySQL)
* 와일드카드 (예: Mari* → Maria, MariaDB 모두 검색)
~ 관련성을 낮춤 (예: ~튜닝 → "튜닝" 단어가 있는 경우 가중치를 낮춤)
"" 정확한 문구 검색 (예: "MariaDB 풀 텍스트")

4. 고급 검색 기능

1. 자연어(Natural Language) vs 불리언(Boolean) 검색 비교

MariaDB에서는 **자연어 검색(Natural Language Mode)**과 불리언 검색(Boolean Mode) 두 가지 모드를 지원합니다.

📌 자연어 검색 (기본값)

SELECT * FROM articles 
WHERE MATCH(title, content) AGAINST ('MariaDB');

관련성 점수 기반 검색
✔ 자동으로 불필요한 단어 제거


📌 불리언 검색

SELECT * FROM articles 
WHERE MATCH(title, content) AGAINST ('+MariaDB -튜닝' IN BOOLEAN MODE);

연산자를 사용하여 논리적으로 검색 조건 적용 가능
관련성 점수를 사용하지 않음


2. 부분 일치 검색 (NGRAM 인덱스 활용)

MariaDB에서 기본적으로 한 단어(토큰) 단위로 검색이 이루어지므로, 부분 검색(예: "DB" 검색)이 불가능합니다.
이를 해결하기 위해 ngram 인덱스를 활용할 수 있습니다.

📌 ngram 인덱스 사용법

ALTER TABLE articles ADD FULLTEXT(title, content) WITH PARSER ngram;

기본적으로 2글자 단위로 인덱싱 (bigram 방식)
"DB"와 같은 부분 단어 검색 가능


3. 정렬 기준 적용 (ORDER BY)

검색 결과를 관련성(relevance) 점수를 기준으로 정렬할 수 있습니다.

SELECT id, title, MATCH(title, content) AGAINST ('MariaDB') AS relevance
FROM articles
WHERE MATCH(title, content) AGAINST ('MariaDB')
ORDER BY relevance DESC;

관련성 점수가 높은 순으로 정렬


5. 정리

MariaDB 풀 텍스트 검색 핵심 요약

  • FULLTEXT 인덱스를 사용하여 빠른 텍스트 검색 가능
  • MATCH() AGAINST() 구문을 활용하여 검색 수행
  • **불리언 검색(Boolean Mode)**을 사용하면 논리 연산을 적용 가능
  • NGRAM 인덱스를 적용하면 부분 검색 지원

풀 텍스트 검색을 언제 사용할까?

  • LIKE 검색이 느려질 때
  • 대량의 텍스트 데이터를 검색할 때
  • 검색어의 관련성(점수) 기준으로 정렬이 필요할 때

MariaDB의 풀 텍스트 검색 기능을 활용하면 강력한 검색 성능과 빠른 응답 속도를 확보할 수 있습니다! 🚀


JPA에서 풀 텍스트 검색(Full-Text Search) 활용하기

JPA(Hibernate)를 사용할 때 **풀 텍스트 검색(Full-Text Search)**을 적용하는 방법은 크게 두 가지입니다.

  1. 데이터베이스 풀 텍스트 검색 기능 활용 (예: MariaDB의 FULLTEXT 인덱스)
  2. Hibernate Search (Elasticsearch, Apache Lucene 등과 연동)

이 글에서는 MariaDB의 FULLTEXT 인덱스를 활용하여 JPA에서 풀 텍스트 검색을 수행하는 방법을 설명하겠습니다.


1. MariaDB의 FULLTEXT 검색을 JPA에서 사용하기

1. 엔티티(Entity) 설정

풀 텍스트 검색을 적용하려면 TEXT 또는 VARCHAR 컬럼에 FULLTEXT 인덱스를 추가해야 합니다.

📌 엔티티 클래스 예제

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@Table(name = "articles", indexes = {
    @Index(name = "idx_fulltext_title_content", columnList = "title,content", unique = false)
})
public class Article {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(columnDefinition = "TEXT", nullable = false)
    private String content;
}

@Index(name = "idx_fulltext_title_content", columnList = "title,content")
JPA로 FULLTEXT 인덱스를 직접 설정할 수 없지만, 인덱스 지정 가능
@Column(columnDefinition = "TEXT")
TEXT 타입 필드(content)를 선언


2. FULLTEXT 인덱스 수동 생성

JPA에서는 FULLTEXT 인덱스를 자동으로 생성하지 않으므로, SQL로 직접 인덱스를 추가해야 합니다.

CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    FULLTEXT (title, content)  -- FULLTEXT 인덱스 추가
) ENGINE=InnoDB;

3. JPA에서 풀 텍스트 검색 쿼리 작성

JPA의 @Query를 사용하여 MATCH() AGAINST() 구문을 활용할 수 있습니다.

📌 Repository 인터페이스

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface ArticleRepository extends JpaRepository<Article, Long> {

    @Query(value = """
        SELECT * FROM articles 
        WHERE MATCH(title, content) AGAINST(:keyword)
        """, nativeQuery = true)
    List<Article> searchByFullText(@Param("keyword") String keyword);
}

MATCH(title, content) AGAINST(:keyword)title과 content에서 keyword 검색
nativeQuery = trueFULLTEXT 검색은 네이티브 쿼리로 실행해야 함


4. 서비스(Service) 계층 작성

📌 검색 기능을 수행하는 서비스 클래스

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class ArticleService {

    private final ArticleRepository articleRepository;

    public ArticleService(ArticleRepository articleRepository) {
        this.articleRepository = articleRepository;
    }

    public List<Article> searchArticles(String keyword) {
        return articleRepository.searchByFullText(keyword);
    }
}

5. 컨트롤러(Controller) 구현

📌 검색 API 컨트롤러

import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/articles")
public class ArticleController {

    private final ArticleService articleService;

    public ArticleController(ArticleService articleService) {
        this.articleService = articleService;
    }

    @GetMapping("/search")
    public List<Article> searchArticles(@RequestParam String keyword) {
        return articleService.searchArticles(keyword);
    }
}

/articles/search?keyword=MariaDBMariaDB 관련 문서를 검색하는 API


2. 불리언(Boolean) 검색 적용

MariaDB의 불리언(Boolean) 검색 모드를 적용하면 검색 연산자(+, -, *, " ")를 사용할 수 있습니다.

BOOLEAN MODE 적용 예제

@Query(value = """
    SELECT * FROM articles 
    WHERE MATCH(title, content) AGAINST(:keyword IN BOOLEAN MODE)
    """, nativeQuery = true)
List<Article> searchByFullTextBoolean(@Param("keyword") String keyword);

IN BOOLEAN MODE논리 연산자를 포함한 검색 수행

📌 검색 연산자 예제

검색어 설명
+MariaDB 반드시 "MariaDB" 포함
-MySQL "MySQL"이 포함된 결과 제외
Mari* "Maria", "MariaDB" 등 검색 가능
"MariaDB 검색" 정확한 문구 검색

3. 정렬(관련성 점수 기반)

풀 텍스트 검색을 수행할 때 관련성 점수를 기준으로 정렬할 수 있습니다.

정렬을 적용한 Repository

@Query(value = """
    SELECT *, MATCH(title, content) AGAINST(:keyword) AS relevance
    FROM articles
    WHERE MATCH(title, content) AGAINST(:keyword)
    ORDER BY relevance DESC
    """, nativeQuery = true)
List<Article> searchByRelevance(@Param("keyword") String keyword);

MATCH(title, content) AGAINST(:keyword) AS relevance관련성 점수 계산
ORDER BY relevance DESC가장 연관성 높은 결과부터 정렬


4. 페이징 처리 적용

Spring Data JPA의 Pageable을 활용하여 검색 결과에 페이징을 적용할 수 있습니다.

페이징 지원 Repository

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

@Query(value = """
    SELECT * FROM articles 
    WHERE MATCH(title, content) AGAINST(:keyword)
    """, nativeQuery = true)
Page<Article> searchByFullTextPaged(@Param("keyword") String keyword, Pageable pageable);

Page<Article> 반환 → Spring Data JPA의 페이징 기능을 활용 가능


5. 정리

JPA에서 MariaDB 풀 텍스트 검색 활용 방법

  • FULLTEXT 인덱스를 적용하여 빠른 검색 수행
  • MATCH() AGAINST()를 활용한 검색 쿼리 작성 (BOOLEAN MODE 지원)
  • 관련성 점수 기반 정렬 가능 (ORDER BY relevance DESC)
  • Pageable을 활용하여 페이징 처리 가능

📌 풀 텍스트 검색이 필요한 경우

✔ 데이터가 많아 LIKE '%keyword%'로 검색할 경우 성능이 저하될 때
✔ 연관성 높은 검색 결과를 우선적으로 정렬해야 할 때
BOOLEAN MODE를 활용해 논리 검색(+, -, *)이 필요할 때

MariaDB 풀 텍스트 검색을 활용하면 JPA에서도 강력한 검색 기능을 구현할 수 있습니다! 🚀