Hangul.js

March 27, 2025 Β· View on GitHub

πŸ”” μœ μ§€λ³΄μˆ˜ 곡지

ν˜„μž¬ 이 ν”„λ‘œμ νŠΈλŠ” μ΅œμ†Œν•œμ˜ μœ μ§€λ³΄μˆ˜ μƒνƒœλ‘œ μ „ν™˜λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ½”λ“œλŠ” μ—¬μ „νžˆ μž‘λ™ν•˜μ§€λ§Œ, 개발 및 μ—…λ°μ΄νŠΈκ°€ μ€‘λ‹¨λœ μƒνƒœμž…λ‹ˆλ‹€.

μΆ”μ²œ λŒ€μ•ˆ: 더 ν™œλ°œν•˜κ²Œ κ΄€λ¦¬λ˜λŠ” μ†”λ£¨μ…˜μ„ μ°ΎμœΌμ‹œλŠ” 뢄듀은 es-hangul을 확인해 λ³΄μ‹œκΈ° λ°”λžλ‹ˆλ‹€. ν•΄λ‹Ή ν”„λ‘œμ νŠΈλŠ” 쑰사 μ™Έ λ‹€λ₯Έ ν•œκΈ€ κ΄€λ ¨ κΈ°λŠ₯듀도 μ œκ³΅ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

ν–₯ν›„ κ³„νš: 좔후에 κ°œλ°œμ„ μž¬κ°œν•  수 μžˆμ§€λ§Œ, ν˜„μž¬λ‘œμ„œλŠ” μ‚¬μš©μžλΆ„λ“€μ΄ ν•„μš”μ— κ°€μž₯ μ ν•©ν•œ 도ꡬλ₯Ό μ‚¬μš©ν•˜μ‹€ 수 μžˆλ„λ‘ μ•ˆλ‚΄ν•΄ λ“œλ¦¬κ³ μž ν•©λ‹ˆλ‹€. 이 μ €μž₯μ†ŒλŠ” μ°Έκ³  및 기둝 μš©λ„λ‘œ 계속 μœ μ§€λ  μ˜ˆμ •μž…λ‹ˆλ‹€. ν˜„μž¬ 이 ν”„λ‘œμ νŠΈλ₯Ό μ‚¬μš© μ€‘μ΄μ‹œκ³  ν•„μš”λ₯Ό μΆ©μ‘±ν•˜κ³  κ³„μ‹œλ‹€λ©΄ 계속 μ‚¬μš©ν•˜μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€λ§Œ, μƒˆλ‘­κ²Œ λ„μž…ν•˜λ € ν•˜μ‹ λ‹€λ©΄ μœ„μ—μ„œ μ–ΈκΈ‰ν•œ λŒ€μ•ˆμ„ κ²€ν† ν•΄ λ³΄μ‹œκΈ°λ₯Ό μΆ”μ²œλ“œλ¦½λ‹ˆλ‹€.

κ·Έλ™μ•ˆ 이 ν”„λ‘œμ νŠΈλ₯Ό μ§€μ›ν•˜κ³  κΈ°μ—¬ν•΄ μ£Όμ‹  λͺ¨λ“  λΆ„λ“€κ»˜ κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€.

Maintenance Notice: This project is currently in a low-maintenance state. For new implementations, we recommend checking out es-hangul which is actively maintained and offers more features. This repository will remain available for reference.

Hangul.js

Hangul.jsλŠ” ν•œκΈ€λ‘œ 이루어진 λ¬Έμž₯의 자음과 λͺ¨μŒμ„ λΆ„λ¦¬ν•˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€. 자λͺ¨ 뢄리 λ˜λŠ” μ΄ˆμ„± 검색에 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ„€μΉ˜ 및 μ‚¬μš©λ°©λ²•

node.js

npm install hangul-js
const Hangul = require('hangul-js');

TypeScript

npm install hangul-js
import * as Hangul from 'hangul-js';

일반 μ›Ή νŽ˜μ΄μ§€

