출시 예정인 정규 표현식 기능

야콥 그루버
양 구오

ES2015에서는 유니코드(/u) 및 고정 (/y) 플래그를 사용한 정규 표현식 구문의 현저한 개선을 비롯한 여러 새로운 기능이 자바스크립트 언어에 도입되었습니다. 하지만 그 이후로 개발은 멈추지 않았습니다. TC39 (ECMAScript 표준 기구)의 다른 구성원과 긴밀히 협력하여 V8 팀은 정규 표현식을 훨씬 더 강력하게 만들기 위해 몇 가지 새로운 기능을 제안하고 공동 설계했습니다.

이러한 기능은 현재 JavaScript 사양에 포함되도록 제안 중입니다. 제안이 완전히 수락되지는 않았지만 이미 TC39 절차의 3단계에 있습니다. Google에서는 사양이 확정되기 전에 각 제안서 작성자에게 시의적절한 설계 및 구현 의견을 제공할 수 있도록 플래그 뒤에 이러한 기능을 구현했습니다 (아래 참고).

이 블로그 게시물에서는 이러한 흥미진진한 미래를 미리 살펴봅니다. 앞으로의 예를 계속해서 살펴보려면 chrome://flags/#enable-javascript-harmony에서 실험용 자바스크립트 기능을 사용 설정하세요.

이름이 지정된 캡처

정규 표현식에는 일치하는 텍스트의 일부를 캡처할 수 있는 캡처 (또는 그룹)를 포함할 수 있습니다. 지금까지 개발자는 색인으로만 이러한 캡처를 참조할 수 있었으며, 색인은 패턴 내의 캡처 위치에 따라 결정됩니다.

const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-10');
// result[0] === '2017-07-10'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '10'

하지만 정규 표현식은 읽기, 쓰기, 유지보수가 이미 매우 까다롭기 때문에 숫자 참조가 정보 표시를 더 복잡하게 만들 수 있습니다. 예를 들어 긴 패턴에서는 특정 캡처의 색인을 결정하기가 까다로울 수 있습니다.

/(?:(.)(.(?<=[^(])(.)))/  // Index of the last capture?

더 심각한 문제는 패턴을 변경하면 모든 기존 캡처의 색인이 변경될 가능성이 있습니다.

/(a)(b)(c)\3\2\1/     // A few simple numbered backreferences.
/(.)(a)(b)(c)\4\3\2/  // All need to be updated.

이름이 지정된 캡처는 개발자가 캡처에 이름을 할당하도록 허용하여 이러한 문제를 완화하는 데 도움이 되는 출시 예정 기능입니다. 구문은 Perl, Java, .Net, Ruby와 유사합니다.

const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-10');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '10'

이름이 지정된 캡처는 이름이 지정된 역참조와 String.prototype.replace를 통해 참조할 수도 있습니다.

// Named backreferences.
/(?<LowerCaseX>x)y\k<LowerCaseX>/.test('xyx');  // true

// String replacement.
const pattern = /(?<fst>a)(?<snd>b)/;
'ab'.replace(pattern, '$<snd>$<fst>');                              // 'ba'
'ab'.replace(pattern, (m, p1, p2, o, s, {fst, snd}) => fst + snd);  // 'ba'

새로운 기능에 대한 자세한 내용은 사양 제안서에서 확인할 수 있습니다.

dotAll 플래그

기본적으로 정규 표현식의 . Atom은 줄 마침 표시를 제외한 모든 문자와 일치합니다.

/foo.bar/u.test('foo\nbar');   // false

제안서에 /s 플래그를 통해 사용 설정된 dotAll 모드가 도입됩니다. dotAll 모드에서 .는 줄 마침 표시자도 일치합니다.

/foo.bar/su.test('foo\nbar');  // true

새로운 기능에 대한 자세한 내용은 사양 제안서에서 확인할 수 있습니다.

유니코드 속성 이스케이프

ES2015에 유니코드 인식 기능이 도입되면서 숫자로 볼 수 있는 문자가 갑자기 많이 생겼습니다(예: 원문자 1:1 또는 눈의 한자인 雪).

둘 중 어느 것도 \d 또는 \w와 일치시킬 수 없습니다. 이러한 약식의 의미를 변경하면 기존의 정규 표현식 패턴이 깨집니다.

대신 새로운 속성 이스케이프 시퀀스가 도입됩니다. /u 플래그로 표시되는 유니코드 인식 정규 표현식에서만 사용할 수 있습니다.

/\p{Number}/u.test('①');      // true
/\p{Alphabetic}/u.test('雪');  // true

그 역은 \P와 매칭할 수 있습니다.

/\P{Number}/u.test('①');      // false
/\P{Alphabetic}/u.test('雪');  // false

유니코드 컨소시엄은 수학 기호, 일본어 히라가나 문자 등 더 많은 속성을 정의합니다.

/^\p{Math}+$/u.test('∛∞∉');                            // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな');  // true

지원되는 유니코드 속성 클래스의 전체 목록은 현재 사양 제안서에서 확인할 수 있습니다. 더 많은 예를 보려면 이 유용한 도움말을 참고하세요.

Lookbehind 어설션

미리보기 어설션은 처음부터 자바스크립트의 정규 표현식 구문의 일부였습니다. 어설션의 Lookbehind가 마침내 도입됩니다. 여러분 중 일부는 이미 꽤 오랫동안 V8에 포함되어 있었다는 것을 기억할 것입니다. 또한 내부적으로 Lookbehind 어설션을 사용하여 ES2015에 지정된 유니코드 플래그를 구현합니다.

이름은 이미 그 의미를 잘 설명하고 있습니다. Lookbehind 그룹의 패턴이 선행되는 경우에만 매칭하도록 패턴을 제한할 수 있습니다. 일치하는 버전과 일치하지 않는 버전이 모두 있습니다.

/(?<=\$)\d+/.exec('$1 is worth about ¥123');  // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123');  // ['123']

자세한 내용은 Lookbehind 어설션과 관련 V8 테스트 사례의 예를 설명하는 이전 블로그 게시물을 참고하세요.

감사의 말씀

이 블로그 게시물에서는 이를 실현하기 위해 열심히 노력한 일부 사람들, 특히 언어 챔피언인 Mathias Bynens, Dan Ehrenberg, Claude Pache, Brian Terlson, Thomas Wood, Gorkem Yakin, Irregexp 전문가, 기타} 에릭 Corry의 언어 사양을 구현했으며 V8의 언어 사양을 모두 지인{/18)에 대한 언급 없이는 완성이 되지 않았습니다.{/1

이처럼 새로운 정규 표현식 기능을 많이 기대해 주세요.