블로그로 돌아가기
Reference 2026-04-25

2026년 정규표현식 치트시트

정규표현식 패턴, 플래그, 테스트된 예제 빠른 참조.

정규표현식 문법은 매주 쓰는 사람도 세부를 잊을 만큼 빽빽합니다. 이 치트시트는 매일 손이 가는 구문에 더해 2026년 시대의 추가 사항인 유니코드 속성 이스케이프와 v 플래그, 그리고 프로덕션 서비스를 쓰러뜨리는 성능 함정까지 다룹니다.

문자 클래스

  • \d / \D — 숫자 / 숫자 아님
  • \w / \W — 단어 문자(글자, 숫자, 밑줄) / 그 외 전부
  • \s / \S — 공백 / 공백 아님
  • . — 개행 제외 모든 문자 (s 플래그를 더하면 개행 포함)
  • [abc], [a-z], [^abc] — 집합, 범위, 부정 집합
  • \p{L}, \p{Script=Hangul} — 유니코드 속성 이스케이프(u 또는 v 플래그 필요). \w는 ASCII 전용이므로 국제 텍스트 매칭에는 \p{L}을 쓰세요

수량자

  • ? — 0개 또는 1개
  • + — 1개 이상
  • {n}, {n,}, {n,m} — 정확히, 최소, 범위 지정 개수
  • a* — a가 0개 이상
  • 기본은 탐욕적: 수량자는 패턴의 나머지가 성공할 수 있는 한 가장 긴 매치를 취합니다
  • ?를 붙이면 게으른 버전 — +?는 가장 짧은 매치를 취합니다. 고전적 용례는 태그 한 줄 전체가 아니라 태그 하나를 잡는 <.+?>

앵커와 경계

  • ^$ — 문자열의 시작과 끝. m 플래그와 함께면 각 줄의 시작과 끝
  • \b / \B — 단어 경계 / 비경계. \bcat\b은 "cat"은 매치하지만 "category"는 아님
  • 경계 정의는 \w를 따르므로 기본적으로 역시 ASCII 전용

그룹과 역참조

  • (abc) — 캡처 그룹, 왼쪽부터 번호 부여
  • (?:abc) — 비캡처. 순수 그룹핑에는 이것을 써서 번호를 안정시키고 할당을 절약
  • (?<name>abc) — 이름 있는 캡처, match.groups.name으로 읽기
  • \1\k<name> — 역참조. (["'])(.?)\1은 어느 따옴표로든 감싼 문자열을 매치

룩어라운드

  • (?=x) / (?!x) — 긍정 / 부정 룩어헤드
  • (?<=x) / (?<!x) — 긍정 / 부정 룩비하인드 (JavaScript는 ES2018부터)
  • 룩어라운드는 문자를 소비하지 않아 비밀번호 규칙과 삽입 위치 매칭에 이상적입니다. 예: 천 단위 구분자 /\B(?=(\d{3})+(?!\d))/g

플래그

  • g — 첫 매치만이 아니라 전부. exec과 함께면 상태를 가져 번갈아 매치되는 버그의 고전적 원인
  • i — 대소문자 무시
  • m^$가 줄바꿈에서도 매치
  • s — 점이 개행도 매치
  • u — 제대로 된 유니코드: 아스트랄 문자가 한 단위, 속성 이스케이프 활성화
  • v (ES2024) — u의 전부에 더해 [\p{L}--[aeiou]](모음 제외 글자) 같은 집합 연산과 \p{RGI_Emoji} 같은 문자열 속성
  • y — 스티키, 정확히 lastIndex에서 매치. 수제 렉서의 빌딩 블록

검증된 패턴

이메일(실용적):     ^[\w.+-]+@[\w-]+\.[\w.-]+$

IPv4 옥텟 정확: ^(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)$

ISO 8601 날짜: ^\d{4}-\d{2}-\d{2}$

UUID v4: ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$

URL 슬러그: ^[a-z0-9]+(?:-[a-z0-9]+)*$

Hex 색상: ^#(?:[0-9a-fA-F]{3}){1,2}$

이메일 패턴은 의도적으로 느슨합니다. RFC 5321에 완전히 부합하는 패턴은 거대하며 그래도 메일박스의 존재 여부는 알 수 없습니다. 형식은 느슨하게 검증하고, 메일 발송으로 확인하세요.

파국적 백트래킹

장애를 일으키는 유일한 정규식 동작입니다. 겹치는 대안 위의 중첩 수량자 — (a+)+b(\w|\d)+$ 같은 형태 — 는 긴 입력이 거의 매치되다가 끝에서 실패할 때 백트래킹 엔진이 지수적으로 많은 분할을 시도하게 만듭니다. 40자짜리 악의적 문자열이 CPU 코어를 몇 분간 점유할 수 있습니다. 이것이 ReDoS입니다.

방어:

  • 대안을 겹치지 않게 만들고, 이미 수량화된 그룹의 수량화를 피하기
  • .보다 명시적 문자 클래스 선호
  • 선형 시간 엔진(RE2, Rust의 regex 크레이트)은 구조적으로 면역 — 대가는 역참조와 룩어라운드 부재
  • 사용자 제공 패턴을 사용자 제공 입력에 요청 스레드에서 실행하지 말 것. 불가피하면 워커에서 타임아웃 적용

성과를 내는 습관

  • 한 번 컴파일해 재사용: 핫 루프 안의 정규식 리터럴은 일부 엔진에서 상태를 재생성
  • 위치를 아는 한 패턴에 앵커를 — ^는 스캔 대신 즉시 실패시킴
  • 복잡한 패턴은 이름 있는 소스 문자열로 조합해 주석화
  • 적대적 입력으로 테스트: 빈 문자열, 매우 긴 근사 매치, ASCII 밖 유니코드

엔진은 문법보다 더 다르다

같은 패턴이 엔진마다 다르게 동작할 수 있으며, 어느 계열 위에 있는지 알면 미묘한 이식 버그를 예방합니다.

  • 백트래킹 엔진 — JavaScript(V8의 Irregexp), PCRE2, Python의 re, Java의 java.util.regex. 전체 기능, 최악의 경우 지수 시간.
  • 선형 시간 엔진 — RE2(Go의 regexp가 사용), Rust의 regex 크레이트. 오토마타로 O(n) 매칭 보장. 역참조와 룩어라운드 없음.
  • 하이브리드 — .NET의 NonBacktracking 모드, PCRE2의 DFA 매칭 함수.

Stack Overflow에서 패턴을 복사하기 전 확인할 기능 격차: 룩비하인드(16.4 이전 Safari 미지원, Go/RE2에 부재), 소유격 수량자와 원자 그룹(PCRE와 Java 전용 — JavaScript는 룩어헤드와 역참조 트릭으로 흉내), \p 속성 이스케이프 지원 범위. 특히 JavaScript에서는 전역 매치 순회에 matchAll을 선호하세요. exec 루프를 취약하게 만드는 공유 lastIndex 상태를 우회합니다. 그리고 일반 문자열을 받는 String.replace는 첫 번째 항목만 치환하므로 g 플래그가 있는 정규식이 필요하다는 것을 기억하세요.

sdk.is/regex-tester 의 정규식 테스터에서 매치 하이라이트와 함께 패턴을 실시간으로 다듬으세요.