> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sifi.life/llms.txt
> Use this file to discover all available pages before exploring further.

# 한국어 RAG의 과제 & Kiwi 형태소 분석

> 이 문서는 **[한국어 RAG 최적화](/blog/guides/rag/korean-nlp)** 의 일부입니다.

한국어는 영어와 매우 다른 언어 구조를 가지고 있어, RAG 파이프라인의 각 단계에서 특별한 고려가 필요합니다.

## 1. 한국어 RAG의 과제

### 한국어 RAG의 구조적 어려움

한국어 RAG는 영어 RAG와 근본적으로 다른 문제를 해결해야 합니다. 이는 한국어의 **언어학적 특성** 에서 비롯됩니다.

**1. 교착어 (Agglutinative Language) 특성**

한국어는 어근에 조사, 어미, 접사가 결합하여 하나의 단어를 형성합니다. 영어가 단어 순서(어순)로 문법적 관계를 표현하는 것과 달리, 한국어는 **접사의 결합** 으로 표현합니다. 이로 인해 동일한 의미의 단어가 수십 가지 형태로 변화합니다.

```
"데이터브릭스" (원형)
→ "데이터브릭스가" (주격), "데이터브릭스를" (목적격)
→ "데이터브릭스에서" (처소격), "데이터브릭스의" (관형격)
→ "데이터브릭스로" (도구격), "데이터브릭스와" (공동격)
→ 영어: "Databricks" 하나의 형태로 모든 문법적 관계 표현
```

**2. 띄어쓰기 불규칙성**

한국어는 띄어쓰기 규칙이 복잡하고, 실제 문서에서 띄어쓰기 오류가 빈번합니다. "데이터 분석"과 "데이터분석"이 혼재하는 경우가 많아, 공백 기반 토큰화에 의존하면 검색 품질이 저하됩니다.

**3. 한영 혼용 텍스트**

한국어 기술 문서에는 영어 용어가 빈번하게 등장합니다. "Databricks 워크스페이스에서 Delta Lake 테이블을 생성합니다"처럼 **한국어와 영어가 한 문장에 혼재** 합니다. 단일 언어 모델로는 양쪽 모두를 잘 처리하기 어렵습니다.

**4. 상대적으로 적은 학습 데이터**

대부분의 임베딩 모델과 LLM은 영어 데이터로 주로 학습됩니다. 한국어 데이터의 비중은 전체 학습 데이터의 1\~3%에 불과한 경우가 많아, 한국어에 대한 **의미 표현 능력이 영어보다 떨어질 수 있습니다**.

### 이 문제들이 RAG에 미치는 실제 영향

위 특성들이 결합되면, 영어 기준으로 설계된 RAG 파이프라인은 한국어에서 심각한 성능 저하를 겪습니다:

* **BM25 키워드 검색 실패**: 조사가 붙은 채로 토큰화되어 "데이터브릭스에서" ≠ "데이터브릭스를"로 처리됨
* **토큰 비용 급증**: 일반 토크나이저(tiktoken, SentencePiece)로 한국어를 처리하면 영어 대비 **2\~3배 많은 토큰** 소비
* **임베딩 품질 저하**: 한국어 학습 데이터 부족으로 의미 벡터의 정밀도가 떨어질 수 있음

이 문제들의 해결책은 다음 섹션에서 다루는 **형태소 분석** 에서 시작됩니다.

> **주의**
> 한국어 RAG에서 가장 흔한 실수는 영어 기준 파이프라인을 그대로 적용하는 것입니다. 특히 BM25 기반 키워드 검색은 형태소 분석 없이는 한국어에서 제대로 작동하지 않습니다.

## 2. Kiwi 한국어 형태소 분석기

### 형태소 분석이란? — 한국어 RAG의 핵심 전처리

**형태소(Morpheme)** 는 의미를 가진 최소 언어 단위입니다. 영어에서는 단어 사이의 공백(space)이 곧 의미 단위의 경계이지만, 한국어는 하나의 **어절(띄어쓰기 단위)** 안에 여러 형태소가 결합되어 있습니다. 형태소 분석은 이 어절을 의미 단위로 분해하는 작업입니다.

```
영어: "I   love   Databricks"   → 공백으로 나누면 3개 단어, 각각이 의미 단위
한국어: "데이터브릭스에서"         → 1개 어절이지만, 2개 형태소
       → "데이터브릭스" (고유명사, 의미 핵심) + "에서" (조사, 문법 기능)
```

**형태소 분석이 앞서 언급한 문제를 어떻게 해결하는가?**

섹션 1에서 설명한 교착어 특성 — "데이터브릭스에서", "데이터브릭스를", "데이터브릭스의"가 모두 다른 토큰으로 처리되는 문제 — 의 해결책이 바로 형태소 분석입니다. 핵심 아이디어는 간단합니다: **어절을 형태소로 분해한 뒤, 의미를 담당하는 형태소(명사, 동사 등)만 추출하고 문법 기능만 하는 형태소(조사, 어미)는 버리는 것** 입니다.

```
형태소 분석 + 의미 형태소 추출:
  "데이터브릭스에서" → [데이터브릭스, 에서] → "데이터브릭스" ✓
  "데이터브릭스를"   → [데이터브릭스, 를]   → "데이터브릭스" ✓
  "데이터브릭스의"   → [데이터브릭스, 의]   → "데이터브릭스" ✓
  → 조사가 달라도 동일한 검색 토큰으로 통일!
```

