Toolypet
Back to Blog
Dev

정규표현식 치트시트: 자주 쓰는 패턴 모음

웹 개발에서 가장 많이 사용하는 정규표현식 패턴과 활용 예제를 정리했습니다.

Toolypet Team6 min read
정규표현식 치트시트: 자주 쓰는 패턴 모음

정규표현식, 왜 배워야 할까?

정규표현식(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-255
  • 2[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>' (첫 번째만)

수량자 뒤에 ?를 붙이면 게으른 매칭이 됩니다: *?, +?, ??

최적화 팁

  1. 앵커 사용: ^$로 범위를 명확히 제한
  2. 구체적인 문자 클래스 사용: .* 대신 [^<]*처럼 제한
  3. 비캡처 그룹 사용: 캡처가 필요 없으면 (?:...)사용
// 캡처 그룹 - 느림 (매칭 결과 저장)
/(abc)+/

// 비캡처 그룹 - 빠름 (저장하지 않음)
/(?:abc)+/

언어별 차이점

기능JavaScriptPythonJava
문법/pattern/flagsr'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에서 먼저 검증하는 것이 훨씬 효율적입니다.

RegexRegular ExpressionValidationPattern Matching