자바스크립트에서 문자열을 분리할 때 일반적으로 split()
메서드를 사용한다. 하지만 아래처럼 구분자는 결과 배열에서 제외되고 불필요한 공백이 추가된다. 즉, language-sensitive 하지 않는 단점이 있다. language-sensitive는 문맥에 맞는 표현과 용어 사용을 의미한다. 한국어로는 언어 감수성이라고 부른다.
'Hello! How are you?'.split(/[.!?]/);
// ['Hello', ' How are you', '']
<aside> 💡 정규식 관련 참고
[]
문자 그룹은 대괄호 내부 문자열 중 하나라도 일치하는 경우를 의미한다
</aside>Intl
자바스크립트 API를 활용하면 위 같은 문제를 말끔하게 해결할 수 있다.
Intl.Segmenter
메서드를 사용하면 문자열을 의미있는 단위로 분리할 수 있다. locale
granularity
를 정의한 후 segment
메서드 파라미터에 분리하고 싶은 문자열을 추가하는 방식으로 사용한다.
<aside> 💡 granularity 옵션(颗粒选项) 종류
segment
메서드는 정의한 locale
granularity
옵션에 따라 문자열의 세그먼트를 나타내는 Segments 인스턴스를 반환한다. Segments 인스턴스는 이터러블이다. 따라서 전개연산자
Array.from
for of
문 등에서 사용할 수 있다.
const segmenterKo = new Intl.Segmenter('ko', { granularity: 'word' });
const segmentsKo = segmenterKo.segment('안녕하세요, 반갑습니다');
console.log([...segmentsKo])
/*
{ segment: '안녕하세요', index: 0, input: '안녕하세요, 반갑습니다', isWordLike: true }
{ segment: ',', index: 5, input: '안녕하세요, 반갑습니다', isWordLike: false }
{ segment: ' ', index: 6, input: '안녕하세요, 반갑습니다', isWordLike: false }
{ segment: '반갑습니다', index: 7, input: '안녕하세요, 반갑습니다', isWordLike: true }
*/
const segmenterKo = new Intl.Segmenter('ko', { granularity: 'sentence' });
const segmentsKo = segmenterKo.segment('안녕하세요, 반갑습니다');
console.log([...segmentsKo])
/*
{ "segment": "안녕하세요, 반갑습니다", "index": 0, "input": "안녕하세요, 반갑습니다" }
*/
const segmenterKo = new Intl.Segmenter('ko', { granularity: 'grapheme' });
const segmentsKo = segmenterKo.segment('안녕하세요, 반갑습니다');
console.log([...segmentsKo])
/*
{ "segment": "안", "index": 0, "input": "안녕하세요, 반갑습니다" }
{ "segment": "녕", "index": 1, "input": "안녕하세요, 반갑습니다" }
{ "segment": "하", "index": 2, "input": "안녕하세요, 반갑습니다" }
...
*/
<aside>
💡 isWordLike
프로퍼티는 word
기준으로 문자열을 분리했을 때만 포함된다
</aside>
만약 word
를 기준으로 문자열을 분리했다면, 모든 세그먼트는 단어뿐만 아니라 공백(whitespace), 구두점(punctuation) 및 줄바꿈(line breaks)을 포함할 수 있다. 여기서 단어만 추출하고 싶으면 isWordLike
프로퍼티를 이용해 필터링 하면 된다. isWordLike
는 세그먼트가 단어와 유사한지 여부를 나타내는 불리언 값이다.
const segmenterKo = new Intl.Segmenter('ko', { granularity: 'word' });
const segmentsKo = segmenterKo.segment('안녕하세요, 반갑습니다');
console.log([...segmentsKo].filter(s => s.isWordLike));
/*
{ "segment": "안녕하세요", "index": 0, "input": "안녕하세요, 반갑습니다", "isWordLike": true }
{ "segment": "반갑습니다", "index": 7, "input": "안녕하세요, 반갑습니다", "isWordLike": true }
*/