korean-search-utils
Version:
한글 초성 검색 및 React 훅 지원 라이브러리
130 lines (95 loc) • 3.81 kB
Markdown
React 기반 프로젝트에서 **한글 검색**을 지원하는 유틸리티 함수와 커스텀 훅입니다.
- 한글 자모 분리 (`disassembleHangul`)
- 초성/중성/종성 fuzzy 검색 (`isMatch`)
- 매칭 구간 하이라이팅 세그먼트 반환 (`getMatchSegments`) — v1.1.0
- React 없이 쓸 수 있는 필터+정렬 유틸 (`filterAndSort`) — v1.1.0
- React 커스텀 훅 (`useKoreanSearch`)
- ESM + CJS 듀얼 빌드 지원 — v1.1.0
```bash
npm install korean-search-utils
```
```tsx
import { useKoreanSearch } from "korean-search-utils";
const fruits = [
{ name: "사과 apple" },
{ name: "오렌지 orange" },
{ name: "바나나 banana" },
];
function FruitSearch() {
const { searchTerm, setSearchTerm, filteredItems, resetSearch } =
useKoreanSearch(fruits, (fruit) => fruit.name);
return (
<div>
<input
placeholder="과일 검색 (ㅅㄱ, 바나, apple...)"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<button onClick={resetSearch}>초기화</button>
<ul>
{filteredItems.map((fruit) => (
<li key={fruit.name}>{fruit.name}</li>
))}
</ul>
</div>
);
}
```
```tsx
import { getMatchSegments } from "korean-search-utils";
const segments = getMatchSegments("사과 apple", "ㅅ");
// → [{ text: "사", matched: true }, { text: "과 apple", matched: false }]
// 하이라이팅 렌더링 예시
segments.map((seg) =>
seg.matched ? <mark>{seg.text}</mark> : <span>{seg.text}</span>
);
```
```ts
import { filterAndSort } from "korean-search-utils";
const fruits = ["사과", "바나나", "오렌지", "딸기", "수박"];
filterAndSort(fruits, "ㅅ", (x) => x);
// → ["사과", "수박"] (ㅅ으로 시작하는 항목, 매칭 위치 순 정렬)
filterAndSort(fruits, "바나", (x) => x);
// → ["바나나"]
```
```ts
import { disassembleHangul, isMatch, getMatchStartIndex, getMatchScore } from "korean-search-utils";
disassembleHangul("사과"); // "ㅅㅏㄱㅘ"
disassembleHangul("한글 hangul"); // "ㅎㅏㄴㄱㅡㄹhangul"
isMatch("사과", "ㅅㄱ"); // true
isMatch("바나나", "ㅂㄴ"); // true
isMatch("딸기", "포도"); // false
getMatchStartIndex("사과", "ㅅ"); // 0 (자모 기준 인덱스)
getMatchStartIndex("사과", "없음"); // -1
getMatchScore("사과", "ㅅ"); // 숫자 (낮을수록 상위)
getMatchScore("사과", "포도"); // Infinity (매칭 없음)
```
- 검색어가 더 **앞에서** 매칭되는 항목을 우선 정렬합니다.
- 같은 시작 위치라면 **짧은 문자열**이 우선됩니다.
```ts
const list = [{ name: "사과 오렌지" }, { name: "오렌지 사과" }];
filterAndSort(list, "ㅅㄱ", (x) => x.name);
// 1) "사과 오렌지" (매칭 시작 인덱스 0)
// 2) "오렌지 사과" (매칭 시작 인덱스 더 뒤)
```
| 함수 | 설명 |
|------|------|
| `disassembleHangul(str)` | 문자열을 자모로 분리 (공백 제거) |
| `isMatch(source, target)` | source가 target을 포함하는지 여부 |
| `getMatchStartIndex(source, target)` | 매칭 시작 자모 인덱스 (-1이면 불일치) |
| `getMatchScore(source, target)` | 매칭 품질 점수 (낮을수록 상위, 불일치 시 Infinity) |
| `getMatchSegments(source, target)` | 하이라이팅용 세그먼트 배열 반환 |
| `filterAndSort(items, target, getField)` | 필터+정렬 (React 불필요) |
| `useKoreanSearch(items, getField)` | React 커스텀 훅 |
MIT