fix: 리서치 재작성 — MeCab-ko 비권장, pg_trgm 1순위로 전환

- MeCab-ko: 2026년 유지보수 중단, 사전 노후, PG14 EOL 고려 → 비권장
- pg_trgm: 키워드 축 복구용 병렬 매칭 엔진으로 재정의 (우회가 아님)
- 로빙이 이미 pgvector+하이브리드 운용 중이라는 현실 반영

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
happybell80 2026-03-22 10:32:00 +09:00
parent 27ca166bcf
commit 7388e720d3

View File

@ -1,86 +1,97 @@
---
type: research
tags: [research, rag, korean, mecab, pg_trgm, fts, postgresql]
tags: [research, rag, korean, mecab, pg_trgm, fts, postgresql, hybrid-search, reranking]
status: open
research_target: 한국어 키워드 검색의 근본 해결책 비교 — MeCab-ko 형태소 분석 vs pg_trgm 물리적 보완
research_target: 한국어 키워드 검색의 근본 해결책 재평가 — MeCab-ko의 2026년 현실, pg_trgm, 하이브리드+리랭킹 패러다임 전환
---
# 260323 한국어 키워드 검색 근본 해결 — MeCab vs pg_trgm 리서치
# 260323 한국어 키워드 검색 근본 해결 리서치 (2차)
## 목적
- keyword 단독 검색 0건의 근본 원인(simple 토크나이저 한국어 한계)에 대한 해결책을 비교한다.
- "근본 해결"과 "물리적 보완"을 명확히 구분한다.
- keyword 단독 검색 0건의 근본 원인에 대한 해결책을 재평가한다.
- MeCab-ko의 2026년 현실(유지보수 중단, 사전 노후)을 반영한다.
- 현재 로빙이 **이미 pgvector + 하이브리드 검색을 운용 중**이라는 사실을 전제로, 키워드 축만 보완하는 방향을 정한다.
## 근본 원인 (확정)
## 근본 원인 (확정, 변경 없음)
PostgreSQL `simple` 토크나이저는 공백 기준 토큰화만 수행. 한국어 교착어 특성(조사 결합, 복합명사)으로 lexeme이 검색어와 구조적으로 불일치.
PostgreSQL `simple` 토크나이저의 한국어 구조적 한계. 공백 기준 토큰화로 조사 결합·복합명사가 하나의 lexeme이 되어 검색어와 불일치.
이것은 검색 로직 버그가 아니라 **분석기 자체의 언어적 한계**다.
## MeCab-ko의 2026년 현실
## 해결책 비교
- **사실상 유지보수 중단 상태**. 한국어 신조어, 복합 명사에 대한 사전 업데이트가 멈춤.
- Company X 고유명사(투자조합명, 기업명)를 사전에 추가하려면 직접 관리해야 함.
- PG14 EOL(2026-11) 이후 PG16 마이그레이션 시 `textsearch_ko` 빌드 호환성 미보장.
- 최신 Python 기반 토크나이저(Kiwi 등)나 Rust 기반 대안이 등장했으나, DB 엔진 레벨 통합은 별도 개발 필요.
- **결론: DB 엔진 레벨에서 MeCab-ko에 의존하는 것은 과거의 유산에 시스템의 운명을 맡기는 것.**
### MeCab-ko 형태소 분석기 (근본 해결)
## 로빙의 현재 검색 구조 (이미 구현)
**원리**: 한국어를 의미 단위로 해체. 조사/어미를 제거하고 어간만 lexeme으로 저장.
로빙은 이미 다음을 운용 중이다:
| 기술 | 역할 | 상태 |
|------|------|------|
| pgvector (768d, Gemini) | 벡터 의미 검색 | ✅ 운용 중 |
| tsvector (simple + prefix) | 키워드 검색 | ⚠️ 부분 동작 (한국어 한계) |
| Apache AGE | 그래프 관계 확장 | ✅ 운용 중 |
| RRF 합산 + 정규화 | 하이브리드 점수 통합 | ✅ 운용 중 |
| 파일명 보조 검색 | 이미지 PDF 보완 | ✅ 운용 중 |
**현재 hybrid 모드에서 17/17 통과(100%).** 벡터 검색이 키워드의 빈자리를 메우고 있음.
문제는 **keyword 단독 축이 죽어 있어 하이브리드의 한 축이 기여하지 못한다**는 것. 벡터가 못 잡는 고유명사·정확 매칭에서 keyword가 보완해야 하는데 그 역할을 못 함.
## 해결책 재평가
### ~~1순위: MeCab-ko~~ → 비권장
- 2026년 현실에서 MeCab-ko를 새로 도입하는 것은 시간 대비 효과가 낮음
- 사전 관리 부담, PG14 EOL, 유지보수 중단 상태
- 이미 벡터 검색이 의미론적 매칭을 담당하고 있어 형태소 분석의 가치가 상대적으로 하락
### 1순위: pg_trgm (키워드 축 복구)
- `CREATE EXTENSION pg_trgm` + `GIN(gin_trgm_ops)` 인덱스
- 형태소 분석 없이 3-gram 글자 단위 매칭으로 0건 방지
- 기존 RRF 합산에 trgm similarity를 추가 축으로 편입
- **이것은 "토크나이저를 교체"하는 것이 아니라 "키워드 매칭 경로를 추가"하는 것**
- simple 토크나이저의 한계를 우회하는 것이 아니라, **다른 매칭 엔진을 병렬로 붙이는 것**
| 항목 | 내용 |
|------|------|
| 방식 | `textsearch_ko` 확장 + MeCab-ko 사전 |
| Recall | 100% (조사/복합어 완벽 분리) |
| Precision | 높음 (의미 단위 매칭) |
| 설치 비용 | 높음 (23서버 OS에 MeCab + 한국어 사전 설치, PG 확장 빌드) |
| 유지 비용 | 사전 업데이트 필요 (신조어, 고유명사) |
| PG14 호환 | 가능하나 EOL(2026-11) 고려 |
| 성능 | tsvector 기반이므로 GIN 인덱스 활용, FTS와 동일 속도 |
**적용 시 변경**:
- tsvector 트리거: `to_tsvector('simple', ...)``to_tsvector('korean', ...)`
- tsquery: `to_tsquery('simple', ...)``to_tsquery('korean', ...)`
- 기존 tsvector 전수 재생성 필요
### pg_trgm (물리적 보완)
**원리**: 텍스트를 3글자 단위로 기계적으로 쪼개 인덱싱. 언어 구조를 모름.
| 항목 | 내용 |
|------|------|
| 방식 | `CREATE EXTENSION pg_trgm` + `GIN(gin_trgm_ops)` |
| Recall | 높음 (글자 조각 매칭, 0건 방지) |
| Precision | 낮음 (짧은 검색어에서 노이즈. "차" 검색 시 "자동차", "차차차" 모두 히트) |
| Precision | 중간 (짧은 검색어에서 노이즈, 긴 검색어에서 정확) |
| 설치 비용 | 낮음 (`CREATE EXTENSION` 1줄) |
| 유지 비용 | 인덱스 크기 증가, INSERT 시 인덱스 업데이트 부하 |
| PG14 호환 | 기본 내장 |
| 성능 | similarity 계산 시 FTS보다 느림. ILIKE 인덱싱은 빠름 |
**적용 시 변경**:
- `chunk_text` 컬럼에 `GIN(gin_trgm_ops)` 인덱스 추가
- 검색 쿼리에 `similarity(chunk_text, :query)` 또는 `chunk_text ILIKE '%keyword%'` 추가
- 기존 tsvector 경로는 그대로 유지, 병렬 축으로 추가
### 2순위: Cross-Encoder 리랭킹
## 판단
- pgvector + pg_trgm이 후보를 뽑으면, LLM/Cross-Encoder가 최종 관련성을 재판정
- 현재 LLM이 `_call_llm_companyx_grounding()`에서 이미 하고 있음 (컨텍스트 보고 답변 가능 여부 판단)
- 검색 단계의 리랭킹(검색 결과 재정렬)은 아직 미구현
| 기준 | MeCab-ko | pg_trgm |
|------|----------|---------|
| 근본 해결 여부 | **근본 해결** | 물리적 보완 |
| 0건 방지 | ✅ | ✅ |
| 정확도 | 높음 | 낮음 |
| 설치 난이도 | 높음 | 낮음 |
| 장기 유지 | 사전 관리 필요 | 인덱스 크기 관리 |
### 장기: 검색 패러다임
**최종 목표**: MeCab-ko + pg_trgm 하이브리드
**현실적 1단계**: pg_trgm 먼저 적용 (0건 즉시 방지) → MeCab-ko 후속 도입
2026년 검색 표준은 **BM25(키워드) + Vector(의미) 하이브리드 + 리랭킹**이다. 로빙은 이미 Vector + 하이브리드 구조를 가지고 있고, 키워드 축만 pg_trgm으로 복구하면 이 표준에 근접한다.
단, pg_trgm 적용 시 "이것은 근본 해결이 아니라 물리적 보완이다"를 문서와 코드에 명시한다.
## 최종 판단
| 기준 | MeCab-ko | pg_trgm | 현재 벡터(pgvector) |
|------|----------|---------|-------------------|
| 2026년 권장 | ❌ 비권장 | ✅ 키워드 축 복구 | ✅ 이미 운용 중 |
| 0건 방지 | ✅ | ✅ | ✅ (의미 매칭) |
| 고유명사 정확 매칭 | 사전 의존 | ✅ (글자 매칭) | ❌ (의미 유사도) |
| 설치/유지 | 높음/높음 | 낮음/낮음 | 완료 |
**결론: pg_trgm을 키워드 축으로 추가하고 기존 RRF에 편입. MeCab-ko는 도입하지 않는다.**
## Unresolved
- MeCab-ko의 PG14 EOL(2026-11) 이후 PG16 마이그레이션과 동시 도입이 합리적인지
- pg_trgm 인덱스 크기가 3,474 청크 → 5만 청크 확장 시 어느 수준인지
- MeCab 사전에 Company X 고유명사(투자조합명, 기업명) 추가 가능 여부
- pg_trgm 인덱스 크기가 3,474 → 5만 청크 확장 시 어느 수준인지
- trgm similarity threshold 최적값 (0.1? 0.3?)
- Cross-Encoder 리랭킹 도입 시점과 모델 선택
## 관련 문서
- [260323 keyword 단독 검색 0건 트러블](../../troubleshooting/260323_companyx_rag_keyword_단독검색_전질의_0건.md)
- [260323 PostgreSQL simple FTS 한국어 한계 요약](./260323_PostgreSQL_simple_FTS_한국어_키워드검색_한계_및_대안_요약.md)
- [PostgreSQL pg_trgm 공식 문서](https://www.postgresql.org/docs/current/pgtrgm.html)