μ›Ή νŽ˜μ΄μ§€μ—μ„œ μ‚¬μš©ν•˜λ €λ©΄ hangul.js νŒŒμΌμ„ <script>νƒœκ·Έλ₯Ό μ΄μš©ν•˜μ—¬ μ‚½μž…ν•©λ‹ˆλ‹€. AMD νŒ¨ν„΄μœΌλ‘œ 뢈러올 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

<script src="hangul.js" type="text/javascript"></script>

<!-- or from CDN -->
<script src="https://unpkg.com/hangul-js" type="text/javascript"></script>

μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œμ—μ„œ 전역에 λ…ΈμΆœλœ Hangulμ΄λΌλŠ” 객체λ₯Ό 톡해 μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Hangul // window.Hangul

λͺ…μ„Έ

Hangul.disassemble (alias Hangul.d)

Hangul.disassemble(str:string, grouped:boolean = false)은 λ¬Έμžμ—΄ str에 μžˆλŠ” ν•œκΈ€μ„ 자음/λͺ¨μŒμœΌλ‘œ λΆ„λ¦¬ν•˜μ—¬ λ¬Έμžλ“€μ˜ λ°°μ—΄λ‘œ λŒλ €μ€λ‹ˆλ‹€. 이 λ•Œ ν•œκΈ€μ΄ μ•„λ‹Œ λ¬ΈμžλŠ” κ·ΈλŒ€λ‘œ λ°˜ν™˜λ©λ‹ˆλ‹€. Hangul.d처럼 짧은 μ΄λ¦„μœΌλ‘œ μ‚¬μš©ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

Hangul.disassemble('κ°€λ‚˜λ‹€'); // ['γ„±','ㅏ','γ„΄','ㅏ','γ„·','ㅏ']

Hangul.disassemble('abκ°€c'); // ['a','b','γ„±','ㅏ','c']

Hangul.disassemble('ab@!23X.'); // ['a','b','@','!','2','3','X','.']

같은 ν™‘λ‚±μžλ‘œ 이루어진 κ²Ήλ‚±μžλŠ” λΆ„λ¦¬λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

Hangul.disassemble('γ„²'); // ['γ„²']

λ‹€λ₯Έ ν™‘λ‚±μžλ‘œ 이루어진 κ²Ήλ‚±μžλŠ” λΆ„λ¦¬λ©λ‹ˆλ‹€.

Hangul.disassemble('γ„³'); // ['γ„±','γ……']

Hangul.disassemble('γ…š'); // ['γ…—','γ…£']

μΆ”κ°€μ μœΌλ‘œ grouped μ˜΅μ…˜μ„ true둜 μ„€μ •ν•˜μ—¬ λ¬Έμžμ—΄μ˜ 각 κΈ€μžλ³„λ‘œ λ”°λ‘œ 뢄리할 수 μžˆμŠ΅λ‹ˆλ‹€.

Hangul.d('λ§€λ“œμΊ£MK2', true); 
// [['ㅁ', 'ㅐ'], ['γ„·', 'γ…‘'], ['γ…‹', 'ㅐ', 'γ……'], ['M'], ['K'], ['2']]

μœˆλ„μš°μ—μ„œ λ‘λ²Œμ‹ ν‚€λ³΄λ“œλ‘œ μ£Όμ–΄μ§„ λ¬Έμžμ—΄μ„ μž…λ ₯ν•  λ•Œ λˆ„λ₯΄λŠ” ν‚€λ“€μ˜ 배열이라고 μƒκ°ν•˜λ©΄ μ‰½μŠ΅λ‹ˆλ‹€.

Hangul.assemble (alias Hangul.a)

Hangul.assemble(arr:string[])λŠ” ν•œκΈ€ 자음/λͺ¨μŒλ“€μ˜ λ°°μ—΄ arr을 인자둜 λ°›μ•„ 이λ₯Ό μ‘°ν•©ν•œ λ¬Έμžμ—΄μ„ λŒλ €μ€λ‹ˆλ‹€. 이 λ•Œ ν•œκΈ€μ΄ μ•„λ‹Œ λ¬ΈμžλŠ” κ·ΈλŒ€λ‘œ λ°˜ν™˜λ©λ‹ˆλ‹€. Hangul.a처럼 짧은 μ΄λ¦„μœΌλ‘œ μ‚¬μš©ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

