최신 정규식은 과거의 복잡하고 읽기 어려운 패턴에서 벗어나, 가독성과 표현력을 모두 끌어올린 방향으로 진화하고 있습니다. 특히 자바스크립트 ES2018 이후 도입된 기능들과 ES2024의 v 플래그까지 더해지면서, 이제는 예전이라면 여러 줄로 풀어야 했던 검증 로직을 한 줄로 처리할 수 있게 되었습니다. 이 글에서는 실무에서 바로 활용 가능한 핵심 변화 5가지를 구체적인 예제와 함께 살펴보겠습니다.
1. 명명된 캡처 그룹으로 가독성 높이기
예전에는 캡처한 값을 match[1], match[2]처럼 숫자 인덱스로 꺼내야 했습니다. 그룹 순서가 바뀌면 인덱스도 전부 어긋나기 때문에 유지보수가 까다로웠습니다. 최신 정규식에서는 (?<이름>...) 문법으로 그룹에 이름을 붙일 수 있습니다.
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const { groups } = '2026-06-05'.match(re);
console.log(groups.year, groups.month, groups.day);
// 2026 06 05
$<이름> 형태로 그룹을 참조할 수 있습니다. 예를 들어 날짜 형식을 바꿀 때 str.replace(re, '$<day>/$<month>/$<year>')처럼 직관적으로 작성됩니다.2. 룩비하인드로 앞 조건 검사하기
기존에도 룩어헤드(앞쪽을 내다보는 검사)는 있었지만, 룩비하인드(뒤쪽을 돌아보는 검사)는 비교적 최근에 정식 지원되었습니다. 덕분에 "특정 문자 뒤에 오는 값만 추출" 같은 작업이 훨씬 간결해졌습니다.
(?<=...): 긍정 룩비하인드, 앞에 특정 패턴이 있을 때만 매칭(?<!...): 부정 룩비하인드, 앞에 특정 패턴이 없을 때만 매칭
// 통화 기호 뒤의 숫자만 추출
const price = '결제 금액 ₩77000원';
const won = price.match(/(?<=₩)\d+/);
console.log(won[0]); // 77000
이런 추출 작업은 패턴을 조금만 바꿔도 결과가 크게 달라지기 때문에, 작성한 정규식을 실시간으로 검증하는 습관이 중요합니다. 여러 입력값을 빠르게 테스트하려면 정규식 테스터를 활용하면 매칭 결과와 캡처 그룹을 한눈에 확인할 수 있어 편리합니다.
3. 유니코드 속성 이스케이프로 다국어 처리
한글, 한자, 이모지가 섞인 텍스트를 처리할 때 과거에는 유니코드 범위를 직접 [\uAC00-\uD7A3]처럼 외워서 적어야 했습니다. 최신 정규식에서는 u 플래그와 함께 \p{...} 속성 문법을 사용해 의미 단위로 문자를 지정할 수 있습니다.
| 속성 표현 | 매칭 대상 |
|---|---|
\p{L} | 모든 언어의 글자 |
\p{Script=Hangul} | 한글 문자 |
\p{N} | 모든 종류의 숫자 |
\p{Emoji} | 이모지 문자 |
// 한글만 추출
const text = 'Hello 안녕 123';
const hangul = text.match(/\p{Script=Hangul}+/gu);
console.log(hangul); // ['안녕']
\p{...} 문법은 반드시 u 플래그를 함께 붙여야 동작합니다. 플래그를 빠뜨리면 문법 오류가 발생하니 주의하세요.4. dotAll과 v 플래그로 표현력 확장
점(.)은 기본적으로 줄바꿈 문자를 매칭하지 않습니다. 여러 줄에 걸친 텍스트를 한 번에 잡으려면 s(dotAll) 플래그가 필요합니다. 또한 ES2024에서 도입된 v 플래그는 문자 클래스 안에서 집합 연산과 교집합, 차집합을 지원해 더욱 정밀한 패턴을 만들 수 있습니다.
// dotAll: 줄바꿈을 포함한 전체 매칭
/<div>(.*?)<\/div>/s.test('<div>\n내용\n</div>'); // true
// v 플래그: 집합 차집합 (한글에서 자음만 제외 등)
const re = /[\p{L}--\p{Script=Latin}]/v;
5. matchAll과 replaceAll로 반복 처리 단순화
정규식 자체의 문법뿐 아니라, 정규식을 다루는 메서드도 함께 발전했습니다. 과거에는 while 루프와 exec를 반복 호출해야 했던 작업이 이제는 한 줄로 정리됩니다.
matchAll(): 모든 매칭 결과를 캡처 그룹까지 포함해 이터레이터로 반환합니다.replaceAll(): 정규식에g플래그가 없어도 문자열 전체를 치환할 수 있습니다.
const log = 'user=soop, user=panda';
for (const m of log.matchAll(/user=(?<name>\w+)/g)) {
console.log(m.groups.name);
}
// soop
// panda
matchAll()에 전달하는 정규식에는 반드시 g 플래그가 있어야 합니다. 없으면 TypeError가 발생합니다. 반대로 replaceAll()에 정규식을 쓸 때 g 플래그가 없으면 오류가 나니, 두 메서드의 요구 조건을 헷갈리지 않도록 합니다.지금까지 살펴본 다섯 가지 변화는 모두 코드의 가독성과 안정성을 높이는 방향으로 설계되었습니다. 명명 그룹과 유니코드 속성으로 의도를 명확히 드러내고, 룩비하인드와 새 플래그로 표현력을 넓히며, 최신 메서드로 반복 로직을 줄이는 것입니다. 작성한 패턴은 머릿속으로만 검증하지 말고 다양한 실제 입력값으로 직접 돌려보면서 다듬는 과정을 거치면, 예외 상황에서도 안정적으로 동작하는 정규식을 완성할 수 있습니다.