이 처리는 BM25 키워드 검색뿐 아니라 **하이브리드 검색** 전체의 품질을 높입니다. BM25 쪽의 품질이 떨어지면 앙상블 가중치를 아무리 조정해도 최종 검색 성능이 제한되기 때문입니다.

**형태소 분석의 동작 원리:**

형태소 분석기는 단순한 규칙 기반이 아닌 **확률 모델** 을 사용하여 어절을 분해합니다:

1. **사전 탐색**: 내장 사전에서 가능한 형태소 조합 후보를 탐색합니다. 예를 들어 "구축했습니다"는 "구축+했+습니다"로도, "구+축했+습니다"로도 분해할 수 있습니다.
2. **확률 모델 적용**: 여러 후보 중 **가장 자연스러운 조합** 을 통계적으로 선택합니다. 대규모 한국어 코퍼스에서 학습된 확률 분포를 기반으로, "구축+했+습니다"가 훨씬 자연스러운 분해임을 판단합니다.
3. **미등록어 처리**: 사전에 없는 신조어(예: "데이터브릭스", "레이크하우스")도 주변 문맥과 문자 패턴을 기반으로 품사를 추정합니다. 이 능력이 기술 문서 처리에서 특히 중요합니다.

다음은 실제 분석 과정의 예시입니다:

```
입력: "데이터브릭스에서 머신러닝 파이프라인을 구축했습니다"

분석 결과:
  데이터브릭스 (NNP, 고유명사) — 의미 핵심 ✓
  에서       (JKB, 부사격 조사) — 문법 기능, 검색에 불필요
  머신러닝    (NNG, 일반명사) — 의미 핵심 ✓
  파이프라인   (NNG, 일반명사) — 의미 핵심 ✓
  을         (JKO, 목적격 조사) — 문법 기능, 검색에 불필요
  구축       (NNG, 일반명사) — 의미 핵심 ✓
  했         (XSA, 과거 시제 접사) — 문법 기능, 검색에 불필요
  습니다      (EF, 종결 어미) — 문법 기능, 검색에 불필요

→ 검색용 토큰: ["데이터브릭스", "머신러닝", "파이프라인", "구축"]
```

RAG에서는 **명사(NNG, NNP)**, **동사 어근(VV)**, **형용사 어근(VA)**, **외국어(SL)** 만 추출하여 검색에 사용합니다. 조사, 어미 등 문법 기능 형태소를 제거함으로써 **핵심 의미만으로 매칭** 할 수 있게 됩니다.

### Kiwi란?

**Kiwi** 는 C++ 기반의 고속 한국어 형태소 분석기입니다. 다른 한국어 형태소 분석기(KoNLPy의 Mecab, Komoran 등)와 비교했을 때 **정확도와 속도 모두** 뛰어나며, 특히 신조어와 미등록어 처리에 강합니다. Python 바인딩(`kiwipiepy`)을 통해 쉽게 사용할 수 있습니다.

| 형태소 분석기          | 속도          | 정확도 | 설치 편의성            | 미등록어 처리  |
| ---------------- | ----------- | --- | ----------------- | -------- |
| **Kiwi**         | 매우 빠름 (C++) | 높음  | `pip install` 한 줄 | 통계 기반 추정 |
| Mecab (KoNLPy)   | 빠름 (C)      | 높음  | 시스템 의존성 복잡        | 사전 추가 필요 |
| Komoran (KoNLPy) | 보통 (Java)   | 보통  | JVM 필요            | 사전 추가 필요 |
| Okt (KoNLPy)     | 느림 (Java)   | 보통  | JVM 필요            | 제한적      |

Kiwi를 권장하는 이유는 **Databricks 환경과의 호환성** 때문이기도 합니다. 순수 Python 패키지로 설치되므로 클러스터에 별도 시스템 라이브러리를 설치할 필요가 없고, UDF로 감싸 대규모 배치 처리에도 사용할 수 있습니다.

### 설치

```bash theme={null}
pip install kiwipiepy
```

### 기본 사용법

```python theme={null}
from kiwipiepy import Kiwi

kiwi = Kiwi()

# 형태소 분석
result = kiwi.tokenize("Databricks에서 RAG 파이프라인을 구축합니다")
for token in result:
    print(f"{token.form}\t{token.tag}\t{token.start}-{token.end}")
# Databricks  NNP    0-11
# 에서         JKB    11-13
# RAG          SL     14-17
# 파이프라인    NNG    18-23
# 을           JKO    23-24
# 구축         NNG    25-27
# 합니다       XSV+EF 27-30
```

### 주요 품사 태그

| 태그       | 의미   | 예시                        |
| -------- | ---- | ------------------------- |
| **NNG**  | 일반명사 | 파이프라인, 구축, 데이터            |
| **NNP**  | 고유명사 | Databricks, Unity Catalog |
| **VV**   | 동사   | 구축하다, 배포하다                |
| **VA**   | 형용사  | 빠르다, 정확하다                 |
| **SL**   | 외국어  | RAG, LLM, API             |
| **JK\*** | 조사   | 에서, 을, 의                  |
| **E\***  | 어미   | 합니다, 했습니다                 |

***

<CardGroup cols={2}>
  <Card title="다음: BM25 검색 & 청킹 전략" href="korean-nlp-advanced">
    Kiwi 기반 BM25 Retriever, 하이브리드 검색(RRF), 한국어 청킹 전략
  </Card>

  <Card title="임베딩 모델 & 베스트 프랙티스" href="korean-nlp-embedding">
    한국어 임베딩 모델 선택, Re-ranking, 트러블슈팅
  </Card>
</CardGroup>
