문단 전체 텍스트를 담은 문자열을 첫 번째 인수로, 원하는 청크(chunk) 크기를 숫자로 두 번째 인수로 받는 JavaScript 함수를 작성해 보겠습니다.
이 함수는 다음과 같은 동작을 수행해야 합니다.
- 문자열을 두 번째 인수로 전달된 크기를 넘지 않는 길이의 청크 단위로 분할합니다.
- 분할 지점은 반드시 공백(whitespace)이나 문장의 끝이어야 하며, 단어 중간에서 잘리면 안 됩니다.
예시
예를 들어 입력 문자열과 청크 크기가 다음과 같다면,
const str = 'this is a string';
const chunkLength = 6;출력 결과는 다음과 같아야 합니다.
const output = ['this', 'is a', 'string'];각 청크가 6자를 넘지 않으면서도 단어가 잘리지 않고 공백을 기준으로 분할된 것을 확인할 수 있습니다.
정규식을 활용한 구현
이 문제는 정규 표현식(regular expression)으로 깔끔하게 해결할 수 있습니다. 먼저 지정한 길이만큼의 문자를 매칭한 뒤, 공백이나 문자열의 끝을 만날 때까지 역방향으로 백트래킹(backtracking)하는 방식입니다.
사용되는 정규식 패턴을 하나씩 살펴보면 다음과 같습니다.
- \S : 공백이 아닌 문자 하나로, 각 청크의 시작을 의미합니다.
- .{1,${size - 2}} : 1자 이상 size-2자 이하의 임의 문자를 매칭합니다.
- \S(?= |$) : 바로 뒤에 공백이나 문자열 끝이 오는 비공백 문자로, 청크의 마지막 문자를 의미합니다.
여기서 String.raw를 사용하면 템플릿 리터럴 안에서 \S 같은 특수 시퀀스가 이스케이프 처리되지 않고 그대로 유지됩니다.
코드 예제
const size = 200;
const str = "This process was continued for several years for the deaf child does not here in a month or even in two or three years the numberless items and expressions using the simplest daily intercourse little hearing child learns from these constant rotation and imitation the conversation he hears in his home simulates is mine and suggest topics and called forth the spontaneous expression of his own thoughts.";
const splitString = (str = '', size) => {
const regex = new RegExp(String.raw`\S.{1,${size - 2}}\S(?= |$)`, 'g');
const chunks = str.match(regex);
return chunks;
}
console.log(splitString(str, size));실행 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[
'This process was continued for several years for the deaf child does not here in a month or even in two or three years the numberless items and expressions using the simplest daily intercourse little',
'hearing child learns from these constant rotation and imitation the conversation he hears in his home simulates is mine and suggest topics and called forth the spontaneous expression of his own',
'thoughts.'
]200자 크기의 청크로 분할되었지만, 어떤 단어도 중간에서 잘리지 않고 모두 온전하게 유지되는 것을 확인할 수 있습니다. 이처럼 정규식 하나만으로 가독성 좋은 코드와 함께 단어 경계를 보존하는 문자열 분할 기능을 손쉽게 구현할 수 있습니다.