정규식 기초
정규식(regex)은 텍스트를 묘사하는 패턴입니다. 이 가이드에서는 가장 자주 쓰는 구성 요소와, 느리거나 예상과 다른 일치를 일으키는 함정을 다룹니다.
리터럴과 문자 클래스
대부분의 문자는 그 문자 자체와 일치합니다. 패턴 cat은 텍스트 "cat"을 찾습니다. . * + ? ( ) [ ] { } ^ $ | \ 같은 일부 문자는 특별한 의미가 있습니다. 이런 문자를 글자 그대로 찾으려면 백슬래시로 이스케이프합니다. 예를 들어 마침표는 \.로 씁니다.
문자 클래스는 집합에 속한 문자 하나와 일치합니다. [abc]는 a, b, c 중 하나와, [a-z]는 ASCII 소문자 하나와, [^0-9]는 숫자가 아닌 문자와 일치합니다. 자주 쓰는 약칭으로는 \d(숫자), \w(영문자, 숫자, 밑줄), \s(공백 문자)와 그 반대인 \D, \W, \S가 있습니다. 점 .은 줄바꿈을 제외한 모든 문자와 일치합니다.
JavaScript에서 \w와 \d는 ASCII 문자만 다룹니다. 모든 언어의 문자와 일치시키려면 u 플래그와 함께 \p{L} 같은 유니코드 속성을 사용하세요.
수량자와 앵커
수량자는 바로 앞의 항목이 몇 번 반복될 수 있는지 정합니다.
| 문법 | 의미 | 예 |
|---|---|---|
* |
0개 이상 | ab*는 a, ab, abbb와 일치 |
+ |
1개 이상 | \d+는 7이나 2026과 일치 |
? |
0개 또는 1개 | colou?r는 color, colour와 일치 |
{n,m} |
n개 이상 m개 이하 | \d{2,4}는 숫자 2~4개와 일치 |
앵커는 문자가 아니라 위치와 일치합니다. ^는 입력의 시작, $는 입력의 끝(m 플래그를 쓰면 각 줄의 시작과 끝)입니다. \b는 단어 경계이므로 \bcat\b는 "cat"은 찾지만 "concatenate"는 찾지 않습니다. 값 전체를 검증할 때는 양쪽 끝을 고정하세요. ^\d{5}$는 정확히 숫자 다섯 개만 허용합니다.
그룹과 캡처
괄호는 패턴의 일부를 묶어 수량자나 선택이 그 부분에 적용되게 합니다. (ab)+는 "ab"를 반복하고, (jpg|png)는 두 단어 중 하나와 일치합니다. 일반 그룹은 일치한 텍스트를 캡처하기도 하며, 치환할 때 $1, $2 등으로 다시 쓸 수 있습니다.
(?<year>\d{4}) 같은 이름 있는 그룹은 패턴을 읽기 쉽게 해 주며 $<year>로 참조할 수 있습니다. 묶기만 필요하다면 캡처하지 않는 그룹 (?:...)을 써서 쓰지 않는 캡처를 만들지 않을 수 있습니다. LeedyBox 정규식 테스트는 각 일치 항목을 캡처 그룹과 함께 나열하고 치환 결과를 미리 보여 줍니다.
플래그
플래그는 패턴 전체의 동작 방식을 바꿉니다. 자주 쓰는 JavaScript 플래그는 다음과 같습니다.
g(global): 첫 번째 일치만이 아니라 모든 일치 항목을 찾습니다.i(ignore case): 대문자와 소문자를 같은 것으로 취급합니다.m(multiline):^와$가 줄바꿈 위치마다 일치합니다.s(dotAll):.이 줄바꿈과도 일치합니다.u(unicode): 유니코드를 인식하는 일치와\p{...}클래스를 사용할 수 있게 합니다.
JavaScript에는 y(sticky)와 d(일치 인덱스)도 있으며, 테스트 도구는 이 플래그도 지원합니다.
탐욕적 일치와 게으른 일치, 그리고 치명적 백트래킹
수량자는 기본적으로 탐욕적입니다. 가능한 한 많이 일치한 다음, 패턴의 나머지 부분이 실패하면 문자를 하나씩 되돌려 줍니다. 텍스트 <b>bold</b>에서 패턴 <.+>는 문자열 전체와 일치합니다. ?를 붙이면 수량자가 게을러져서 <.+?>는 <b>만 일치합니다. <[^>]+> 같은 부정 클래스가 더 명확하고 빠른 경우가 많습니다.
JavaScript를 포함한 대부분의 정규식 엔진은 백트래킹을 사용합니다. (a+)+$ 같은 중첩 수량자나 서로 겹치는 선택지가 있으면, 일치에 실패할 때 엔진이 엄청나게 많은 조합을 시도해 페이지나 서버가 멈출 수 있습니다. 이를 치명적 백트래킹(catastrophic backtracking)이라고 하며, 신뢰할 수 없는 입력에서는 서비스 거부 공격(ReDoS)에 악용될 수 있습니다. 같은 문자에 대해 수량자를 중첩하지 말고, .*보다는 구체적인 클래스를 쓰고, 일치하지 않는 긴 입력으로 패턴을 테스트하세요.
정규식 방언은 서로 다릅니다
정규식에는 하나의 표준이 없습니다. JavaScript, Python, Java, .NET, PCRE(PHP에서 사용), Go, 데이터베이스는 각각 조금씩 다른 문법을 지원합니다. 후방 탐색, 소유적 수량자, 이름 있는 그룹 문법, 유니코드 클래스, 치환 문법이 서로 다릅니다. 예를 들어 Go의 RE2 엔진은 전후방 탐색과 역참조를 지원하지 않습니다.
LeedyBox 정규식 테스트는 브라우저의 JavaScript 엔진을 사용합니다. 여기서 동작하는 패턴도 다른 언어에서는 수정이 필요할 수 있으므로, 실제로 실행할 곳에서 다시 테스트하세요.
자주 묻는 질문
패턴이 왜 첫 번째 항목만 찾나요?
g 플래그가 없으면 JavaScript는 첫 번째 일치 후에 멈춥니다. 모든 일치 항목을 찾으려면 g를 켜세요.
정규식으로 이메일 주소를 검증할 수 있나요?
정규식으로 값이 그럴듯한 형태인지는 확인할 수 있지만, 주소가 실제로 존재하는지는 확인할 수 없습니다. 보통은 확인 이메일을 보내 검증합니다.
여러 줄 텍스트에서 ^가 왜 한 번만 일치하나요?
기본적으로 ^와 $는 입력 전체를 기준으로 합니다. 각 줄의 시작과 끝에서 일치하게 하려면 m 플래그를 켜세요.