Hangul.assemble(['γ„±','ㅏ','γ„΄','ㅏ','γ„·','ㅏ']); // 'κ°€λ‚˜λ‹€'

Hangul.assemble(['a','b','γ„±','ㅏ','c']); // 'abκ°€c'

Hangul.assemble(['a','b','@','!','2','3','X','.']); // 'ab@!23X.'

이 κ²½μš°μ—λ„ λ‘λ²Œμ‹ ν‚€λ³΄λ“œμ—μ„œ μ£Όμ–΄μ§„ 킀듀을 λˆ„λ₯Ό λ•Œ λ§Œλ“€μ–΄μ§€λŠ” λ¬Έμžμ—΄μ„ λŒλ €μ€€λ‹€κ³  μƒκ°ν•˜λ©΄ μ‰½μŠ΅λ‹ˆλ‹€.

Hangul.assemble(['γ…—','ㅐ']); // 'γ…™'

Hangul.assemble(['γ„Ή','γ…‚','γ……']); // 'γ„Όγ……'

Hangul.disassemble ν•¨μˆ˜μ™€ μ—­ν•¨μˆ˜ 관계가 μ•„λ‹˜μ— μ£Όμ˜ν•˜μ„Έμš”.

Hangul.a(Hangul.d('μ˜½γ…')); // 'μ˜€νƒ€' ('μ˜½γ…' κ°€ μ•„λ‹˜)

Hangul.search

Hangul.search(a:string, b:string)λŠ” λ¬Έμžμ—΄ aκ°€ λ¬Έμžμ—΄ bλ₯Ό ν¬ν•¨ν•˜λŠ”μ§€ κ²€μ‚¬ν•©λ‹ˆλ‹€. μ΄λ•Œ ν¬ν•¨κ΄€κ³„λŠ” 'λ‘λ²Œμ‹ ν‚€λ³΄λ“œ κΈ°μ€€μœΌλ‘œ aλ¬Έμžμ—΄μ„ μž…λ ₯ν•  λ•Œ λˆ„λ₯΄λŠ” ν‚€λ“€μ˜ 배열이 bλ¬Έμžμ—΄μ„ μž…λ ₯ν•  λ•Œ λˆ„λ₯΄λŠ” ν‚€λ“€μ˜ 배열을 ν¬ν•¨ν•œλ‹€'둜 μ •μ˜ν•©λ‹ˆλ‹€. λ°˜ν™˜κ°’μ΄ 0보닀 ν¬κ±°λ‚˜ κ°™λ‹€λ©΄ ν¬ν•¨ν•©λ‹ˆλ‹€.

Hangul.search('달걀','λ‹­'); // 0

Hangul.search('달걀','μ•Œ'); // -1

indexOfν•¨μˆ˜μ™€ λ‹€λ¦…λ‹ˆλ‹€.

let a = 'λ„μš°λ―Έ'
  , b = '도움';
  
a.indexOf(b); // -1

Hangul.search(a, b); // 0

μ‹€μ œ μ‚¬μš©ν•  λ•Œμ—λŠ” ν•˜λ‚˜μ˜ 단어λ₯Ό μ—¬λŸ¬κ°œμ˜ λ¬Έμžμ—΄κ³Ό λΉ„κ΅ν•˜λ―€λ‘œ Hangul.Searcherλ₯Ό μ‚¬μš©ν•˜λŠ”κ²Œ νŽΈν•©λ‹ˆλ‹€. λ‚΄λΆ€μ μœΌλ‘œ ν•œλ²ˆλ§Œ 자λͺ¨ 뢄리λ₯Ό μˆ˜ν–‰ν•˜λ―€λ‘œ νš¨μœ¨μ μž…λ‹ˆλ‹€.

let searcher = new Hangul.Searcher('λ‹­');

searcher.search('달걀'); // 0
searcher.search('달ꡬ지'); // 0
searcher.search('달무리'); // -1

Hangul.rangeSearch

