Rust에서 정규 표현식 마스터하기: 문자열 처리를 위한 완벽 가이드
정규 표현식(Regex)은 문자열 패턴 매칭에 있어 강력한 도구입니다. Rust에서는 이 기능을 사용하기 위해 외부 크레이트가 필요하지만, 그 활용성은 무궁무진합니다. 이 글에서는 Rust에서 정규 표현식을 사용하는 방법부터 고급 기능까지 차근차근 알아보겠습니다.

🚀 시작하기: Rust에서 정규 표현식 설정하기
Rust는 파이썬과 달리 정규 표현식이 표준 라이브러리에 포함되어 있지 않습니다. 대신 regex 크레이트를 사용해야 합니다. 프로젝트에 이 크레이트를 추가하려면 Cargo.toml 파일에 다음 내용을 추가하세요:
[dependencies]
regex = "1"
이렇게 하면 Rust 코드에서 정규 표현식을 사용할 준비가 끝납니다.
🔍 기본 패턴 매칭: 첫 번째 정규 표현식 사용하기
정규 표현식의 기본적인 사용법을 살펴봅시다. 다음은 날짜 형식의 문자열에서 년, 월, 일을 추출하는 간단한 예제입니다:
use regex::Regex;
fn main() {
let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
let text = "2023-07-16";
let cap = re.captures(text).unwrap();
println!("Year: {}", &cap[1]);
println!("Month: {}", &cap[2]);
println!("Day: {}", &cap[3]);
}
이 코드는 어떻게 동작할까요? Regex::new 함수는 정규 표현식 패턴을 컴파일하여 Regex 인스턴스를 생성합니다. r"..." 문법은 원시 문자열(raw string)로, 백슬래시를 이스케이프 처리하지 않아도 됩니다. 정규식에서 \d는 숫자를 의미하고, {n}은 앞의 패턴이 n번 반복됨을 나타냅니다.
captures 메서드는 패턴에 맞는 부분을 찾아 캡처 그룹으로 반환합니다. 첫 번째 그룹(인덱스 0)은 전체 매치를 나타내고, 이후 그룹들은 괄호로 캡처된 부분들을 나타냅니다.
🔎 탐색 기능: find와 find_iter 사용하기
정규 표현식의 가장 기본적인 기능 중 하나는 패턴 검색입니다. Rust의 regex 크레이트는 이를 위해 find와 find_iter 메서드를 제공합니다.
⚡ find 메서드: 첫 매치 찾기
find 메서드는 패턴과 일치하는 첫 번째 위치를 찾아 Option<Match> 타입으로 반환합니다:
let re = Regex::new("world").unwrap();
let mat = re.find("Hello, world!").unwrap();
println!("Found match at {}", mat.start()); // 7 출력
실제 프로젝트에서는 이런 기능을 활용해 특정 패턴이 문자열 내에 존재하는지 확인하고, 위치를 파악할 수 있습니다. 예를 들어, 로그 파일에서 특정 에러 메시지의 위치를 찾거나, 사용자 입력에서 특정 패턴이 있는지 확인하는 데 유용합니다.
⚡ find_iter 메서드: 모든 매치 찾기
여러 번 등장하는 패턴을 모두 찾고 싶다면 find_iter 메서드를 사용할 수 있습니다:
let re = Regex::new(r"\b\w{5}\b").unwrap();
let text = "Hello, world! This is a Rust program.";
for mat in re.find_iter(text) {
println!("Found '{}' at position {}", mat.as_str(), mat.start());
}
이 예제는 5글자 단어를 모두 찾아 출력합니다. \b는 단어 경계를, \w{5}는 5개의 단어 문자를 의미합니다. 실행하면 "Hello", "world", "program" 등의 단어와 그 위치가 출력됩니다.
📝 제가 경험한 정규 표현식의 실전 활용
제가 최근에 진행한 프로젝트에서는 웹 크롤링 데이터에서 특정 정보를 추출해야 했습니다. HTML 문서에서 모든 이메일 주소를 추출하는 작업이었죠. 정규 표현식 없이는 정말 복잡했을 작업이 몇 줄의 코드로 해결되었습니다:
let re = Regex::new(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b").unwrap();
let html = "연락처: info@example.com, support@rust-lang.org";
for email in re.find_iter(html) {
println!("Found email: {}", email.as_str());
}
이 코드는 문서 내의 모든 이메일 주소를 정확하게 찾아냈고, 데이터 처리 시간도 크게 단축되었습니다. 정규 표현식의 강력함을 실감한 순간이었죠!
🔄 고급 기능: 캡처 그룹과 치환
정규 표현식의 진가는 복잡한 패턴 매칭과 문자열 조작에서 발휘됩니다.
명명된 캡처 그룹 (Named Capture Groups)
캡처 그룹에 이름을 붙이면 코드의 가독성이 크게 향상됩니다:
let re = Regex::new(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})").unwrap();
let text = "2023-07-16";
let cap = re.captures(text).unwrap();
println!("Year: {}", &cap["year"]);
println!("Month: {}", &cap["month"]);
println!("Day: {}", &cap["day"]);
숫자 인덱스 대신 이름으로 접근할 수 있어 코드가 더 명확해집니다.
문자열 치환 (String Replacement)
replace 메서드를 사용하면 패턴에 맞는 부분을 다른 문자열로 치환할 수 있습니다:
let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
let text = "Date: 2023-07-16";
let result = re.replace(text, "$3/$2/$1");
println!("{}", result); // "Date: 16/07/2023" 출력
여기서 $1, $2, $3는 각각 첫 번째, 두 번째, 세 번째 캡처 그룹을 나타냅니다.
📊 정규 표현식 vs 표준 문자열 메서드 비교
어떤 상황에서는 정규 표현식이 더 적합하고, 다른 상황에서는 표준 문자열 메서드가 더 나은 선택일 수 있습니다. 아래 표는 두 방식의 장단점을 비교합니다:

