카테고리 : MySQL/기술노트

MySQL Fulltext index 기본: 한글 검색 한계와 ngram parser 검토

MySQL Fulltext index의 내부 구조와 ngram parser의 한글 토큰화 방식, 검색 품질 한계, 운영 적용 기준을 정리한다.

저자: MySQL 기술 노트 작성: 2026.07.26 약 12분 7,184자
다운로드

관계형 데이터베이스에도 본문 검색 요구는 자주 들어온다. 상품명, 게시물, 운영 메모처럼 문자열이 긴 컬럼에서 LIKE '%검색어%'를 사용하기 시작하면 기능 구현은 빠르지만 데이터가 늘수록 전체 스캔 비용이 문제가 된다. MySQL의 FULLTEXT index는 이러한 역방향 포함 검색을 B+Tree가 아닌 전문 검색용 역색인으로 처리한다.

그러나 영어 단어 경계를 전제로 한 기본 parser를 한글에 그대로 적용하면 기대한 검색 결과를 얻기 어렵다. MySQL이 제공하는 ngram parser는 한글처럼 공백만으로 단어 경계를 판단하기 어려운 언어를 일정 길이의 문자열 조각으로 나눠 색인한다. 도입 장벽은 낮지만 형태소 분석, 동의어 처리, 오탈자 보정까지 제공하는 검색 엔진은 아니다. 따라서 이 기능을 검토할 때에는 “검색이 되는가”뿐 아니라 “원하는 품질과 운영 비용을 감당할 수 있는가”를 함께 판단해야 한다.

1. B+Tree와 Fulltext index가 해결하는 문제가 다른 이유

일반 B+Tree index는 정렬된 키의 왼쪽부터 조건을 좁힌다. title = 'MySQL', created_at >= ..., name LIKE '데이터%'처럼 키의 시작 위치가 정해진 조건에는 적합하다. 반면 body LIKE '%데이터%'는 문자열 어디에서 검색어가 시작할지 알 수 없어 보통 전체 행 또는 전체 인덱스를 읽어야 한다.

Fulltext index는 문서에서 추출한 token을 key로, 그 token이 등장한 문서 식별자와 위치 정보를 posting 정보로 저장한다. 검색할 때에는 원문을 처음부터 훑지 않고 검색어에서 만든 token의 posting 목록을 찾은 뒤 문서 후보를 계산한다.

flowchart LR
    A[원문 컬럼] --> B[Fulltext parser]
    B --> C[Token 생성]
    C --> D[역색인 저장]
    Q[검색어] --> E[동일 parser로 분석]
    E --> F[Token posting 조회]
    D --> F
    F --> G[문서 후보와 관련도 계산]
    G --> H[원문 조건과 결과 반환]

핵심은 색인할 때와 검색할 때 같은 parser 규칙을 사용한다는 점이다. parser 선택과 token 크기를 바꾸면 이미 만들어진 역색인의 의미도 달라지므로 설정만 변경해서 끝낼 수 없고 Fulltext index를 다시 구축해야 한다.

2. 기본 parser가 한글에서 불리한 이유

MySQL 기본 Fulltext parser는 공백과 구두점 등으로 단어 경계를 판정하는 방식에 가깝다. 영어 문장은 공백 단위가 검색 단위와 대체로 맞지만, 한글 검색은 다음 특성 때문에 단순한 단어 분리만으로 부족하다.

  • 조사와 어미가 어간에 붙는다. 데이터베이스, 데이터베이스를, 데이터베이스에서는 사용자가 같은 핵심어로 찾기를 기대할 수 있다.
  • 띄어쓰기 편차가 크다. 장애 대응장애대응을 같은 의미로 검색하려는 요구가 흔하다.
  • 복합 명사가 많다. 복제지연, 복제 지연, 리플리케이션 지연은 운영 문서에서 함께 등장할 수 있다.
  • 한 글자 검색어, 초성 검색, 오탈자 검색은 별도의 요구다. ngram이 자동으로 해결하지 않는다.
  • Unicode 정규화가 다른 문자열은 화면상 같아 보여도 저장된 code point 배열이 다를 수 있다.