Hangul.rangeSearch(a:string, b:string)λŠ” a λ¬Έμžμ—΄μ—μ„œ b λ¬Έμžμ—΄μ„ λͺ¨λ‘ μ°Ύκ³  μΌμΉ˜ν•˜λŠ” λ²”μœ„λ₯Ό a λ¬Έμžμ—΄ μƒμ˜ 인덱슀둜 λŒλ €μ€λ‹ˆλ‹€. λ§Œμ•½ b λ¬Έμžμ—΄μ„ μ°Ύμ§€ λͺ»ν–ˆλ‹€λ©΄ 빈 배열을 λŒλ €μ€λ‹ˆλ‹€. 검색 μ‹œμŠ€ν…œμ—μ„œ μΌμΉ˜ν•˜λŠ” 뢀뢄을 κ°•μ‘°ν•˜λ €κ³  ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€.

let a = 'κ°„μž₯곡μž₯곡μž₯μž₯',
    b = '곡μž₯';

Hangul.rangeSearch(a, b); // [[2, 3], [4, 5]]

기타 ν•œκΈ€ κ΄€λ ¨ ν•¨μˆ˜

μ΄ν•˜ ν•¨μˆ˜λ“€μ€ 인자둜 문자λ₯Ό λ°›μŠ΅λ‹ˆλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” 문자 νƒ€μž…μ΄ μ—†μœΌλ―€λ‘œ λ¬Έμžμ—΄λ‘œ λŒ€μ²΄ν•©λ‹ˆλ‹€. 길이가 2 이상인 λ¬Έμžμ—΄μ˜ 경우 첫 ν•œκΈ€μžμ— λŒ€ν•΄ νŒλ‹¨ν•©λ‹ˆλ‹€.

Hangul.isComplete(c)

μ£Όμ–΄μ§„ λ¬Έμžκ°€ μ™„μ„±λœ ν•œκΈ€μΈμ§€ μ•„λ‹Œμ§€ νŒλ‹¨ν•©λ‹ˆλ‹€. μ™„μ„±λœ ν•œκΈ€μ΄λž€ μœ λ‹ˆμ½”λ“œλ‘œ 'κ°€'(0xAC00) ~ '힣'(0xD7A3) 사이에 μžˆλŠ” 문자λ₯Ό λ§ν•©λ‹ˆλ‹€. 'γ„±', 'γ…™' 등은 μ™„μ„±λœ ν•œκΈ€μ΄ μ•„λ‹™λ‹ˆλ‹€. Hangul.isCompleteAll(str) ν˜•νƒœλ‘œ str의 λͺ¨λ“  λ¬Έμžκ°€ μ™„μ„±λœ ν•œκΈ€μΈμ§€ νŒλ‹¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Hangul.isConsonant(c)

μ£Όμ–΄μ§„ λ¬Έμžκ°€ μžμŒμΈμ§€ νŒλ‹¨ν•©λ‹ˆλ‹€. Hangul.isCosonantAll(str) ν˜•νƒœλ‘œ str의 λͺ¨λ“  λ¬Έμžκ°€ μžμŒμΈμ§€ νŒλ‹¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Hangul.isVowel(c)

μ£Όμ–΄μ§„ λ¬Έμžκ°€ λͺ¨μŒμΈμ§€ νŒλ‹¨ν•©λ‹ˆλ‹€. Hangul.isVowelAll(str) ν˜•νƒœλ‘œ str의 λͺ¨λ“  λ¬Έμžκ°€ λͺ¨μŒμΈμ§€ νŒλ‹¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Hangul.isCho(c)

μ£Όμ–΄μ§„ λ¬Έμžκ°€ μ΄ˆμ„±μœΌλ‘œ 쓰일 수 μžˆλŠ”μ§€ νŒλ‹¨ν•©λ‹ˆλ‹€. 'γ„²'은 μ΄ˆμ„±μœΌλ‘œ 쓰일 수 μžˆμ§€λ§Œ 'γ„³'λŠ” μ΄ˆμ„±μœΌλ‘œ 쓰일 수 μ—†μŠ΅λ‹ˆλ‹€. Hangul.isChoAll(str) ν˜•νƒœλ‘œ str의 λͺ¨λ“  λ¬Έμžκ°€ μ΄ˆμ„±μΈμ§€ νŒλ‹¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Hangul.isJong(c)

