정규 표현식 튜토리얼: 초보자를 위한 Regex 가이드

· 12분 읽기

목차

정규 표현식이란 무엇이며 왜 배워야 할까요?

정규 표현식(일반적으로 regex 또는 regexp로 축약)은 특수 구문을 사용하여 텍스트를 검색, 검증, 추출 및 조작할 수 있는 강력한 패턴 매칭 도구입니다. 단순한 "찾기 및 바꾸기" 작업을 훨씬 뛰어넘는 정교한 검색 언어라고 생각하면 됩니다.

수천 줄의 로그 데이터가 포함된 파일에서 모든 이메일 주소를 추출하거나, 사용자의 전화번호가 올바른 형식을 따르는지 검증해야 한다고 상상해보세요. 전통적인 문자열 조작 방법을 사용하면 장황하고 유지보수하기 어려운 코드가 만들어집니다. 정규 표현식은 이러한 작업을 단일하고 간결한 패턴으로 수행할 수 있습니다.

정규 표현식의 핵심은 리터럴 문자와 특수 메타문자의 조합을 사용하여 검색 패턴을 정의하는 것입니다. 이러한 패턴은 "cat"과 같은 단순한 문자열이나 이메일 주소, URL 또는 신용카드 번호와 같은 복잡한 구조를 매칭할 수 있습니다.

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

실제 응용 사례

정규 표현식은 소프트웨어 개발과 데이터 처리 전반에 걸쳐 광범위하게 사용됩니다:

프로 팁: regex는 강력하지만 모든 작업에 최선의 도구는 아닙니다. HTML이나 JSON과 같은 복잡한 구조화된 데이터를 파싱할 때는 전용 파서를 사용하세요. Regex는 일반 텍스트의 패턴 매칭에 가장 적합합니다.

기본 구문과 기초

정규 표현식은 두 가지 유형의 문자로 구성됩니다: 리터럴 문자(자기 자신과 매칭) 및 메타문자(특별한 의미를 가짐). 기초부터 시작해봅시다.

리터럴 문자

가장 간단한 regex는 일반 텍스트입니다. cat 패턴은 텍스트에서 정확히 "cat" 문자열과 매칭됩니다.

텍스트: "The cat sat on the mat"
Regex: cat
매칭: "The cat sat on the mat"

리터럴 문자는 기본적으로 대소문자를 구분하므로, 대소문자 구분 없는 플래그를 사용하지 않는 한 cat은 "Cat"이나 "CAT"과 매칭되지 않습니다.

점 메타문자 (.)

.은 개행 문자를 제외한 모든 단일 문자와 매칭되는 와일드카드입니다.

텍스트: "cat", "cot", "cut", "c@t"
Regex: c.t
매칭: 네 문자열 모두

리터럴 점 문자와 매칭하려면 백슬래시로 이스케이프하세요: \.

텍스트: "file.txt"
Regex: file\.txt
매칭: "file.txt" ("fileAtxt"는 아님)

앵커: 위치 매칭

앵커는 문자와 매칭하지 않고 텍스트의 위치와 매칭합니다.

캐럿 (^) - 줄의 시작: ^ 앵커는 문자열이나 줄의 시작과 매칭됩니다.

텍스트: "cat\ndog\ncat"
Regex: ^cat
매칭: 첫 번째 "cat"만

달러 기호 ($) - 줄의 끝: $ 앵커는 문자열이나 줄의 끝과 매칭됩니다.

텍스트: "cat\ndog\ncat"
Regex: cat$
매칭: 마지막 "cat"만

앵커 결합: 둘 다 사용하여 전체 줄과 매칭합니다.

Regex: ^cat$
매칭: 앞뒤에 아무것도 없이 정확히 "cat"만 포함하는 줄

단어 경계 (\b)

\b 앵커는 단어와 비단어 문자 사이의 위치인 단어 경계와 매칭됩니다.

텍스트: "cat category caterpillar"
Regex: \bcat\b
매칭: 독립적인 단어 "cat"만

이것은 부분 단어와 매칭하지 않고 전체 단어를 찾는 데 매우 유용합니다.

이스케이프 시퀀스

regex의 특수 문자는 리터럴로 매칭하려면 백슬래시로 이스케이프해야 합니다:

특수 문자 이스케이프 형식
. * + ? ^ $ { } [ ] ( ) | \ \. \* \+ \? \^ \$ \{ \} \[ \] \( \) \| \\

가격 매칭 예제:

Regex: \$\d+\.\d{2}
매칭: "$19.99", "$5.00"

문자 클래스와 범위

문자 클래스를 사용하면 문자 집합을 정의하고 그 중 하나와 매칭할 수 있습니다. 대괄호로 묶습니다.

기본 문자 클래스

대괄호 []는 내부의 모든 단일 문자와 매칭되는 문자 집합을 만듭니다.

텍스트: "cat", "cot", "cut", "cit"
Regex: c[aou]t
매칭: "cat", "cot", "cut" ("cit"는 아님)

문자 범위

하이픈을 사용하여 문자 범위를 정의합니다:

텍스트: "a1", "b2", "c3", "d4"
Regex: [a-c][1-3]
매칭: "a1", "b2", "c3" ("d4"는 아님)

부정 문자 클래스

문자 클래스의 시작 부분에 캐럿 ^을 사용하여 부정합니다—집합에 없는 모든 문자와 매칭합니다.