즉, 한글 검색에서 필요한 것은 단지 “한글 문장을 token으로 나눌 수 있음”이 아니다. 검색어 정규화, 형태 변화, 동의어, 랭킹, 오탈자, 자동완성까지 요구 범위를 먼저 분리해야 한다.

3. ngram parser의 토큰화 원리

ngram parser는 문자열을 n개의 연속된 문자로 겹쳐 자른다. 기본 ngram_token_size=2라면 데이터베이스는 개념적으로 다음과 같은 bigram으로 나뉜다.

데이 / 이터 / 터베 / 베이 / 이스

검색어도 같은 방식으로 분해되므로 데이터를 검색하면 데이, 이터 token을 이용해 후보 문서를 찾을 수 있다. 조사나 어미가 뒤에 붙더라도 핵심 문자열의 bigram이 유지되는 경우가 많아 기본 parser보다 부분 문자열 검색에 유리하다.

하지만 token 크기에는 명확한 trade-off가 있다.

token 크기 기대 효과 비용과 한계
1 한 글자 검색과 높은 recall에 유리 token/posting 수와 노이즈가 커지고 낮은 precision이 발생하기 쉬움
2 한글 부분 검색의 현실적인 출발점 한 글자 검색을 직접 충족하지 못하고 동음·공통 bigram 충돌이 존재
3 이상 더 구체적인 문자열 일치로 precision 개선 가능 짧은 검색어와 형태 변화에 취약하고 recall이 낮아질 수 있음

ngram_token_size는 서버 시작 시 결정되는 read-only 변수다. 값 변경에는 서버 재시작이 필요하며, 변경 후 기존 Fulltext index를 재구축해야 한다. 운영 중 값을 즉흥적으로 바꾸기보다 실제 문서와 검색어 표본으로 후보 값을 비교한 뒤 배포해야 한다.

다음 쿼리는 대상 인스턴스의 버전, token 크기, parser plugin 상태를 확인한다.

SELECT VERSION() AS mysql_version;
SHOW VARIABLES LIKE 'ngram_token_size';
SELECT PLUGIN_NAME, PLUGIN_STATUS, PLUGIN_TYPE
FROM information_schema.PLUGINS
WHERE PLUGIN_NAME = 'ngram';

실행 결과(MySQL 8.0.x):

mysql> SELECT VERSION() AS mysql_version;

+---------------+
| mysql_version |
+---------------+
| 8.0.46        |
+---------------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'ngram_token_size';

+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| ngram_token_size | 2     |
+------------------+-------+
1 row in set (0.00 sec)

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS, PLUGIN_TYPE
    -> FROM information_schema.PLUGINS
    -> WHERE PLUGIN_NAME = 'ngram';

+-------------+---------------+-------------+
| PLUGIN_NAME | PLUGIN_STATUS | PLUGIN_TYPE |
+-------------+---------------+-------------+
| ngram       | ACTIVE        | FTPARSER    |
+-------------+---------------+-------------+
1 row in set (0.00 sec)

ngram은 MySQL 배포판에 포함된 built-in Fulltext parser이지만, 관리형 서비스나 호환 엔진은 지원 범위가 다를 수 있다. DDL을 배포하기 전에 실제 대상 버전에서 위 조회와 테스트용 CREATE TABLE을 확인하는 편이 안전하다.

4. 한글 Fulltext index 생성과 검색

다음 예제는 InnoDB 테이블에 ngram 기반 Fulltext index를 만들고 한글 본문을 조회한다. Fulltext index 정의에 WITH PARSER ngram을 명시하지 않으면 같은 컬럼이라도 기본 parser로 구축되므로 DDL 검토에서 반드시 확인해야 한다.

SET NAMES utf8mb4;

