안녕하세요! 지난 시간에는 파이썬에서 날짜와 시간을 다루는 데 필수적인 datetime 모듈에 대해 알아보았습니다. 이제 시간 관련 데이터를 정확하고 유연하게 처리할 수 있게 되셨을 거예요!
이번 시간에는 파이썬에서 **정규 표현식(Regular Expression)**을 사용하여 문자열을 검색하고 조작하는 방법에 대해 알아보겠습니다. 정규 표현식은 특정 패턴을 가진 문자열을 찾거나, 추출하거나, 바꾸는 데 사용되는 강력한 도구입니다.
일반적인 문자열 메서드(find(), replace(), split())로는 처리하기 어려운 복잡한 문자열 패턴을 다룰 때 정규 표현식이 빛을 발합니다. 마치 특정 규칙을 가진 문자열을 찾아내는 '패턴 탐정'과 같다고 생각하시면 됩니다.
Part 1: 정규 표현식(Regular Expression)이란 무엇인가?
정규 표현식(Regular Expression), 줄여서 정규식(Regex) 또는 RegExp는 문자열에서 특정 패턴을 검색, 추출, 또는 대체하는 데 사용되는 문자열입니다. 특정한 규칙을 가진 문자의 조합으로 이루어지며, 이 규칙을 통해 복잡한 문자열 패턴을 정의할 수 있습니다.
1. 정규 표현식의 필요성
- 복잡한 패턴 검색: "이메일 주소 형식 찾기", "전화번호 형식 찾기", "HTML 태그 제거" 등 고정된 문자열이 아닌, 특정 규칙을 가진 문자열을 찾을 때 유용합니다.
- 데이터 유효성 검사: 사용자 입력이 특정 형식(예: 비밀번호 규칙, 날짜 형식)을 따르는지 검사할 때 사용합니다.
- 문자열 조작: 특정 패턴에 맞는 부분을 한 번에 바꾸거나, 분리할 때 사용합니다.
2. 파이썬의 re 모듈
파이썬에서는 re 모듈을 통해 정규 표현식을 지원합니다.
import re
Part 2: 정규 표현식의 기본 패턴
정규 표현식은 다양한 메타 문자(Meta Characters)와 시퀀스를 사용하여 패턴을 정의합니다.
메타 문자/시퀀스 | 설명 | 예시 (패턴) | 매칭되는 문자열 |
. | 모든 단일 문자 (줄바꿈 문자 \n 제외) | a.b | acb, aab |
^ | 문자열의 시작 | ^Hello | Hello World |
$ | 문자열의 끝 | World$ | Hello World |
* | 앞의 문자가 0번 이상 반복 | ab*c | ac, abc, abbbc |
+ | 앞의 문자가 1번 이상 반복 | ab+c | abc, abbbc |
? | 앞의 문자가 0번 또는 1번 반복 | ab?c | ac, abc |
{m} | 앞의 문자가 m번 반복 | a{3}b | aaab |
{m,n} | 앞의 문자가 m번 이상 n번 이하 반복 | a{2,4}b | aab, aaab, aaaab |
[] | 괄호 안의 문자 중 하나 (문자 클래스) | [abc] | a, b, c |
[^] | 괄호 안의 문자를 제외한 모든 문자 | [^abc] | d, e, 1 |
` | ` | OR 조건 (둘 중 하나) | `a |
() | 그룹화 (패턴 묶기, 캡처) | (ab)+ | ab, abab |
\ | 특수 문자를 일반 문자로, 일반 문자를 특수 문자로 (이스케이프) | \. | . (점 문자) |
\d | 모든 숫자 (0-9) | \d+ | 123, 45 |
\D | 숫자가 아닌 모든 문자 | \D+ | abc, !@# |
\w | 모든 단어 문자 (알파벳, 숫자, 밑줄 _) | \w+ | hello_123 |
\W | 단어 문자가 아닌 모든 문자 | \W+ | !@#, |
\s | 모든 공백 문자 (스페이스, 탭, 줄바꿈 등) | \s+ | , \n |
\S | 공백 문자가 아닌 모든 문자 | \S+ | abc, 123 |
\b | 단어 경계 (단어의 시작이나 끝) | \bcat\b | cat in "The cat sat" |
\B | 단어 경계가 아님 | \Bcat\B | cat in "wildcat" |
Part 3: re 모듈의 주요 함수
re 모듈은 정규 표현식을 사용하여 문자열을 처리하는 다양한 함수를 제공합니다.
1. re.match(pattern, string) - 문자열 시작부터 매칭 확인
- 문자열의 시작 부분부터 패턴과 일치하는지 확인합니다.
- 일치하면 Match object를 반환하고, 일치하지 않으면 None을 반환합니다.
예시:
# 파일 이름: re_match.py
import re
text1 = "Hello World"
text2 = "World Hello"
# 'Hello'로 시작하는지 매칭
match_obj1 = re.match("Hello", text1)
match_obj2 = re.match("Hello", text2)
if match_obj1:
print(f"'{text1}'에서 매칭 성공: {match_obj1.group()}") # 매칭된 문자열 반환
else:
print(f"'{text1}'에서 매칭 실패")
if match_obj2:
print(f"'{text2}'에서 매칭 성공: {match_obj2.group()}")
else:
print(f"'{text2}'에서 매칭 실패")
# 숫자 패턴 매칭
match_obj3 = re.match(r"\d+", "123abc") # r""는 Raw String (이스케이프 문자 처리 용이)
if match_obj3:
print(f"숫자 매칭 성공: {match_obj3.group()}")
match_obj4 = re.match(r"\d+", "abc123")
if match_obj4:
print(f"숫자 매칭 성공: {match_obj4.group()}")
else:
print(f"숫자 매칭 실패: 문자열 시작에 숫자가 없음")
[VS Code 터미널 출력]

2. re.search(pattern, string) - 문자열 전체에서 첫 번째 매칭 확인
- 문자열 전체에서 패턴과 일치하는 첫 번째 부분을 찾습니다.
- 일치하면 Match object를 반환하고, 일치하지 않으면 None을 반환합니다. (re.match와 달리 시작 위치에 상관없이 찾습니다.)
예시:
# 파일 이름: re_search.py
import re
text = "My phone number is 010-1234-5678. Call me!"
# 전화번호 패턴 검색 (첫 번째만 찾음)
# \d{3} : 숫자 3개
# - : 하이픈
# \d{4} : 숫자 4개
phone_pattern = r"\d{3}-\d{4}-\d{4}"
search_obj = re.search(phone_pattern, text)
if search_obj:
print(f"전화번호 매칭 성공: {search_obj.group()}")
print(f"시작 인덱스: {search_obj.start()}")
print(f"끝 인덱스: {search_obj.end()}")
print(f"매칭 범위: {search_obj.span()}")
else:
print("전화번호 매칭 실패")
# 이메일 패턴 검색
email_text = "Contact me at user@example.com or admin@domain.org"
email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
search_email = re.search(email_pattern, email_text)
if search_email:
print(f"이메일 매칭 성공: {search_email.group()}")
else:
print("이메일 매칭 실패")
[VS Code 터미널 출력]

3. re.findall(pattern, string) - 모든 매칭 결과 리스트로 반환
- 문자열 전체에서 패턴과 일치하는 모든 부분을 찾아 리스트로 반환합니다.
예시:
# 파일 이름: re_findall.py
import re
text = "Numbers: 123, 45, 6789. Also 0 and 100."
# 모든 숫자 찾기
numbers_found = re.findall(r"\d+", text)
print(f"찾은 모든 숫자: {numbers_found}")
# 모든 단어 찾기 (알파벳만)
words_found = re.findall(r"[a-zA-Z]+", text)
print(f"찾은 모든 단어: {words_found}")
# 이메일 주소 모두 찾기
email_text = "user1@example.com, user2@domain.org, invalid-email, user3@test.net"
email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
all_emails = re.findall(email_pattern, email_text)
print(f"찾은 모든 이메일: {all_emails}")
[VS Code 터미널 출력]

4. re.sub(pattern, repl, string) - 매칭되는 부분 대체
- 문자열에서 패턴과 일치하는 모든 부분을 repl (대체 문자열)로 바꿉니다.
예시:
# 파일 이름: re_sub.py
import re
text = "Today is 2024-07-05. Tomorrow is 2024-07-06."
# 날짜 형식을 'YYYY/MM/DD'로 변경
# (\d{4}) : 4자리 숫자를 그룹 1로 캡처
# (\d{2}) : 2자리 숫자를 그룹 2로 캡처
# (\d{2}) : 2자리 숫자를 그룹 3으로 캡처
# \g<1>, \g<2>, \g<3> : 캡처된 그룹 참조
date_pattern = r"(\d{4})-(\d{2})-(\d{2})"
replaced_text = re.sub(date_pattern, r"\g<1>/\g<2>/\g<3>", text)
print(f"날짜 형식 변경: {replaced_text}")
# 모든 숫자 제거
no_numbers_text = re.sub(r"\d+", "", text)
print(f"숫자 제거: {no_numbers_text}")
# 공백을 하이픈으로 대체
spaced_text = "This is a test string with spaces."
hyphenated_text = re.sub(r"\s+", "-", spaced_text)
print(f"공백을 하이픈으로: {hyphenated_text}")
[VS Code 터미널 출력]

Part 4: 정규 표현식 컴파일 (re.compile)
동일한 정규 표현식 패턴을 여러 번 사용해야 할 경우, re.compile() 함수를 사용하여 패턴을 미리 컴파일(pre-compile)할 수 있습니다. 이렇게 하면 매번 패턴을 파싱하는 오버헤드를 줄여 성능을 향상시킬 수 있습니다.
예시:
# 파일 이름: re_compile.py
import re
import time
# 컴파일하지 않은 패턴 사용
start_time = time.time()
for _ in range(100000):
re.search(r"\d{3}-\d{4}-\d{4}", "My phone is 010-1234-5678.")
end_time = time.time()
print(f"컴파일하지 않은 패턴 소요 시간: {end_time - start_time:.4f}초")
# 패턴 컴파일
phone_pattern_compiled = re.compile(r"\d{3}-\d{4}-\d{4}")
# 컴파일된 패턴 사용
start_time = time.time()
for _ in range(100000):
phone_pattern_compiled.search("My phone is 010-1234-5678.")
end_time = time.time()
print(f"컴파일된 패턴 소요 시간: {end_time - start_time:.4f}초")
- 반복 횟수가 많을수록 컴파일된 패턴의 성능 이점이 더 명확해집니다.
[VS Code 터미널 출력]

(소요 시간은 시스템 환경에 따라 다를 수 있습니다.)
마무리하며
이번 시간에는 파이썬에서 정규 표현식(Regular Expression)을 사용하여 문자열을 검색하고 조작하는 방법에 대해 자세히 알아보았습니다.
- 정규 표현식: 특정 패턴을 가진 문자열을 정의하고 찾기 위한 강력한 도구.
- re 모듈: 파이썬에서 정규 표현식을 다루는 표준 모듈.
- 주요 함수:
- re.match(): 문자열 시작부터 매칭.
- re.search(): 문자열 전체에서 첫 번째 매칭.
- re.findall(): 모든 매칭 결과를 리스트로.
- re.sub(): 매칭되는 부분을 대체.
- re.compile(): 동일한 패턴을 여러 번 사용할 때 성능 최적화를 위해 패턴을 미리 컴파일.
정규 표현식은 처음에는 다소 복잡하고 어렵게 느껴질 수 있지만, 문자열 처리의 강력한 유연성을 제공하므로 꾸준히 연습하여 익숙해지는 것이 중요합니다. 웹 크롤링, 데이터 파싱, 로그 분석 등 다양한 분야에서 매우 유용하게 활용될 것입니다.
이것으로 '파이썬 고급 문법 & 실전 예제' 챕터의 여섯 번째 포스팅이 마무리됩니다. 다음 포스팅에서는 파이썬에서 데이터를 직렬화하고 역직렬화하는 데 사용되는 JSON과 Pickle 모듈에 대해 알아보겠습니다.
궁금한 점이 있다면 언제든지 질문해주세요! 다음 포스팅에서 만나요!
'Python' 카테고리의 다른 글
7-8. datetime 모듈로 날짜와 시간 다루기 (0) | 2025.07.08 |
---|---|
7-7. os 모듈과 pathlib 모듈 (0) | 2025.07.06 |
7-5. 가상 환경(Virtual Environment)의 이해와 사용법 (0) | 2025.07.05 |
7-3. 데코레이터(Decorator) 이해하기 (0) | 2025.07.03 |
7-2. 제너레이터(Generator)와 yield 키워드 (0) | 2025.07.03 |