정규 표현식은 강력하지만 몇 가지 주의해야 할 점이 있습니다:
✔️ 성능에 주의하세요: 복잡한 정규 표현식은 성능 저하를 가져올 수 있습니다. 특히 .*와 같은 탐욕적(greedy) 패턴은 사용에 주의해야 합니다.
✔️ 컴파일 비용을 고려하세요: 정규 표현식은 사용 전에 컴파일되어야 합니다. 루프 내에서 반복적으로 컴파일하는 것은 피하고, 가능하면 미리 컴파일해 재사용하세요.
✔️ 가독성을 유지하세요: 복잡한 패턴은 주석을 달거나 여러 작은 패턴으로 분리하세요.
✔️ 에러 처리를 잊지 마세요: unwrap()은 예제에서는 괜찮지만, 실제 코드에서는 적절한 에러 처리를 구현해야 합니다.
🌟 결론: Rust에서 정규 표현식 활용하기
Rust에서 정규 표현식은 다양한 문자열 처리 작업을 효율적으로 수행할 수 있는 강력한 도구입니다. 기본적인 패턴 매칭부터 복잡한 문자열 조작까지, regex 크레이트는 다양한 기능을 제공합니다.
정규 표현식의 강점은 복잡한 패턴을 간결하게 표현할 수 있다는 점입니다. 하지만 모든 상황에 정규 표현식이 필요한 것은 아닙니다. 간단한 문자열 작업에는 Rust의 표준 문자열 메서드가 더 효율적일 수 있습니다.
정규 표현식의 구문을 익히고 적절한 상황에서 활용한다면, 문자열 처리 코드가 더 간결하고 표현력 있게 변할 것입니다. 계속해서 연습하고 복잡한 패턴도 도전해보세요. 시간이 지날수록 정규 표현식은 여러분의 코딩 도구 상자에서 없어서는 안 될 중요한 도구가 될 것입니다.
'Rust' 카테고리의 다른 글
[Rust] 함수 값 전달(Passing Arguments by Value) 완벽 가이드 (0) | 2025.02.24 |
---|---|
[Rust] 포인터의 종류와 사용방법 (0) | 2023.12.11 |
[Rust] Option<T> 의 사용방법에 대하여 (2) | 2023.12.06 |
Rust in Jupyter notebook (0) | 2023.12.04 |
[Rust] Clap과 커맨드 라인 argument 다루기 (0) | 2023.09.07 |