정규식 치트 시트: 궁극의 참조 가이드
정규 표현식(Regex)은 매우 강력하지만 마스터하기 어렵기로 유명합니다. 이메일 주소 유효성 검사, 데이터 스크래핑, 코드 검색 등 어떤 작업을 하든 신뢰할 수 있는 정규식 치트 시트가 있으면 수많은 시간을 절약할 수 있습니다.
이 가이드에서는 기본 문자부터 복잡한 전방/후방 탐색에 이르기까지 모든 정규식 구성 요소를 시각적 설명 및 실제 예제와 함께 분석합니다.
1. 핵심 메타 문자
모든 정규식 패턴의 기본 구성 요소입니다.
| 메타 문자 | 설명 | 예시 |
|---|---|---|
. |
줄바꿈을 제외한 모든 단일 문자 일치 | a.b는 acb, a1b와 일치 |
\ |
특수 문자 이스케이프 | \.은 리터럴 .과 일치 |
| |
선택 (OR) | cat|dog는 cat 또는 dog와 일치 |
[] |
문자 집합 (대괄호 안의 모든 문자) | [aeiou]는 모든 모음과 일치 |
[^] |
부정 문자 집합 | [^0-9]는 숫자가 아닌 모든 문자와 일치 |
2. 수량자: 빈도 제어
수량자는 문자나 그룹이 몇 번 나타나야 하는지 정규식 엔진에 알려줍니다.
| 수량자 | 설명 | 예시 |
|---|---|---|
* |
0회 이상 | a*는 ``, a, aa와 일치 |
+ |
1회 이상 | a+는 a, aa와 일치 |
? |
0회 또는 1회 (선택 사항) | a?는 `` 또는 a와 일치 |
{n} |
정확히 n회 |
a{3}는 aaa와 일치 |
{n,} |
n회 이상 |
a{2,}는 aa, aaa와 일치 |
{n,m} |
n회에서 `m회 사이 |
a{2,4}는 aa, aaa, aaaa와 일치 |
3. 문자 클래스: 일반적인 단축키
| 클래스 | 설명 | 동일한 표현 |
|---|---|---|
\d |
모든 숫자 | [0-9] |
\D |
숫자가 아닌 모든 문자 | [^0-9] |
\w |
모든 단어 문자 (영문자, 숫자, 언더바) | [a-zA-Z0-9_] |
\W |
단어 문자가 아닌 모든 문자 | [^a-zA-Z0-9_] |
\s |
모든 공백 문자 (공백, 탭, 줄바꿈) | [ \t\n\r\f\v] |
\S |
공백 문자가 아닌 모든 문자 | [^ \t\n\r\f\v] |
4. 앵커: 경계 정의
| 앵커 | 설명 | 예시 |
|---|---|---|
^ |
문자열/줄의 시작 | ^Hello |
$ |
문자열/줄의 끝 | World$ |
\b |
단어 경계 | \bcat\b ("cat"은 일치하지만 "category"는 일치하지 않음) |
\B |
단어 경계가 아님 | \Bcat ("category" 내의 "cat"과 일치) |
5. 그룹 및 캡처
| 구문 | 설명 | 예시 |
|---|---|---|
(...) |
캡처 그룹 | (abc)+는 abcabc와 일치 |
(?:...) |
비캡처 그룹 | (?:abc)+ |
(?<name>...) |
이름이 지정된 캡처 그룹 | (?<id>\d+) |
\1 |
1번 그룹에 대한 역참조 | (\w)\1은 aa, bb와 일치 |
6. 전방/후방 탐색 (Lookaround): 고급 필터링
Lookaround를 사용하면 패턴이 다른 패턴의 앞이나 뒤에 올 때(또는 오지 않을 때)만 일치하도록 할 수 있으며, 해당 패턴은 일치 결과에 포함되지 않습니다.
| 구문 | 이름 | 설명 |
|---|---|---|
(?=...) |
긍정 전방 탐색 (Positive Lookahead) | 뒤에 ...이 오는 경우 |
(?!...) |
부정 전방 탐색 (Negative Lookahead) | 뒤에 ...이 오지 않는 경우 |
(?<=...) |
긍정 후방 탐색 (Positive Lookbehind) | 앞에 ...이 오는 경우 |
(?<!...) |
부정 후방 탐색 (Negative Lookbehind) | 앞에 ...이 오지 않는 경우 |
7. 철도 다이어그램을 통한 정규식 시각화
복잡한 정규식 패턴은 금방 읽기 어려워질 수 있습니다. **철도 다이어그램(Railroad Diagrams)**은 정규 표현식의 흐름을 시각적으로 나타내는 방법입니다.
기차 선로를 상상해 보세요:
- 선로는 선택 (
|)에서 갈라집니다. - 선로는 수량자 (
*,+)에서 루프를 형성합니다. - 선로는 그룹 상자를 통과합니다.
시각화 도구를 사용하면 중첩된 그룹이나 복잡한 수량자를 다룰 때 로직 오류를 디버깅하는 데 도움이 됩니다.
8. 실제 예제
이메일 유효성 검사 (단순화)
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
강력한 비밀번호 (전방 탐색 예제)
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$
(최소 하나의 소문자, 하나의 대문자, 하나의 숫자를 포함하고 8자 이상)
전화번호 (미국 형식)
^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$
9. 자주 묻는 질문 (FAQ)
Q: "Greedy(탐욕적)" 일치와 "Lazy(게으른)" 일치의 차이점은 무엇인가요?
A: 기본적으로 수량자는 탐욕적입니다. 즉, 가능한 한 많은 문자와 일치하려고 합니다. 수량자 뒤에 ?를 추가하면(예: .*?) 게으른(또는 비탐욕적) 일치가 되어 가능한 한 적은 문자와 일치하게 됩니다.
Q: 대소문자를 구분하지 않고 검색하려면 어떻게 하나요?
A: 대부분의 정규식 엔진은 대소문자 구분을 하지 않기 위해 플래그(보통 i)를 사용합니다. 예를 들어, /hello/i는 Hello, HELLO, hello 모두와 일치합니다.
Q: 백트래킹(Backtracking)이란 무엇이며 왜 중요한가요?
A: 정규식 엔진이 한 경로를 시도했다가 실패하고 다른 경로를 시도하기 위해 "되돌아가는" 것을 백트래킹이라고 합니다. 중첩된 수량자가 많은 복잡한 패턴은 **치명적 백트래킹(Catastrophic Backtracking)**을 유발하여 애플리케이션이나 서버가 멈출 수 있습니다.