정규표현식 치트시트: 자주 쓰는 패턴 모음
웹 개발에서 가장 많이 사용하는 정규표현식 패턴과 활용 예제를 정리했습니다.

정규표현식, 왜 배워야 할까?
정규표현식(Regular Expression, Regex)은 개발자에게 있어 스위스 아미 나이프 같은 존재입니다. 처음에는 어렵게 느껴지지만, 한번 익숙해지면 수십 줄의 문자열 처리 코드를 단 한 줄로 대체할 수 있습니다. 이메일 검증, 전화번호 추출, 로그 파싱, 텍스트 치환 등 문자열을 다루는 거의 모든 작업에서 정규표현식은 빛을 발합니다.
많은 개발자들이 정규표현식을 두려워하는 이유는 그 문법이 한눈에 이해되지 않기 때문입니다. /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/처럼 생긴 코드는 마치 암호문처럼 보입니다. 하지만 기본 문법만 이해하면 이 패턴도 논리적으로 읽을 수 있게 됩니다. 이 글에서는 정규표현식의 핵심 문법을 먼저 설명하고, 실무에서 자주 사용하는 패턴들을 하나씩 분해하여 살펴보겠습니다.
기본 문법 체계적으로 이해하기
정규표현식의 문법은 크게 네 가지 범주로 나눌 수 있습니다: 메타 문자, 수량자, 그룹, 앵커입니다.
메타 문자: 특별한 의미를 가진 문자들
메타 문자는 특정 문자 집합이나 조건을 나타냅니다.
| 기호 | 의미 | 예시 |
|---|---|---|
. | 줄바꿈을 제외한 모든 문자 | a.c → abc, adc, a1c |
\d | 숫자 (0-9) | \d+ → 123, 4567 |
\D | 숫자가 아닌 문자 | \D+ → abc, !@# |
\w | 단어 문자 (a-z, A-Z, 0-9, _) | \w+ → hello_123 |
\W | 단어 문자가 아닌 것 | \W → 공백, 특수문자 |
\s | 공백 문자 (스페이스, 탭, 줄바꿈) | \s+ → 여러 공백 |
\S | 공백이 아닌 문자 | \S+ → 연속된 단어 |
수량자: 반복을 표현하기
수량자는 앞선 요소가 몇 번 반복되는지를 지정합니다.
| 기호 | 의미 | 예시 |
|---|---|---|
* | 0개 이상 | ab* → a, ab, abb, abbb |
+ | 1개 이상 | ab+ → ab, abb, abbb |
? | 0개 또는 1개 | colou?r → color, colour |
{n} | 정확히 n개 | \d{4} → 2025 |
{n,} | n개 이상 | \d{2,} → 10, 100, 1000 |
{n,m} | n개 이상 m개 이하 | \d{2,4} → 10, 100, 1000 |
앵커와 경계
앵커는 문자 자체가 아닌 위치를 매칭합니다.
| 기호 | 의미 | 예시 |
|---|---|---|
^ | 문자열의 시작 | ^Hello → "Hello World" 매치 |
$ | 문자열의 끝 | World$ → "Hello World" 매치 |
\b | 단어 경계 | \bcat\b → "cat"만, "catch" 불가 |
\B | 단어 경계가 아닌 곳 | \Bcat → "catch"의 cat |
그룹과 캡처
괄호를 사용하면 패턴을 그룹화하고, 매칭된 부분을 캡처할 수 있습니다.
const dateStr = '2025-12-25';
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const match = dateStr.match(regex);
console.log(match[0]); // '2025-12-25' (전체 매치)
console.log(match[1]); // '2025' (첫 번째 그룹 - 년)
console.log(match[2]); // '12' (두 번째 그룹 - 월)
console.log(match[3]); // '25' (세 번째 그룹 - 일)
실전 패턴 모음: 하나씩 분해하기
1. 이메일 검증
이메일 패턴은 정규표현식의 고전적인 예제입니다. 단계별로 분해해보겠습니다.
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
패턴 분해:
^- 문자열의 시작[a-zA-Z0-9._%+-]+- 로컬 파트 (@ 앞부분): 알파벳, 숫자, 점, 밑줄 등이 1개 이상@- @ 기호 (리터럴)[a-zA-Z0-9.-]+- 도메인 이름: 알파벳, 숫자, 점, 하이픈이 1개 이상\.- 점 (이스케이프 필요)[a-zA-Z]{2,}- 최상위 도메인: 알파벳 2자 이상 (com, kr, museum 등)$- 문자열의 끝
경계 케이스 처리:
이 패턴은 대부분의 일반적인 이메일을 검증하지만, RFC 5322 표준을 완전히 따르지는 않습니다. 예를 들어 "user name"@example.com같은 따옴표가 포함된 이메일은 매칭되지 않습니다. 실무에서는 형식 검증 후 실제 이메일 발송으로 확인하는 것이 가장 확실합니다.
2. 비밀번호 강도 검사
복잡한 비밀번호 규칙을 정규표현식으로 검증하려면 전방탐색(Lookahead)을 사용합니다.
// 최소 8자, 대소문자, 숫자, 특수문자 포함
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
패턴 분해:
(?=.*[a-z])- 소문자가 최소 1개 포함되어야 함 (전방탐색)(?=.*[A-Z])- 대문자가 최소 1개 포함되어야 함(?=.*\d)- 숫자가 최소 1개 포함되어야 함(?=.*[@$!%*?&])- 특수문자가 최소 1개 포함되어야 함[A-Za-z\d@$!%*?&]{8,}- 허용된 문자로 8자 이상
전방탐색 (?=...)은 해당 패턴이 존재하는지 확인하지만, 실제로 문자를 소비하지 않습니다. 이를 통해 여러 조건을 동시에 검사할 수 있습니다.
3. 전화번호 검증
한국 휴대폰 번호를 검증하는 패턴입니다.
const phoneRegex = /^01[016789]-?\d{3,4}-?\d{4}$/;
패턴 분해:
01[016789]- 010, 011, 016, 017, 018, 019로 시작-?- 하이픈은 있어도 되고 없어도 됨\d{3,4}- 3자리 또는 4자리 숫자\d{4}- 마지막 4자리
phoneRegex.test('010-1234-5678'); // true
phoneRegex.test('01012345678'); // true
phoneRegex.test('010 1234 5678'); // false (공백 미지원)
4. 한글 이름 검증
한글 이름을 검증할 때는 한글 유니코드 범위를 사용합니다.
const koreanNameRegex = /^[가-힣]{2,5}$/;
koreanNameRegex.test('홍길동'); // true
koreanNameRegex.test('김'); // false (2자 미만)
koreanNameRegex.test('Kim'); // false (영문)
[가-힣]은 완성형 한글 음절을 나타냅니다. 자음이나 모음만 있는 경우를 포함하려면 [ㄱ-ㅎㅏ-ㅣ가-힣]을 사용합니다.
5. URL 검증
URL 패턴은 다양한 형식을 지원해야 해서 복잡해집니다.
const urlRegex = /^(https?:\/\/)?(www\.)?[\w-]+(\.[a-z]{2,})+([\/\w.-]*)*\/?$/i;
패턴 분해:
(https?:\/\/)?- 프로토콜 (http:// 또는 https://) 선택적(www\.)?- www. 선택적[\w-]+- 도메인 이름(\.[a-z]{2,})+- .com, .co.kr 등 최상위 도메인 (1개 이상)([\/\w.-]*)*- 경로 (선택적)\/?$- 마지막 슬래시 선택적i플래그 - 대소문자 무시
6. IPv4 주소 검증
IPv4 주소의 각 옥텟은 0-255 범위여야 합니다. 이를 정규표현식으로 표현하면:
const ipv4Regex = /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
패턴 분해 (0-255 매칭):
25[0-5]- 250-2552[0-4]\d- 200-249[01]?\d\d?- 0-199
ipv4Regex.test('192.168.1.1'); // true
ipv4Regex.test('256.1.1.1'); // false (256은 범위 초과)
ipv4Regex.test('192.168.001.001'); // true (앞의 0 허용)
성능 최적화
정규표현식이 느려지는 가장 큰 원인은 백트래킹(Backtracking)입니다. 탐욕적 수량자가 과도하게 사용되면 성능이 급격히 저하될 수 있습니다.
탐욕적 vs 게으른 수량자
// 탐욕적 (Greedy) - 최대한 많이 매칭
'<div>content</div><div>more</div>'.match(/<div>.*<\/div>/);
// 결과: '<div>content</div><div>more</div>' (전체)
// 게으른 (Lazy) - 최소한만 매칭
'<div>content</div><div>more</div>'.match(/<div>.*?<\/div>/);
// 결과: '<div>content</div>' (첫 번째만)
수량자 뒤에 ?를 붙이면 게으른 매칭이 됩니다: *?, +?, ??
최적화 팁
- 앵커 사용:
^와$로 범위를 명확히 제한 - 구체적인 문자 클래스 사용:
.*대신[^<]*처럼 제한 - 비캡처 그룹 사용: 캡처가 필요 없으면
(?:...)사용
// 캡처 그룹 - 느림 (매칭 결과 저장)
/(abc)+/
// 비캡처 그룹 - 빠름 (저장하지 않음)
/(?:abc)+/
언어별 차이점
| 기능 | JavaScript | Python | Java |
|---|---|---|---|
| 문법 | /pattern/flags | r'pattern' | Pattern.compile("pattern") |
| 유니코드 | /u 플래그 | 기본 지원 | Pattern.UNICODE_CASE |
| 명명 그룹 | (?<name>...) | (?P<name>...) | (?<name>...) |
| 전방탐색 | 지원 | 지원 | 지원 |
| 후방탐색 | 가변 길이 제한 | 지원 | 지원 |
JavaScript에서 정규표현식 활용
const str = 'Contact us at support@example.com or sales@example.com';
const regex = /[\w.-]+@[\w.-]+\.\w+/g;
// 모든 매치 찾기
const emails = str.match(regex);
// ['support@example.com', 'sales@example.com']
// 치환
const masked = str.replace(regex, '[이메일 숨김]');
// 'Contact us at [이메일 숨김] or [이메일 숨김]'
// 분할
'a,b;c:d'.split(/[,;:]/);
// ['a', 'b', 'c', 'd']
// 반복 매칭 (matchAll)
for (const match of str.matchAll(/(\w+)@(\w+\.\w+)/g)) {
console.log(`로컬: ${match[1]}, 도메인: ${match[2]}`);
}
Toolypet Regex Tester 활용
정규표현식을 작성할 때 가장 어려운 점은 즉각적인 피드백을 받기 어렵다는 것입니다. Toolypet의 Regex Tester는 이 문제를 해결합니다:
- 패턴과 테스트 문자열을 입력하면 실시간으로 매칭 결과 확인
- 각 캡처 그룹이 무엇을 매칭했는지 시각적으로 표시
- 여러 플래그(g, i, m)를 토글로 간편하게 테스트
- 자주 사용하는 패턴 템플릿 제공
복잡한 정규표현식을 디버깅할 때, 코드에서 직접 테스트하는 것보다 Toolypet에서 먼저 검증하는 것이 훨씬 효율적입니다.