정규식 입문 — 자주 쓰는 패턴과 반드시 걸리는 함정 두 가지
문자 지정·반복·캡처 그룹을 순서대로 정리하고, 탐욕적 매칭과 파국적 백트래킹이라는 두 함정을 피하는 법, 한국어에서 \b가 통하지 않는 이유까지 다룹니다.
정규식은 배우기 전에는 암호처럼 보이고, 배우고 나면 없이는 못 사는 도구입니다. 로그에서 특정 형식의 줄만 뽑거나, 문서 전체에서 전화번호 형식을 한 번에 바꾸거나, 입력값이 규칙에 맞는지 검사하는 일을 몇 글자로 처리할 수 있습니다. 이 글에서는 실제로 자주 쓰는 것부터 순서대로 정리하고, 초보자가 반드시 걸리는 함정 두 가지를 짚습니다.
문자 하나를 가리키는 방법
정규식의 출발점은 "이 자리에 어떤 문자가 올 수 있는가"를 적는 것입니다.
| 표기 | 의미 | 예시 |
|---|---|---|
. | 줄바꿈을 제외한 아무 문자 하나 | a.c → abc, a1c |
\d | 숫자 하나 (0–9) | \d\d → 42 |
\w | 영문자·숫자·언더스코어 | \w+ → user_01 |
\s | 공백·탭·줄바꿈 | \s+ → 연속 공백 |
[가-힣] | 한글 완성형 한 글자 | [가-힣]+ → 안녕하세요 |
[^abc] | a, b, c가 아닌 문자 | [^0-9] → 숫자 아님 |
몇 번 반복되는지 적는 방법
*— 0번 이상 (있어도 되고 없어도 됨)+— 1번 이상 (최소 하나는 있어야 함)?— 0번 또는 1번 (있을 수도, 없을 수도){3}— 정확히 3번,{2,4}— 2~4번,{2,}— 2번 이상
이 둘을 조합하면 대부분의 패턴이 만들어집니다. 예를 들어 한국 휴대폰 번호는
01\d-\d{3,4}-\d{4}로 잡을 수 있고, 날짜는
\d{4}-\d{2}-\d{2}로 잡힙니다.
첫 번째 함정: 탐욕적 매칭
가장 많은 사람이 처음 걸리는 지점입니다. *와 +는 기본적으로
가능한 한 길게 먹으려 합니다. HTML 태그 하나를 잡으려고
<.*>라고 쓰면, 첫 <부터 마지막 >까지
통째로 잡힙니다.
해결 방법은 두 가지입니다. 수량자 뒤에 ?를 붙여
비탐욕(게으른) 매칭으로 바꾸거나 — <.*?> —
애초에 범위를 제한하는 것입니다 — <[^>]*>. 후자가 더 빠르고
의도도 분명해서 실무에서는 이쪽을 선호합니다.
두 번째 함정: 브라우저가 멈추는 패턴
(a+)+b처럼 수량자가 중첩된 패턴에 매치되지 않는 긴
문자열을 넣으면, 엔진이 가능한 조합을 전부 시도하느라 사실상 끝나지 않습니다.
이를 파국적 백트래킹이라고 부르며, 서버에서 이런 패턴을 쓰면 요청 하나로 서비스가
멈추는 보안 문제(ReDoS)가 되기도 합니다.
예방법은 간단합니다. (x+)+, (x*)*, (x|xy)+처럼
같은 문자를 여러 경로로 매치할 수 있는 구조를 피하고, .* 대신
[^구분자]*처럼 범위를 좁히면 대부분 해결됩니다. 사용자 입력을 정규식으로
쓰는 경우라면 길이 제한을 함께 두세요.
괄호로 잡아서 다시 쓰기
괄호로 감싼 부분은 캡처 그룹이 되어 나중에 참조할 수 있습니다.
치환할 때 $1, $2로 순서대로 가져다 쓰면 됩니다.
날짜 형식을 바꾸는 예를 보겠습니다.
- 찾기:
(\d{4})-(\d{2})-(\d{2}) - 바꾸기:
$3/$2/$1 - 결과:
2026-09-12→12/09/2026
그룹이 많아지면 번호를 세기 어려우므로 (?<year>\d{4})처럼 이름을
붙이고 $<year>로 참조할 수도 있습니다. 반대로 묶기만 하고 캡처는
필요 없다면 (?:...)를 쓰면 번호를 차지하지 않습니다.
플래그가 결과를 바꾼다
- g (전역): 모든 매치를 찾습니다. 꺼져 있으면 첫 번째만 찾고, 치환도 한 번만 일어납니다. 여러 곳을 바꾸려는데 하나만 바뀐다면 이걸 확인하세요.
- i (대소문자 무시):
abc가ABC에도 매치됩니다. - m (멀티라인):
^와$가 문자열 전체가 아니라 각 줄의 시작과 끝을 가리키게 됩니다. 로그를 줄 단위로 다룰 때 필수입니다. - s (dotAll):
.이 줄바꿈까지 포함하게 됩니다.
한국어를 다룰 때 알아 둘 것
단어 경계를 뜻하는 \b는 영문자·숫자·언더스코어를 기준으로 정의되어 있어
한글에서는 의도대로 동작하지 않습니다. "학교"를 찾을 때 "학교에서"를
제외하고 싶어도 \b학교\b로는 걸러지지 않습니다. 한국어는 조사가 붙는
교착어라 애초에 단어 경계가 명확하지 않기 때문입니다.
대안으로는 조사까지 포함해 패턴을 쓰거나(학교(?:에서|에|를|가)?),
앞뒤에 올 수 없는 문자를 직접 지정하는 방법을 씁니다. 한글 자모까지 다루려면
[ㄱ-ㅎㅏ-ㅣ가-힣]처럼 범위를 넓혀야 합니다.
언어마다 문법이 조금씩 다르다
정규식은 하나의 표준이 아니라 여러 방언이 있습니다. 자바스크립트, 파이썬, 자바,
PCRE(PHP·grep) 사이에 룩비하인드 지원 범위나 \A·\z 같은
앵커의 존재 여부가 다릅니다. 어디서 쓸 패턴인지 정하고 그 환경에서 테스트하는 것이
안전합니다. 정규식 테스터는 브라우저 내장
자바스크립트 엔진을 그대로 쓰므로, 웹 프론트엔드나 Node.js에서 쓸 패턴을 검증하기에
적합합니다.
연습하는 순서
복잡한 패턴을 한 번에 완성하려 하면 어디가 틀렸는지 알 수 없습니다. 작은 조각부터
붙여 가며 결과를 확인하는 편이 훨씬 빠릅니다. 예를 들어 이메일을 잡는다면
\w+ → \w+@ → \w+@\w+ →
\w+@\w+\.\w+ 순으로 늘려 가면서 매번 실제 데이터에 대고 확인합니다.
다만 이메일이나 URL처럼 규격이 복잡한 값은 정규식으로 완벽하게 검증하려 들지 않는 편이 낫습니다. 실무에서는 대략적인 형태만 확인하고 실제 유효성은 인증 메일 발송 같은 방법으로 검증합니다.
마무리
정규식은 외우는 것이 아니라 필요할 때 조합해 쓰는 도구입니다. 문자 지정·반복·그룹 세 가지 축만 잡고 있으면 나머지는 찾아 쓰면 됩니다. 탐욕적 매칭과 중첩 수량자 두 함정만 피해도 실무에서 겪는 문제의 대부분이 사라집니다. 패턴을 실제 데이터에 대고 확인하려면 정규식 테스터를, 문서 전체에 여러 치환 규칙을 한꺼번에 적용하려면 찾기·바꾸기를 사용해 보세요.