정규식이란?
정규식은 문자열의 집합을 적는 작은 패턴 언어다. 어떤 문자가 어떤 순서로 몇 번 올 수 있는지를 한 줄로 쓴다. 표현식 하나로 입력을 검사하고, 로그 한 줄에서 필드를 뽑고, 텍스트를 고쳐 쓸 수 있다. 거의 모든 언어와 편집기, 명령줄 도구에 정규식이 들어 있는 이유다.
문제는 정규식이 주석을 넣을 자리도 없는 빽빽한 한 줄이라는 데 있다. 그래서 동작하는 패턴이 여섯 달 뒤에는 아무도 손대지 못하는 패턴이 되곤 한다. 이 테스터는 입력하는 동안 표현식을 돌려 모든 일치를 위치와 캡처 그룹까지 보여주고, 치환 결과를 미리 보여주고, 패턴을 토큰으로 갈라 하나씩 뜻을 붙인다.
A Regular Expression (regexp) is a pattern which specifies a set of character strings.
기능
- 패턴을 말로 풀어 준다
- 표현식을 토큰으로 갈라 각각에 이름을 붙인다. \d 는 "숫자 0-9", {3} 은 "정확히 n번 반복". 복사해 온 패턴을 고칠 수 있는 패턴으로 바꾸는 지점이 여기다.
- 모든 일치를 위치와 그룹까지
- 일치마다 문자열 안의 위치와 캡처 그룹의 내용을 함께 보여준다. 엉뚱한 것을 잡은 그룹이 짐작이 아니라 눈에 보인다.
- 치환 미리보기
- $1 같은 역참조를 포함해 바꿀 내용을 넣으면 고쳐진 텍스트가 바로 나온다. 진짜 데이터에 돌리기 전에 확인한다.
- 방언을 숨기지 않는다
- 자바스크립트 엔진으로 돌린다. 브라우저와 Node 가 쓰는 그것이고, 그렇다고 화면에 적어 둔다. PCRE 를 지원하는 척하면서 조용히 다르게 동작하는 테스터는 없느니만 못하다.
- 실제 데이터로 시험해도 된다
- 패턴과 대상 문자열 모두 브라우저에서 평가된다. 로그나 고객 데이터를 어디로도 보내지 않고 테스트 입력으로 쓸 수 있다.
사용법
- 1
패턴을 쓴다
슬래시 사이에 표현식을 입력하거나, 자주 쓰는 패턴에서 시작한다.
- 2
플래그를 고른다
g 는 첫 하나가 아니라 모두 찾고, i 는 대소문자를 무시하고, m 은 ^ 와 $ 를 줄마다 맞춘다.
- 3
대상 문자열을 붙여넣는다
입력하는 동안 일치가 갱신되고, 각각의 위치와 캡처 그룹이 함께 나온다.
- 4
설명을 읽는다
토큰 분해가 패턴의 각 부분이 무슨 일을 하는지 말해 준다. 의도한 뜻이 맞는지 확인하는 방법이다.
파국적 백트래킹, 그리고 미리 알아보는 법
(a+)+$ 같은 패턴을 a 가 길게 이어지다 b 로 끝나는 문자열에 돌리면 빨리 실패하지 않는다 — 포기하기 전에 a 들을 나누는 지수적으로 많은 방법을 전부 시도한다. 서른 글자면 우주의 나이보다 오래 걸릴 수 있다. 눈여겨볼 모양은 수량자가 붙은 그룹 안에 또 수량자가 있는 것, 특히 같은 텍스트를 두 갈래로 맞출 수 있는 선택지가 섞인 경우다.
자바스크립트에는 소유 수량자도 원자 그룹도 없어서 해법은 플래그가 아니라 구조다. 시작할 수 있는 자리가 하나뿐이도록 앵커를 붙이고, 겹친 수량자를 문자 집합 하나로 바꾸고((\w|\d)+ 대신 [a-z]+), 선택지가 서로 겹치지 않게 만든다. 내가 통제하지 않는 입력에 이 패턴이 돌 것이라면 이건 성능 문제가 아니다 — 입력을 공격자가 고르는 ReDoS 서비스 거부다.
자주 묻는 질문
플래그 g·i·m 은 뭘 하나?
g(전역)는 첫 일치에서 멈추지 않고 모두 찾는다. i 는 대소문자를 무시한다. m(여러 줄)은 ^ 와 $ 를 문자열 전체가 아니라 각 줄의 처음과 끝에 맞춘다. s 는 . 이 줄바꿈에도 맞게 하고, u 는 유니코드를 온전히 다루게 한다.
정규식이 첫 번째만 찾는다
g 플래그가 빠진 것이다. 없으면 엔진이 첫 일치에서 멈춘다. replace() 같은 메서드가 한 번만 바꾸는 이유도 같다. g 를 켜면 모든 자리를 찾는다.
캡처 그룹이 뭔가?
패턴의 일부를 괄호로 감싸면 그 부분이 잡은 것을 따로 꺼내 읽거나 치환에서 $1·$2 로 참조할 수 있다. 반복을 묶기만 하고 잡을 필요는 없으면 (?:...) 를 쓴다.
PCRE 나 파이썬 정규식도 되나?
안 된다 — 자바스크립트 엔진으로 돈다. 문법이 많이 겹치지만 실제 차이가 있다. 뒤돌아보기 지원, 이름 있는 그룹 문법, 일부 유니코드 속성 이스케이프가 방언마다 다르다. 미묘한 것은 실제로 쓸 엔진에서 시험한다.
정규식이 너무 느리다
대개 파국적 백트래킹이다. (a+)+ 처럼 수량자가 겹친 패턴을 맞지 않는 문자열에 돌리면 엔진이 지수적으로 많은 경로를 시도한다. 자바스크립트에는 소유 수량자가 없으므로 패턴 자체를 고쳐야 한다 — 앵커를 붙이거나, 겹친 수량자를 문자 집합으로 바꾼다.
이메일 검사에 정규식을 쓰는 것이 맞나?
대충 거르는 데는 맞다. @ 양쪽에 무언가가 있어야 한다는 정도면 오타의 대부분을 잡는다. 정확성을 원한다면 아니다. RFC 5322 의 주소 문법은 따옴표 문자열과 주석까지 허용해서 읽을 수 있는 패턴으로는 덮이지 않고, 그 주소가 실제로 되는지는 메일을 보내 봐야만 안다.
이 도구가 따르는 규격
- MDN — 정규 표현식 — 이 테스터가 돌리는 자바스크립트 방언. 플래그와 이스케이프가 모두 여기 있다.
- ECMA-262 — RegExp 객체 — 그 방언의 규범 문법.
- POSIX.1-2024 — 정규식 — grep 과 sed 가 따르는 오래된 POSIX 문법, 그리고 방언이 갈리는 지점.
- RFC 5322 §3.4.1 — 주소 명세 — 읽을 수 있는 패턴으로 이메일 주소를 온전히 검사할 수 없는 이유.