μ£Όμ–΄μ§„ λ¬Έμžκ°€ μ’…μ„±μœΌλ‘œ 쓰일 수 μžˆλŠ”μ§€ νŒλ‹¨ν•©λ‹ˆλ‹€. 'γ„²'은 μ’…μ„±μœΌλ‘œ 쓰일 수 μžˆμ§€λ§Œ 'γ„Έ'λŠ” μ’…μ„±μœΌλ‘œ 쓰일 수 μ—†μŠ΅λ‹ˆλ‹€. Hangul.isJongAll(str) ν˜•νƒœλ‘œ str의 λͺ¨λ“  λ¬Έμžκ°€ 쒅성인지 νŒλ‹¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Hangul.endsWithConsonant(c)

μ£Όμ–΄μ§„ λ¬Έμžκ°€ 자음으둜 λλ‚˜λŠ”μ§€ νŒλ‹¨ν•©λ‹ˆλ‹€. 받침이 μžˆκ±°λ‚˜ 자음 ν•˜λ‚˜κ°€ 인자둜 μ£Όμ–΄μ§€λ©΄ trueλ₯Ό μ•„λ‹Œ 경우 falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. ν•œκΈ€μ΄ μ•„λ‹Œ κ²½μš°λŠ” falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. 은/λŠ” 이/κ°€ ꡬ뢄에 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Hangul.endsWith(c, t)

μ£Όμ–΄μ§„ λ¬Έμžκ°€ t(νƒ€κ²Ÿ)으둜 λλ‚˜λŠ”μ§€ νŒλ‹¨ν•©λ‹ˆλ‹€. t둜 λλ‚˜λ©΄ trueλ₯Ό μ•„λ‹Œ 경우 falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. 둜/으둜 ꡬ뢄에 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

예제

여기에 μ£Όμ–΄μ§„ λ¬Έμž₯μ—μ„œ μ˜ˆμ‚¬μ†Œλ¦¬(γ„±, γ„·, γ…‚, γ……, γ…ˆ)와 κ±°μ„Όμ†Œλ¦¬(γ…‹, γ…Œ, ㅍ, γ…Š)λ₯Ό λœμ†Œλ¦¬(γ„², γ„Έ, γ…ƒ, γ…†, γ…‰)둜 λ°”κΎΈλŠ” μ˜ˆμ œκ°€ μ€€λΉ„λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

핡심 μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

let input = '아버지가 방에 λ“€μ–΄κ°€μ‹ λ‹€'

function stronger(x){
  if(x == 'γ„±' || x == 'γ…‹') return 'γ„²';
  if(x == 'γ„·' || x == 'γ…Œ') return 'γ„Έ';
  if(x == 'γ…‚' || x == 'ㅍ') return 'γ…ƒ';
  if(x == 'γ……') return 'γ…†';
  if(x == 'γ…ˆ' || x == 'γ…Š') return 'γ…‰';
  return x;
}

console.log(Hangul.a(Hangul.d(input).map(stronger))); 
// μ•„λ»μ°ŒκΉŒ 빡에 λœ°μ–΄κΉŒμ”¬λ”°

ν…ŒμŠ€νŠΈ 및 κΈ°μ—¬

μ½”λ“œλ₯Ό μˆ˜μ •ν•˜μ…¨λ‹€λ©΄ κΌ­ grunt λͺ…λ Ήμ–΄λ₯Ό 톡해 ν…ŒμŠ€νŠΈλ₯Ό μˆ˜ν–‰ν•΄ μ£Όμ„Έμš”. ν˜„μž¬ λ§ˆμŠ€ν„° λΈŒλžœμΉ˜μ— μžˆλŠ” μ½”λ“œμ˜ ν…ŒμŠ€νŠΈ κ²°κ³ΌλŠ” https://e-.github.io/Hangul.js/test/μ—μ„œ 보싀 수 μžˆμŠ΅λ‹ˆλ‹€.