개발자를 위한 정규 표현식 치트 시트
· 12분 읽기
목차
정규 표현식 소개
정규 표현식(regex)은 모든 개발자가 마스터해야 하는 강력한 패턴 매칭 도구입니다. 장황한 문자열 조작 코드를 작성하지 않고도 텍스트 데이터를 검색, 검증 및 조작할 수 있는 간결하고 선언적인 방법을 제공합니다.
폼 검증을 구축하든, 로그 파일을 파싱하든, API에서 데이터를 추출하든, 데이터셋을 정리하든, 정규식은 우아한 솔루션을 제공합니다. 단일 정규식 패턴으로 수십 줄의 조건부 로직을 대체할 수 있어 코드를 더 유지보수하기 쉽고 오류가 적게 만듭니다.
JavaScript, Python, Java, PHP, Ruby와 같은 최신 프로그래밍 언어는 모두 내장 정규식 지원을 제공합니다. 구문을 배우면 거의 모든 개발 환경에서 이러한 기술을 적용할 수 있습니다.
프로 팁: 정규 표현식은 처음에는 암호처럼 보일 수 있지만 일관된 패턴을 따릅니다. 간단한 표현식으로 시작하여 자신감이 생기면 점차 복잡성을 높이세요. 온라인 정규식 테스터를 사용하여 실시간으로 매치를 실험하고 시각화하세요.
기본 구문 및 요소
복잡한 패턴을 다루기 전에 정규식의 기본 구성 요소를 이해하는 것이 필수적입니다. 이러한 핵심 요소는 작성할 모든 정규 표현식의 기초를 형성합니다.
리터럴 문자
가장 간단한 정규식 패턴은 나타나는 그대로 리터럴 문자와 정확히 일치합니다. cat 패턴은 텍스트에서 "cat" 문자열이 나타나는 곳마다 일치합니다.
대부분의 영숫자 문자는 리터럴이지만 특정 특수 문자(메타문자라고 함)는 특별한 의미를 가지며 리터럴로 일치시키려면 백슬래시로 이스케이프해야 합니다.
필수 메타문자
| 패턴 | 설명 | 예제 | 일치 |
|---|---|---|---|
. |
개행 문자를 제외한 모든 단일 문자와 일치 | c.t |
"cat", "cot", "c9t" |
^ |
문자열 시작 위치를 나타냄 | ^Hello |
"Hello world" (시작 부분만) |
$ |
문자열 끝 위치를 나타냄 | world$ |
"Hello world" (끝 부분만) |
* |
0회 이상 반복과 일치 | ab*c |
"ac", "abc", "abbc" |
+ |
1회 이상 반복과 일치 | ab+c |
"abc", "abbc" ("ac"는 아님) |
? |
0회 또는 1회 발생과 일치 | colou?r |
"color", "colour" |
| |
교체 (OR 연산자) | cat|dog |
"cat" 또는 "dog" |
\ |
특수 문자 이스케이프 | \. |
리터럴 마침표 문자 |
특수 문자 이스케이프
메타문자를 리터럴로 일치시켜야 할 때는 백슬래시를 접두사로 붙입니다. 예를 들어, 리터럴 마침표를 일치시키려면 . 대신 \.를 사용합니다.
이스케이프가 필요한 일반적인 문자는 다음과 같습니다: . * + ? ^ $ { } [ ] ( ) | \
// 리터럴 물음표 일치
const pattern = /What\?/;
pattern.test("What?"); // true
// 달러 금액 일치
const price = /\$\d+\.\d{2}/;
price.test("$19.99"); // true
문자 클래스 및 수량자
문자 클래스를 사용하면 특정 집합의 모든 문자와 일치시킬 수 있으며, 수량자는 패턴이 반복되어야 하는 횟수를 제어합니다. 이들은 함께 유연한 패턴 매칭의 중추를 형성합니다.
사전 정의된 문자 클래스
| 클래스 | 설명 | 동등 | 예제 |
|---|---|---|---|
\d |
모든 숫자 | [0-9] |
\d{3}는 "123"과 일치 |
\D |
숫자가 아닌 모든 문자 | [^0-9] |
\D+는 "abc"와 일치 |
\w |
단어 문자 (영숫자 + 밑줄) | [A-Za-z0-9_] |
\w+는 "user_123"과 일치 |
\W |
단어 문자가 아닌 문자 | [^A-Za-z0-9_] |
\W는 "@" 또는 " "와 일치 |
\s |
공백 (공백, 탭, 개행) | [ \t\n\r\f\v] |
\s+는 " "와 일치 |
\S |
공백이 아닌 문자 | [^ \t\n\r\f\v] |
\S+는 "hello"와 일치 |
사용자 정의 문자 집합
대괄호는 사용자 정의 문자 집합을 정의합니다. [aeiou] 패턴은 모든 단일 모음과 일치하고, [0-9a-fA-F]는 모든 16진수 숫자와 일치합니다.
대괄호 안에 캐럿을 사용하여 집합을 부정합니다: [^0-9]는 숫자가 아닌 모든 문자와 일치합니다.
// 모든 모음 일치
const vowels = /[aeiou]/gi;
"Hello World".match(vowels); // ["e", "o", "o"]
// 자음만 일치
const consonants = /[^aeiou\s]/gi;
"Hello".match(consonants); // ["H", "l", "l"]
수량자 상세
수량자는 앞의 요소가 일치해야 하는 횟수를 지정합니다. 기본적으로 탐욕적이며, 가능한 한 많은 텍스트와 일치합니다.
{n}- 정확히 n번:\d{4}는 정확히 4자리 숫자와 일치{n,}- 최소 n번:\d{3,}는 3자리 이상의 숫자와 일치{n,m}- n번에서 m번 사이:\d{2,4}는 2, 3 또는 4자리 숫자와 일치*- 0회 이상 ({0,}와 동등)+- 1회 이상 ({1,}과 동등)?- 0회 또는 1회 ({0,1}과 동등)
빠른 팁: 수량자 뒤에 물음표를 추가하여 비탐욕적(게으른)으로 만드세요. 예를 들어, .*?는 가능한 한 많은 문자가 아닌 가능한 한 적은 문자와 일치합니다. 이는 구분 기호 사이의 콘텐츠를 추출할 때 중요합니다.
앵커 및 단어 경계
앵커는 문자와 일치하지 않고 문자열의 위치와 일치합니다. 텍스트가 특정 위치에 나타나는지 확인해야 할 때 정확한 패턴 매칭에 필수적입니다.
위치 앵커
캐럿 ^는 문자열(또는 다중 행 모드에서 줄)의 시작과 일치하고, 달러 기호 $는 끝과 일치합니다. 전체 문자열이 패턴과 일치해야 하는 검증에 매우 유용합니다.
// 전체 문자열이 숫자인지 검증
const onlyDigits = /^\d+$/;
onlyDigits.test("12345"); // true
onlyDigits.test("123abc"); // false
// "Error"로 시작하는 줄 일치
const errorLines = /^Error/gm;
const logs = "Info: Starting\nError: Failed\nError: Timeout";
logs.match(errorLines); // ["Error", "Error"]
단어 경계
\b 앵커는 단어 경계, 즉 단어 문자와 비단어 문자 사이의 위치와 일치합니다. 더 큰 단어의 일부를 실수로 일치시키지 않고 전체 단어를 일치시키는 데 완벽합니다.
\B 앵커는 단어 경계가 아닌 위치와 일치합니다.
// "cat"을 전체 단어로만 일치
const wholeCat = /\bcat\b/;
wholeCat.test("cat"); // true
wholeCat.test("cats"); // false
wholeCat.test("concatenate"); // false
// 단어 내의 "cat" 일치
const partialCat = /\Bcat\B/;
partialCat.test("concatenate"); // true
partialCat.test("cat"); // false
단어 경계는 부분 일치를 피하려는 검색 및 바꾸기 작업에 특히 유용합니다. 구문 강조 표시기나 코드 분석기를 구축할 때도 필수적입니다.
그룹 및 캡처
정규식의 괄호는 여러 목적을 제공합니다: 패턴의 일부를 그룹화하고, 나중에 사용할 일치하는 텍스트를 캡처하며, 패턴 내에서 역참조를 가능하게 합니다.
캡처 그룹
괄호는 일치하는 텍스트를 저장하는 번호가 매겨진 캡처 그룹을 만듭니다. 이러한 캡처를 대체 문자열에서 참조하거나 프로그래밍 방식으로 추출할 수 있습니다.
// 날짜 구성 요소 추출
const datePattern = /(\d{4})-(\d{2})-(\d{2})/;
const match = "2026-03-31".match(datePattern);
// match[0]: "2026-03-31" (전체 일치)
// match[1]: "2026" (년)
// match[2]: "03" (월)
// match[3]: "31" (일)
// 캡처를 사용하여 날짜 형식 변경
const text = "Date: 2026-03-31";
const reformatted = text.replace(/(\d{4})-(\d{2})-(\d{2})/, "$2/$3/$1");
// 결과: "Date: 03/31/2026"
비캡처 그룹
(?:...)를 사용하여 캡처를 만들지 않고 패턴을 그룹화합니다. 이는 성능을 향상시키고 교체나 수량자에만 그룹화가 필요할 때 캡처 번호를 깔끔하게 유지합니다.
// 캡처 없이 그룹화
const protocol = /(?:https?|ftp):\/\//;
protocol.test("https://example.com"); // true
// 캡처와 비교 (불필요한 오버헤드)
const protocolCapture = /(https?|ftp):\/\//;
// 필요하지 않은 추가 캡처 그룹 생성
명명된 캡처 그룹
최신 정규식 엔진은 (?<name>...) 구문을 사용하여 명명된 캡처를 지원합니다. 이는 패턴을 자체 문서화하고 유지보수하기 쉽게 만듭니다.
// 명확성을 위한 명명된 캡처
const emailPattern = /(?<user>[\w.]+)@(?<domain>[\w.]+)/;
const match = "[email protected]".match(emailPattern);
console.log(match.groups.user); // "john.doe"
console.log(match.groups.domain); // "example.com"
// 대체에서 사용
const masked = "[email protected]".replace(
/(?<user>[\w.]+)@(?<domain>[\w.]+)/,
"***@$<domain>"
);
// 결과: "***@example.com"
역참조
\1, \2 등을 사용하여 동일한 패턴 내에서 이전 캡처를 참조합니다. 이는 반복되거나 미러링된 패턴을 일치시키는 데 강력합니다.
// 반복된 단어 일치
const repeated = /\b(\w+)\s+\1\b/;
repeated.test("hello hello"); // true
repeated.test("hello world"); // false
// HTML 태그 일치
const htmlTag = /<(\w+)>.*?<\/\1>/;
htmlTag.test("<div>content</div>"); // true
htmlTag.test("<div>content</span>"); // false
정규식 플래그 및 수정자
플래그는 정규식 엔진이 패턴을 해석하는 방식을 수정합니다. 대부분의 언어에서 닫는 구분 기호 뒤에 추가됩니다(예: JavaScript의 /pattern/flags).
일반적인 플래그
- g (전역) - 첫 번째 일치 후 중지하는 대신 모든 일치 찾기
- i (대소문자 무시) - 문자를 일치시킬 때 대소문자 무시
- m (다중 행) -
^와$가 문자열 경계 대신 줄 경계와 일치하도록 만들기 - s (dotall) -
.가 개행 문자와 일치하도록 만들기 - u (유니코드) - 전체 유니코드 지원 활성화
- y (고정) - lastIndex 위치에서만 일치
// 대소문자 무시 검색
const pattern = /hello/i;
pattern.test("HELLO"); // true
pattern.test("Hello"); // true
// 여러 일치를 위한 전역 플래그
const digits = /\d+/g;
"Phone: 555-1234, Fax: 555-5678".match(digits);
// ["555", "1234", "555", "5678"]
// 다중 행 모드
const headers = /^#.+$/gm;
const markdown = "# Title\nContent\n## Subtitle";
markdown.match(headers); // ["# Title", "## Subtitle"]
프로 팁: 전역 플래그는 exec() 및 test()와 같은 메서드의 동작을 변경합니다. 호출 간에 상태를 유지합니다. 예상치 못한 결과가 발생하면 전역 플래그가 필요한지 또는 상태 저장 일치로 인해 문제가 발생하는지 확인하세요.
일반적인 패턴 및 응용
일반적인 개발 작업을 위한 실전 테스트를 거친 정규식 패턴을 살펴보겠습니다. 이러한 패턴은 실제 사용을 통해 개선되었으며 처음에는 고려하지 않을 수 있는 엣지 케이스를 처리합니다.
이메일 검증
이메일 검증은 RFC 사양으로 인해 매우 복잡하지만, 이 실용적인 패턴은 실제 이메일 주소의 99%를 처리합니다:
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
// 유효한 이메일
emailPattern.test("[email protected]"); // true
emailPattern.test("[email protected]"); // true
// 유효하지 않은 이메일
emailPattern.test("invalid@"); // false
emailPattern.test("@example.com"); // false
emailPattern.test("[email protected]"); // false
프로덕션 애플리케이션의 경우 국제화된 도메인과 모든 RFC 엣지 케이스를 처리하는 전용 이메일 검증 라이브러리 사용을 고려하세요. 이메일 검증 도구를 사용하여 이메일 패턴을 대화식으로 테스트할 수도 있습니다.
URL 일치
이 포괄적인 패턴으로 텍스트에서 URL을 일치시키고 추출합니다:
const urlPattern