정규식은 텍스트 검색, 유효성 검사, 변환이 필요할 때마다 활용도가 높은 기술입니다. 이 치트시트는 가장 많이 쓰이는 패턴을 즉시 테스트할 수 있는 예제와 함께 정리합니다.
실시간 정규식 테스터 열기 →
문자 클래스
| 패턴 | 매칭 대상 |
|---|
. | 줄바꿈을 제외한 모든 문자 |
\d | 숫자 [0-9] |
\D | 숫자가 아닌 문자 |
\w | 단어 문자 [a-zA-Z0-9_] |
\W | 단어 문자가 아닌 것 |
\s | 공백 (스페이스, 탭, 줄바꿈) |
\S | 공백이 아닌 것 |
[abc] | a, b, c 중 하나 |
[^abc] | a, b, c가 아닌 것 |
[a-z] | 소문자 a부터 z |
[A-Z] | 대문자 A부터 Z |
[0-9] | 숫자 0부터 9 |
앵커
| 패턴 | 매칭 대상 |
|---|
^ | 문자열 시작 (멀티라인 모드에서는 줄 시작) |
$ | 문자열 끝 (멀티라인 모드에서는 줄 끝) |
\b | 단어 경계 |
\B | 단어 경계가 아닌 것 |
/^\d{5}$/ → 정확히 5자리 숫자만 매칭 (우편번호)
/\bword\b/ → "word"는 매칭, "password"는 미매칭
수량자
| 패턴 | 의미 |
|---|
* | 0번 이상 |
+ | 1번 이상 |
? | 0 또는 1번 (선택적) |
{n} | 정확히 n번 |
{n,} | n번 이상 |
{n,m} | n번 이상 m번 이하 |
탐욕적(greedy) vs 게으른(lazy): 기본적으로 수량자는 탐욕적(가능한 많이 매칭)입니다. ?를 추가하면 게으른 방식이 됩니다:
<.+> → 탐욕적: <b>bold</b> 전체를 하나로 매칭
<.+?> → 게으른: <b>와 </b>를 별도로 매칭
그룹과 선택
| 패턴 | 의미 |
|---|
(abc) | 캡처 그룹 |
(?:abc) | 비캡처 그룹 |
a|b | 선택: a 또는 b |
\1 | 첫 번째 그룹에 대한 역참조 |
// 날짜 문자열에서 연, 월, 일 추출
const match = '2026-04-07'.match(/(\d{4})-(\d{2})-(\d{2})/);
// match[1] = '2026', match[2] = '04', match[3] = '07'
룩어헤드와 룩비하인드
| 패턴 | 의미 |
|---|
(?=abc) | 긍정 룩어헤드 — abc 앞 위치 |
(?!abc) | 부정 룩어헤드 — abc가 없는 앞 위치 |
(?<=abc) | 긍정 룩비하인드 — abc 뒤 위치 |
(?<!abc) | 부정 룩비하인드 — abc가 없는 뒤 위치 |
/\d+(?= 원)/ → " 원" 앞의 숫자만 매칭
/(?<=\$)\d+/ → "$" 뒤의 숫자만 매칭
룩비하인드는 JavaScript에서 ES2018 이상이 필요합니다.
플래그
| 플래그 | 효과 |
|---|
i | 대소문자 무시 |
g | 전역 — 모든 매칭 찾기 |
m | 멀티라인 — ^와 $가 줄 경계 매칭 |
s | Dotall — .이 줄바꿈도 매칭 |
u | 유니코드 모드 |
/hello/i.test('Hello World') // true
'abc abc'.match(/abc/g) // ['abc', 'abc']
자주 쓰는 패턴
이메일 (기본)
/^[^\s@]+@[^\s@]+\.[^\s@]+$/
URL
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)/
IPv4 주소
/^(\d{1,3}\.){3}\d{1,3}$/
16진수 색상
/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/
한국 휴대폰 번호
/^01[016789]-?\d{3,4}-?\d{4}$/
URL 슬러그
/^[a-z0-9]+(?:-[a-z0-9]+)*$/
Semver
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([\da-zA-Z-]+(?:\.[\da-zA-Z-]+)*))?(?:\+([\da-zA-Z-]+(?:\.[\da-zA-Z-]+)*))?$/
코드에서 정규식 사용하기
JavaScript
// 문자열이 패턴과 일치하는지 테스트
/^\d+$/.test('123') // true
/^\d+$/.test('12a') // false
// 첫 번째 매칭 찾기
'hello world'.match(/\w+/) // ['hello']
// 모든 매칭 찾기
'hello world'.match(/\w+/g) // ['hello', 'world']
// 교체
'foo bar'.replace(/\b\w/g, c => c.toUpperCase()) // 'Foo Bar'
// 분할
'one, two,three'.split(/,\s*/) // ['one', 'two', 'three']
Python
import re
# 테스트
bool(re.match(r'^\d+$', '123')) # True
# 첫 번째 찾기
re.search(r'\d+', 'abc123def') # 매칭 객체
re.search(r'\d+', 'abc123def').group() # '123'
# 모두 찾기
re.findall(r'\d+', 'a1 b22 c333') # ['1', '22', '333']
# 교체
re.sub(r'\s+', '-', 'hello world') # 'hello-world'
실시간으로 정규식 테스트하기
패턴을 작성할 때 배포 전에 반드시 테스트하세요 — 엣지 케이스를 놓치기 쉽습니다.
ZeroTool 정규식 테스터 →
- 패턴과 테스트 문자열을 붙여넣기
- 실시간으로 모든 매칭 하이라이트
- 플래그 지원:
g, i, m, s
- 캡처 그룹 결과 표시
디버깅 팁
- 단순하게 시작 — 패턴을 조각씩 구성하기
- Python에서 raw 문자열 사용 —
r'\d+'는 이중 이스케이프를 피함
- 특수문자 이스케이프 —
., *, +, ?, (, ), [, ], {, }, ^, $, |, \는 리터럴로 쓸 때 이스케이프 필요
- 앵커 의식적 사용 —
/\d+/는 어디서든 숫자 매칭; /^\d+$/는 전체 문자열이 숫자여야 함
- 경계 케이스로 테스트 — 빈 문자열, 전체 매칭, 매칭 없음, 겹치는 패턴
정규식은 강력하지만 빠르게 유지보수 불가 상태가 됩니다. 패턴이 ~60자를 넘으면 명명된 서브패턴으로 분리하거나 파서 라이브러리 사용을 고려하세요.
ZeroTool 정규식 테스터에서 패턴을 바로 테스트하기 →