Regex: [^0-9]
매칭: 숫자가 아닌 모든 문자
텍스트: "abc123def"
Regex: [^a-z]+
매칭: "123" (소문자가 아닌 문자의 시퀀스)

미리 정의된 문자 클래스

Regex는 일반적인 문자 클래스에 대한 단축 표기를 제공합니다:

단축 표기 동등한 표현 설명
\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] 공백이 아닌 모든 문자

간단한 전화번호 매칭 예제:

Regex: \d{3}-\d{3}-\d{4}
매칭: "555-123-4567"

빠른 팁: 단축 클래스의 대문자 버전은 항상 소문자 버전의 부정입니다. \d는 숫자와 매칭하고, \D는 숫자가 아닌 것과 매칭합니다.

수량자: 매칭 반복 제어하기

수량자는 문자나 그룹이 몇 번 매칭되어야 하는지 지정합니다. 반복하려는 요소 뒤에 배치됩니다.

기본 수량자

수량자 실전 예제

별표 (*) - 0회 이상:

Regex: ca*t
매칭: "ct", "cat", "caat", "caaat"

플러스 (+) - 1회 이상:

Regex: ca+t
매칭: "cat", "caat", "caaat" ("ct"는 아님)

물음표 (?) - 선택적:

Regex: colou?r
매칭: "color"와 "colour"

정확한 횟수 {n}:

Regex: \d{3}
매칭: "123"과 같이 정확히 세 자리 숫자

범위 {n,m}:

Regex: \d{2,4}
매칭: "12", "123" 또는 "1234"와 같이 2~4자리 숫자

탐욕적 vs. 게으른 수량자

기본적으로 수량자는 탐욕적입니다—가능한 한 많은 텍스트와 매칭합니다. 수량자 뒤에 ?를 추가하면 게으르게 만듭니다(가능한 한 적게 매칭).

텍스트: "<div>content</div><div>more</div>"
Regex (탐욕적): <div>.*</div>
매칭: "<div>content</div><div>more</div>" (전체 문자열)

Regex (게으른): <div>.*?</div>
매칭: "<div>content</div>" (첫 번째 태그만)

게으른 수량자:

프로 팁: 탐욕적 매칭은 큰 텍스트에서 성능 문제를 일으킬 수 있습니다. 특히 중첩된 구조로 작업할 때 가능한 가장 짧은 문자열과 매칭해야 할 때는 게으른 수량자를 사용하세요.

실용적인 예제: HTML 태그 매칭

Regex: <([a-z]+)>.*?</\1>
매칭: "<p>text</p>" 또는 "<div>content</div>"와 같은 쌍을 이루는 HTML 태그

이 패턴은 여러 태그를 한 번에 캡처하지 않도록 게으른 매칭을 사용하고, 여는 태그와 닫는 태그가 일치하도록 역참조(다음에 다룸)를 사용합니다.

그룹과 캡처

괄호 ()는 여러 목적을 제공하는 그룹을 만듭니다: 패턴의 일부를 함께 그룹화하고, 나중에 사용할 매칭된 텍스트를 캡처하며, 역참조를 가능하게 합니다.

기본 그룹화

그룹을 사용하면 여러 문자에 수량자를 적용할 수 있습니다:

Regex: (ha)+
매칭: "ha", "haha", "hahaha"

그룹화 없이 ha+는 "ha", "haa", "haaa"와 매칭됩니다('a'만 반복됨).

캡처 그룹

그룹은 매칭한 텍스트를 자동으로 캡처하며, 나중에 참조할 수 있습니다:

텍스트: "John Smith"
Regex: (\w+) (\w+)
캡처: 그룹 1 = "John", 그룹 2 = "Smith"

대부분의 프로그래밍 언어에서 이러한 캡처에 액세스할 수 있습니다:

// JavaScript 예제
const match = "John Smith".match(/(\w+) (\w+)/);
console.log(match[1]); // "John"
console.log(match[2]); // "Smith"

역참조

역참조를 사용하면 패턴의 앞부분에서 그룹이 캡처한 것과 동일한 텍스트와 매칭할 수 있습니다. \1, \2 등을 사용합니다.

Regex: (\w+) \1
매칭: "the the" 또는 "is is"와 같은 반복된 단어
Regex: <([a-z]+)>.*?</\1>
매칭: "<div>...</div>"와 같이 일치하는 HTML 태그

비캡처 그룹

때로는 캡처 없이 그룹화만 필요합니다. 비캡처 그룹에는 (?:...)를 사용합니다:

Regex: (?:https?|ftp)://\S+
매칭: http, https 또는 ftp로 시작하는 URL
(프로토콜은 그룹으로 캡처되지 않음)

비캡처 그룹은 캡처된 텍스트를 참조할 필요가 없을 때 성능을 향상시킵니다.

명명된 캡처 그룹

명명된 그룹은 regex를 더 읽기 쉽고 유지보수하기 쉽게 만듭니다:

Regex: (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
매칭: "2026-03-31"과 같은 날짜
액세스: match.groups.year, match.groups.month, match.groups.day

명명된 그룹은 번호 참조가 혼란스러워지는 복잡한 패턴에서 특히 유용합니다.

빠른 팁: 복잡한 패턴에는 명명된 그룹을 사용하세요