CREATE TABLE ft_note_demo (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    title VARCHAR(100) NOT NULL,
    body TEXT NOT NULL,
    PRIMARY KEY (id),
    FULLTEXT KEY ft_body (body) WITH PARSER ngram
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO ft_note_demo (title, body) VALUES
    ('운영 기초', 'MySQL 데이터베이스 운영 기술노트'),
    ('인덱스 설계', '관계형 데이터베이스 인덱스 설계'),
    ('장애 대응', '애플리케이션 장애 대응 절차');

SELECT id, title
FROM ft_note_demo
WHERE MATCH(body) AGAINST('데이터베이스' IN NATURAL LANGUAGE MODE)
ORDER BY id;

실행 결과(MySQL 8.0.x):

mysql> SET NAMES utf8mb4;

Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE ft_note_demo (
    ->     id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    ->     title VARCHAR(100) NOT NULL,
    ->     body TEXT NOT NULL,
    ->     PRIMARY KEY (id),
    ->     FULLTEXT KEY ft_body (body) WITH PARSER ngram
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO ft_note_demo (title, body) VALUES
    ->     ('운영 기초', 'MySQL 데이터베이스 운영 기술노트'),
    ->     ('인덱스 설계', '관계형 데이터베이스 인덱스 설계'),
    ->     ('장애 대응', '애플리케이션 장애 대응 절차');

Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT id, title
    -> FROM ft_note_demo
    -> WHERE MATCH(body) AGAINST('데이터베이스' IN NATURAL LANGUAGE MODE)
    -> ORDER BY id;

+----+------------------+
| id | title            |
+----+------------------+
|  1 | 운영 기초    |
|  2 | 인덱스 설계 |
+----+------------------+
2 rows in set (0.00 sec)

MATCH(body)의 컬럼 목록은 해당 Fulltext index 정의와 일치하도록 관리하는 것이 좋다. 제목과 본문을 함께 검색하려면 FULLTEXT(title, body)를 만들고 쿼리도 MATCH(title, body)로 통일한다. 서로 다른 Fulltext index 여러 개를 하나의 MATCH()가 임의로 조합해 주는 구조로 이해하면 안 된다.

4.1 Natural language mode와 Boolean mode

IN NATURAL LANGUAGE MODE는 token의 문서 빈도와 출현 정보를 이용해 관련도를 계산한다. 일반적인 검색 화면의 출발점으로 사용할 수 있지만, 짧고 비슷한 문서만 있는 테스트 데이터의 score를 운영 랭킹 품질로 해석해서는 안 된다.

IN BOOLEAN MODE+, -, 따옴표, wildcard 등으로 포함·제외 조건을 표현할 수 있다. 다만 ngram parser에서는 입력이 다시 ngram으로 나뉘며 phrase와 wildcard 해석도 일반 단어 parser에 대한 직관과 다를 수 있다. 제품 검색 문법으로 노출하기 전에 다음 항목을 실제 문장으로 회귀 테스트해야 한다.

  • 공백이 포함된 검색어와 붙여 쓴 검색어
  • 한 글자, 두 글자, 긴 검색어
  • 반드시 포함할 단어와 제외할 단어
  • 따옴표로 감싼 phrase 검색
  • 영문·숫자·한글이 섞인 모델명
  • 조사와 어미가 달라진 문장

4.2 실행 계획에서 Fulltext 접근 확인

Fulltext 조건을 작성했다고 해서 애플리케이션의 다른 predicate, 정렬, LIMIT 비용이 사라지는 것은 아니다. EXPLAIN으로 Fulltext access path가 선택되는지 확인하고, 후보 문서를 찾은 뒤 적용되는 추가 필터와 정렬 비용도 함께 보아야 한다.

SET NAMES utf8mb4;

EXPLAIN
SELECT id, title
FROM ft_note_demo
WHERE MATCH(body) AGAINST('데이터베이스' IN NATURAL LANGUAGE MODE)
ORDER BY id;

실행 결과(MySQL 8.0.x):

mysql> SET NAMES utf8mb4;

Query OK, 0 rows affected (0.00 sec)

mysql> EXPLAIN
    -> SELECT id, title
    -> FROM ft_note_demo
    -> WHERE MATCH(body) AGAINST('데이터베이스' IN NATURAL LANGUAGE MODE)
    -> ORDER BY id;

+----+-------------+--------------+------------+----------+---------------+---------+---------+-------+------+----------+---------------------------------------------------+
| id | select_type | table        | partitions | type     | possible_keys | key     | key_len | ref   | rows | filtered | Extra                                             |
+----+-------------+--------------+------------+----------+---------------+---------+---------+-------+------+----------+---------------------------------------------------+
|  1 | SIMPLE      | ft_note_demo | NULL       | fulltext | ft_body       | ft_body | 0       | const |    1 |   100.00 | Using where; Ft_hints: no_ranking; Using filesort |
+----+-------------+--------------+------------+----------+---------------+---------+---------+-------+------+----------+---------------------------------------------------+
1 row in set (0.00 sec)

Traditional EXPLAIN에서는 일반적으로 type=fulltext와 선택된 Fulltext key를 확인할 수 있다. 다만 rows 추정치와 Extra는 버전과 데이터 통계에 따라 달라질 수 있으므로 특정 숫자보다 access type과 key 선택 여부를 우선 해석한다.

5. 역색인 token을 직접 확인하는 방법

검색 결과가 예상과 다를 때 원문만 보아서는 parser가 실제로 어떤 token을 만들었는지 알기 어렵다. InnoDB는 진단 대상으로 지정한 Fulltext table에서 아직 디스크 역색인으로 병합되지 않은 token을 INNODB_FT_INDEX_CACHE로 조회할 수 있다. 병합된 token은 INNODB_FT_INDEX_TABLE에서 확인한다.

innodb_ft_aux_table은 전역 진단 변수이므로 운영 인스턴스에서 바꿀 때에는 다른 진단 작업과 충돌하지 않도록 주의해야 한다. 다음 예제의 database/table 이름은 검증용 환경에 맞춘 것이다.

SET NAMES utf8mb4;
SET GLOBAL innodb_ft_aux_table = 'mysql_tech_note/ft_note_demo';

SELECT WORD, DOC_COUNT, DOC_ID, POSITION
FROM information_schema.INNODB_FT_INDEX_CACHE
WHERE WORD IN ('데이', '이터', '터베', '베이', '이스')
ORDER BY WORD, DOC_ID, POSITION;

실행 결과(MySQL 8.0.x):

mysql> SET NAMES utf8mb4;

Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL innodb_ft_aux_table = 'mysql_tech_note/ft_note_demo';

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT WORD, DOC_COUNT, DOC_ID, POSITION
    -> FROM information_schema.INNODB_FT_INDEX_CACHE
    -> WHERE WORD IN ('데이', '이터', '터베', '베이', '이스')
    -> ORDER BY WORD, DOC_ID, POSITION;

+--------+-----------+--------+----------+
| WORD   | DOC_COUNT | DOC_ID | POSITION |
+--------+-----------+--------+----------+
| 데이 |         2 |      2 |        6 |
| 데이 |         2 |      3 |       10 |
| 베이 |         2 |      2 |       15 |
| 베이 |         2 |      3 |       19 |
| 이스 |         2 |      2 |       18 |
| 이스 |         2 |      3 |       22 |
| 이터 |         2 |      2 |        9 |
| 이터 |         2 |      3 |       13 |
| 터베 |         2 |      2 |       12 |
| 터베 |         2 |      3 |       16 |
+--------+-----------+--------+----------+
10 rows in set (0.00 sec)

이 조회는 parser가 데이터베이스에서 기대한 bigram을 생성했는지 확인하는 진단 수단이다. 결과가 비어 있다면 다음을 순서대로 점검한다.

  1. innodb_ft_aux_table의 database/table 이름이 정확한가.
  2. 테이블의 Fulltext index에 WITH PARSER ngram이 지정되었는가.
  3. ngram_token_size가 예상한 값인가.
  4. transaction commit과 Fulltext index 동기화 상태를 고려했는가.
  5. stopword 또는 collation 규칙이 token에 영향을 주었는가.

진단을 마치면 전역 보조 테이블 지정을 해제하고 예제 테이블을 정리한다.

SET GLOBAL innodb_ft_aux_table = NULL;
DROP TABLE ft_note_demo;

실행 결과(MySQL 8.0.x):

mysql> SET GLOBAL innodb_ft_aux_table = NULL;

Query OK, 0 rows affected (0.00 sec)

mysql> DROP TABLE ft_note_demo;

Query OK, 0 rows affected (0.01 sec)

6. ngram parser가 해결하지 못하는 검색 품질 문제

6.1 형태소와 의미를 이해하지 않는다

ngram은 연속된 문자 조각을 만들 뿐 명사, 동사, 조사, 어근을 구분하지 않는다. 장애를 분석했다장애 분석은 공통 bigram 덕분에 일부 일치할 수 있지만, 고장, 장애, failure를 동의어로 연결하지 않는다. 검색어 확장이나 동의어 사전은 애플리케이션 계층 또는 전문 검색 시스템에서 별도로 구현해야 한다.

6.2 짧은 검색어와 낮은 precision

ngram_token_size=2에서 한 글자 검색은 색인 token보다 짧다. 반대로 1로 줄이면 한 글자 token이 매우 많은 문서에 등장해 후보 집합과 posting 정보가 커지고 의미 없는 일치가 늘 수 있다. “한 글자 검색을 지원해야 한다”는 요구는 token 크기만 변경할 문제가 아니라 자동완성, prefix 사전, 별도 검색 컬럼 같은 설계를 함께 검토할 사안이다.

6.3 띄어쓰기와 Unicode 정규화

ngram은 공백을 경계로 한 기본 parser보다 띄어쓰기 변화에 강할 수 있지만 모든 경우를 동등하게 만든다는 뜻은 아니다. 입력 단계에서 다음 정규화 정책을 일관되게 적용하는 것이 중요하다.

  • Unicode normalization form 통일
  • 불필요한 연속 공백과 제어 문자 정리
  • 제품 정책에 따른 영문 대소문자와 기호 처리
  • 검색 전용 정규화 컬럼을 둘 경우 원문 보존

Collation은 문자열 비교 규칙에 영향을 준다. utf8mb4_0900_ai_ciai, ci 특성이 필요한지, 기호와 영문 모델명을 엄격히 구분해야 하는지 실제 데이터로 확인해야 한다.

6.4 stopword의 예상 밖 영향

Fulltext 검색에는 흔한 단어를 제외하기 위한 stopword가 적용될 수 있다. ngram에서는 stopword 문자열을 포함하는 token이 제거되어 예상보다 넓은 영향을 줄 수 있다. 사용자 정의 stopword 정책을 도입했다면 정책 변경 후 index 재구축이 필요한지 확인하고, 검색 실패 사례에서 stopword를 반드시 점검한다.

6.5 랭킹과 결과 설명 가능성

MySQL의 관련도 score는 편리하지만 사용자 행동, 최신성, 필드별 가중치, 비즈니스 우선순위를 모두 반영하는 검색 랭커가 아니다. 다음과 같은 복합 랭킹 요구가 생기면 SQL 식을 계속 덧붙이기보다 검색 시스템 분리를 검토한다.

  • 제목 일치를 본문 일치보다 강하게 가중
  • 최신 문서와 인기 문서를 함께 반영
  • 개인화 또는 권한별 boost
  • 오탈자 허용과 유사어 확장
  • 검색 결과 하이라이트와 facet 집계

7. 저장 공간과 쓰기 경로의 운영 비용

Fulltext index는 원문 컬럼 외에 token과 posting 정보를 유지한다. 따라서 읽기 성능만 보고 도입하면 다음 비용을 놓치기 쉽다.

  • 대량 INSERTUPDATE 시 parser 실행 및 역색인 변경 비용
  • 본문 수정이 잦을 때 발생하는 삭제·재색인 작업
  • Fulltext auxiliary table과 캐시가 차지하는 저장 공간 및 메모리
  • 대량 적재 후 index 생성 또는 기존 index 유지 적재 중 어느 쪽이 유리한지에 대한 배치 전략
  • index rebuild 동안의 DDL 시간, 임시 공간, redo/undo 및 복제 영향
  • backup, restore, logical migration에 추가되는 데이터량과 시간

Fulltext index를 추가하기 전에는 대표 크기의 복제 데이터로 다음 수치를 비교해야 한다.

  1. index 생성 전후 테이블 크기
  2. 대표 검색어의 p50/p95 지연 시간과 반환 후보 수
  3. 본문 입력·수정 처리량과 transaction 지연
  4. DDL/rebuild 시간과 필요한 여유 공간
  5. replica 또는 변경 전파 지연
  6. 검색 품질 표본의 precision과 recall

LIKE '%...%'보다 빨라졌다는 단일 결과만으로 운영 적합성을 판단해서는 안 된다.

8. Aurora MySQL에서의 해석

Aurora MySQL은 MySQL 호환 SQL 계층을 제공하지만 저장 계층과 고가용성 구조는 Community MySQL과 다르다. Fulltext index의 SQL 사용법이 호환되더라도 다음 사항은 별도로 검증해야 한다.

  • 사용 중인 Aurora MySQL engine version에서 ngram parser와 필요한 Fulltext 기능을 지원하는가.
  • ngram_token_size를 DB cluster parameter group 또는 DB parameter group 중 어디에서 관리하며 적용 유형이 static인가.
  • 값 변경과 instance 재시작 또는 failover 이후 writer와 reader가 동일한 설정을 유지하는가.
  • 대규모 index 생성·재구축이 writer 부하, I/O, replica lag, failover 시간에 미치는 영향은 어느 정도인가.
  • reader endpoint로 검색을 분산할 때 애플리케이션이 허용할 수 있는 가시성 지연과 failover 동작은 무엇인가.

Aurora의 분산 저장 구조가 Fulltext 검색 품질 문제를 해결해 주지는 않는다. 검색 트래픽과 쓰기 증폭이 커지면 reader 확장만으로 충분한지, Amazon OpenSearch Service 같은 별도 검색 계층과 변경 데이터 전달 구조가 필요한지 비교해야 한다. 서비스 문서와 실제 engine version에서 parser 지원 및 parameter 적용 방식을 확인한 뒤 결정하는 것이 안전하다.

9. 장애와 성능 저하 시 진단 순서

검색 결과 누락과 검색 지연은 서로 다른 문제다. 먼저 증상을 분류한 뒤 다음 순서로 접근한다.

결과가 누락될 때

  1. 원문과 검색어의 실제 Unicode code point 및 정규화 상태를 확인한다.
  2. DDL의 WITH PARSER ngram과 현재 ngram_token_size를 확인한다.
  3. Natural language/Boolean mode 차이를 제거하기 위해 단순 검색어로 비교한다.
  4. stopword, collation, 검색 컬럼 목록을 확인한다.
  5. INNODB_FT_INDEX_TABLE에서 기대 token의 존재를 확인한다.
  6. 설정 변경 후 index rebuild가 누락되지 않았는지 확인한다.

검색이 느릴 때

  1. EXPLAIN에서 fulltext access와 사용 key를 확인한다.
  2. 검색어별 후보 문서 수와 반환 행 수를 구분한다.
  3. Fulltext 조건 뒤에 적용되는 권한·상태 필터와 정렬을 확인한다.
  4. OFFSET pagination과 전체 결과 count 요구를 점검한다.
  5. 동시 검색과 본문 수정 부하를 분리해 측정한다.
  6. buffer pool, CPU, 임시 테이블, I/O, connection 대기를 함께 관찰한다.

Fulltext access가 선택되더라도 매우 흔한 token은 큰 posting 목록을 만들 수 있다. LIMIT 20은 최종 반환 행만 줄일 뿐 후보 평가와 정렬이 항상 20건으로 제한된다는 뜻이 아니다.

10. 도입 판단 체크리스트

기능 요구

설계와 검증

  • 대상 버전에서 ngram plugin과 ngram_token_size
  • Fulltext index DDL에 WITH PARSER ngram

운영 준비

11. 결론

MySQL Fulltext index는 %검색어% 형태의 전체 스캔을 줄이고 데이터베이스 안에서 비교적 간단한 본문 검색을 제공한다. 한글에서는 ngram parser가 기본 parser의 단어 경계 한계를 완화하지만, 그 본질은 고정 길이 문자 조각을 이용한 역색인이다. 형태소, 동의어, 오탈자, 정교한 랭킹을 이해하는 검색 엔진으로 오해해서는 안 된다.

운영 도입의 출발점은 기본값을 그대로 적용하는 것이 아니라 실제 문서·검색어 정답 세트로 token 크기, 검색 품질, index 크기, 쓰기 비용을 함께 측정하는 것이다. 요구가 단순하고 데이터 규모가 관리 가능하면 ngram Fulltext index가 실용적인 선택이 될 수 있다. 반대로 검색이 제품의 핵심 기능이고 품질·분석·확장 요구가 빠르게 커진다면 MySQL에는 원본과 transaction을 맡기고 전문 검색 계층을 분리하는 편이 더 안정적이다. 이후 기술노트에서는 공간·다중값·함수 기반 index처럼 B+Tree 외의 특수 index를 각각 어떤 조건에서 선택해야 하는지 이어서 다룬다.