우아한테크코스 테코톡
플린트의 MySQL의 전문 검색 인덱스
https://youtu.be/FTC58pJZEYo?si=RtfFd4qMzkv4Kv0I
플린트의 MySQL의 전문 검색 인덱스
- 플린트의 MySQL의 전문 검색 인덱스
- MySQL 전문 검색(Full-Text Search)이란 무엇인가
- LIKE 검색의 한계
- LIKE 검색의 정확도 문제
- Full-Text Search란 무엇인가
- 전문 검색의 핵심 원리
- 1. 텍스트 분석 — N-Gram
- 왜 N-Gram이 중요한가
- N-Gram 상세 동작 과정
- 역인덱스(Inverted Index)
- Full-Text Search 사용 조건
- Full-Text Index 생성 방법
- MATCH AGAINST 문법
- 실제 성능 비교
- 존재하지 않는 키워드 검색
- 자연어 모드(Natural Language Mode)
- Boolean Mode
- 전문 검색의 한계점
- 1. 비실시간 인덱스 갱신
- 2. 쓰기 부하 증가
- Full-Text Search가 적합한 상황
- 하지만 Elasticsearch와 비교하면?
- 정리
MySQL 전문 검색(Full-Text Search)이란 무엇인가
MySQL에서 게시글 제목이나 본문 검색 기능을 만들 때 가장 먼저 떠오르는 방식은 보통 LIKE 검색이다.
예를 들면 다음과 같다.
SELECT *
FROM articles
WHERE title LIKE '%스프링%';
처음에는 간단하고 잘 동작해 보인다. 하지만 데이터가 많아지고 실제 서비스 환경으로 가면 다음과 같은 문제가 발생한다.
- 검색 속도가 매우 느려짐
- 특정 단어가 검색되지 않음
- 띄어쓰기 차이 때문에 검색 누락 발생
- Full Table Scan 발생
이러한 문제를 해결하기 위해 MySQL은 전문 검색(Full-Text Search) 기능을 제공한다.
LIKE 검색의 한계
1. 성능 문제
LIKE 검색은 와일드카드 위치에 따라 성능 차이가 매우 크다.
인덱스를 사용할 수 있는 경우
SELECT *
FROM article
WHERE title LIKE 'spring%';
이 경우는 "spring" 으로 시작하는 범위를 인덱스에서 바로 찾을 수 있다.
즉:
springA
springB
springboot
처럼 정렬된 범위를 빠르게 탐색 가능하다.
인덱스를 사용할 수 없는 경우
하지만 대부분 실제 검색은 다음 형태다.
SELECT *
FROM article
WHERE title LIKE '%spring%';
이 경우 문제는:
앞에 무엇이 올지 알 수 없음
이다.
즉 인덱스의 정렬 구조를 사용할 수 없다.
결국 MySQL은:
Full Table Scan
을 수행하게 된다.
왜 Full Table Scan이 위험한가
예를 들어 데이터가 100만 건이라면:
1건씩 전부 검사
→ 문자열 비교 수행
→ CPU 증가
→ 디스크 I/O 증가
→ 응답 지연
이 발생한다.
실제 서비스에서는 P99 응답 시간이 급격히 증가할 수 있다.
LIKE 검색의 정확도 문제
LIKE 검색은 단순 문자열 비교다.
즉:
완전히 일치해야 함
이라는 문제가 있다.
예시
데이터:
전문 검색 질문입니다
검색:
LIKE '%전문 검색%'
→ 검색 성공
하지만:
LIKE '%전문검색%'
→ 검색 실패
띄어쓰기 하나 때문에 검색되지 않는다.
Full-Text Search란 무엇인가
MySQL 전문 검색은:
단어와 의미 기반 검색
을 수행하는 기능이다.
단순 문자열 비교가 아니라:
- 단어 분석
- 토큰화
- 역인덱스
- 관련성 점수
를 활용한다.
전문 검색의 핵심 원리
전문 검색은 크게 두 단계로 동작한다.
1. 텍스트 분석
2. 역인덱스 저장
1. 텍스트 분석 — N-Gram
MySQL 전문 검색은 한국어 환경에서 보통:
N-Gram
방식을 많이 사용한다.
N-Gram이란
문장을 N글자 단위로 분해하는 방식이다.
예를 들어:
안녕하세요
를 2-Gram으로 분해하면:
안녕
녕하
하세
세요
처럼 나뉜다.
왜 N-Gram이 중요한가
한국어는 띄어쓰기와 형태 변화가 많다.
예를 들어:
전문검색
전문 검색
처럼 띄어쓰기 여부가 달라도 검색 가능해야 한다.
N-Gram은 기계적으로 잘라 저장하기 때문에 이런 문제를 해결할 수 있다.
N-Gram 상세 동작 과정
예시:
전문 검색 기능
1단계 — 공백 분리
전문
검색
기능
2단계 — N글자 단위 분리
2-Gram 기준:
전문
문검
검색
같은 토큰 생성 가능하다.
역인덱스(Inverted Index)
전문 검색의 핵심 성능 비밀이다.
일반 인덱스 vs 역인덱스
일반 인덱스:
문서 → 단어
역인덱스:
단어 → 문서
예시
문서1 : 전문 검색
문서2 : 전문 기능
역인덱스:
전문 → [1,2]
검색 → [1]
기능 → [2]
즉 "전문" 검색 시:
바로 문서 1,2 반환 가능
하다.
Full-Text Search 사용 조건
MySQL에서 전문 검색을 사용하려면 조건이 있다.
지원 버전
MySQL 5.7.6 이상
지원 스토리지 엔진
InnoDB
MyISAM
지원 타입
CHAR
VARCHAR
TEXT
문자 타입만 가능하다.
Full-Text Index 생성 방법
전문 검색을 사용하려면 반드시:
FULLTEXT INDEX
를 생성해야 한다.
기본 생성 예시
CREATE FULLTEXT INDEX idx_title
ON article(title);
N-Gram 사용 시
CREATE FULLTEXT INDEX idx_title
ON article(title)
WITH PARSER ngram;
WITH PARSER ngram 을 반드시 명시해야 한다.
MATCH AGAINST 문법
전문 검색은 일반 WHERE LIKE가 아니라:
MATCH(column)
AGAINST(keyword)
문법을 사용한다.
예시
SELECT *
FROM article
WHERE MATCH(title)
AGAINST('스프링');
이 문법을 사용해야 FullText Index가 적용된다.
실제 성능 비교
발표에서 진행한 테스트:
데이터 100만 건
LIKE 검색
1.044초
MATCH AGAINST
0.856초
약 18% 성능 향상이 있었다.
존재하지 않는 키워드 검색
더 큰 차이가 난다.
LIKE
0.892초
MATCH AGAINST
0초 수준
역인덱스를 통해 존재 여부를 즉시 판단 가능하기 때문이다.
자연어 모드(Natural Language Mode)
전문 검색은 단순 검색만 하지 않는다.
관련성 점수 기반 정렬도 가능하다.
관련성 점수란
문서와 검색어 간의 연관도다.
다음 요소를 고려한다.
등장 빈도
희귀성
중요도
특징
ORDER BY 없이도:
가장 관련성 높은 결과 우선 반환
가능하다.
Boolean Mode
조건 기반 검색도 가능하다.
AND 검색
MATCH(title)
AGAINST('+스프링 +JPA'
IN BOOLEAN MODE);
→ 둘 다 포함
NOT 검색
MATCH(title)
AGAINST('+스프링 -JPA'
IN BOOLEAN MODE);
→ 스프링 포함 + JPA 제외
전문 검색의 한계점
Full-Text Search도 만능은 아니다.
1. 비실시간 인덱스 갱신
트랜잭션 Commit 이전에는:
FullText Index 반영 안됨
즉:
INSERT
→ 아직 검색 안됨
COMMIT
→ 검색 가능
상황이 발생할 수 있다.
2. 쓰기 부하 증가
N-Gram은 토큰을 엄청 많이 생성한다.
예시:
100만 건 데이터
→ 728만 토큰 생성
즉 인덱스 저장 비용이 커진다.
Full-Text Search가 적합한 상황
다음과 같은 경우 매우 효과적이다.
게시글 검색
블로그 검색
문서 검색
채팅 검색
상품 검색
특히:
부분 문자열 검색
띄어쓰기 유연성
관련도 기반 검색
이 필요할 때 강력하다.
하지만 Elasticsearch와 비교하면?
MySQL Full-Text는 가볍고 간단하다.
하지만:
- 형태소 분석
- 복잡한 랭킹
- 대규모 검색
- 오타 교정
- 자동완성
같은 고급 기능은 Elasticsearch가 훨씬 강력하다.
즉:
간단 검색 → MySQL FullText
대규모 검색 플랫폼 → Elasticsearch
구조로 많이 사용한다.
정리
LIKE 검색은:
성능 한계
정확도 한계
Full Table Scan 위험
이 존재한다.
반면 MySQL Full-Text Search는:
N-Gram 분석
역인덱스
관련성 점수
를 활용해 훨씬 빠르고 정확한 검색을 제공한다.
특히:
MATCH AGAINST
FULLTEXT INDEX
를 통해 검색 성능을 크게 향상시킬 수 있다.
다만:
비실시간 인덱스 갱신
쓰기 부하 증가
같은 특성도 반드시 고려해야 한다.