정규표현식 입문: 텍스트 처리의 강력한 도구
정규표현식이란 무엇인가?
정규표현식(Regular Expression, 줄여서 Regex)은 텍스트에서 특정 패턴을 찾고, 추출하고, 치환하는 강력한 도구입니다. 프로그래밍 언어가 아닌 ‘패턴 매칭 언어’로, Python, JavaScript, Java, PHP 등 거의 모든 프로그래밍 언어에서 지원합니다.
정규표현식은 1950년대 수학자 스티븐 클레인(Stephen Kleene)이 정규 집합(regular set)을 설명하기 위해 고안한 표기법에서 유래했습니다. 1968년 켄 톰슨(Ken Thompson)이 Unix의 텍스트 에디터 ed에 정규표현식을 구현하면서 프로그래밍 도구로 자리잡았습니다.
- 이메일 검증: 사용자 입력이 유효한 이메일 형식인지 확인
- 로그 파싱: 서버 로그에서 IP 주소나 에러 메시지 추출
- 데이터 추출: HTML에서 전화번호나 URL 찾기
- 코드 리팩토링: 수백 개 파일에서 함수명 일괄 변경
- 텍스트 변환: 날짜 형식 변환, 공백 정리 등
기본 문법: 메타문자와 리터럴
리터럴 문자
정규표현식의 가장 기본은 일반 문자 그대로 매칭하는 것입니다. cat이라는 정규식은 텍스트에서 “cat”이라는 문자열을 찾습니다.
메타문자 (특수 의미)
| 메타문자 | 의미 | 예시 | 매칭 결과 |
|---|---|---|---|
. |
임의의 한 문자 | c.t |
cat, cot, c9t, c@t |
^ |
문자열 시작 | ^Hello |
Hello로 시작하는 줄 |
$ |
문자열 끝 | world$ |
world로 끝나는 줄 |
* |
0회 이상 반복 | ab*c |
ac, abc, abbc, abbbc |
+ |
1회 이상 반복 | ab+c |
abc, abbc (ac는 안됨) |
? |
0 또는 1회 | colou?r |
color, colour |
{n} |
정확히 n회 | \d{3} |
123, 999 |
{n,} |
n회 이상 | \d{2,} |
12, 123, 12345 |
{n,m} |
n~m회 | \d{2,4} |
12, 123, 1234 |
[] |
문자 클래스 | [aeiou] |
모음 한 글자 |
| |
OR 연산 | cat|dog |
cat 또는 dog |
\ |
이스케이프 | \. |
마침표 문자 그대로 |
문자 클래스
| 클래스 | 의미 | 동등 표현 |
|---|---|---|
\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] |
자주 쓰는 패턴 라이브러리
1. 이메일 주소
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
설명:
^: 문자열 시작[a-zA-Z0-9._%+-]+: 로컬 파트 (1자 이상)@: @ 기호[a-zA-Z0-9.-]+: 도메인명\.: 점 (이스케이프 필요)[a-zA-Z]{2,}: 최상위 도메인 (2자 이상)$: 문자열 끝
2. 전화번호 (한국)
^01[0-9]-\d{3,4}-\d{4}$
매칭 예시: 010-1234-5678, 011-123-4567
3. URL
https?://[^\s]+
설명:
https?: http 또는 https://: 프로토콜 구분자[^\s]+: 공백이 아닌 문자 1개 이상
4. IP 주소 (IPv4)
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
매칭 예시: 192.168.0.1, 255.255.255.255
5. 한글
[가-힣]+
설명: 완성형 한글 자모 범위 (가~힣)
6. 날짜 (YYYY-MM-DD)
^\d{4}-\d{2}-\d{2}$
매칭 예시: 2026-02-02, 1999-12-31
그룹과 캡처: 패턴 재사용
캡처 그룹 ( )
괄호로 묶인 부분은 “그룹”이 되며, 매칭된 내용을 추출하거나 재사용할 수 있습니다.
(\d{4})-(\d{2})-(\d{2})
예시: “2026-02-02″를 매칭하면
- 그룹 1:
2026(연도) - 그룹 2:
02(월) - 그룹 3:
02(일)
비캡처 그룹 (?:)
그룹으로 묶되 캡처하지 않을 때 사용합니다 (성능 향상).
(?:https?|ftp)://[^\s]+
역참조 (Backreference)
앞에서 캡처한 그룹을 다시 참조할 수 있습니다.
<(\w+)>.*?</\1>
설명: HTML 태그 매칭 (여는 태그와 닫는 태그 동일)
(\w+): 태그명 캡처\1: 첫 번째 그룹 참조
매칭 예시: <div>...</div>, <p>...</p>
실전 예제
예제 1: 이메일 유효성 검사 (JavaScript)
function validateEmail(email) {
const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return regex.test(email);
}
console.log(validateEmail("user@example.com")); // true
console.log(validateEmail("invalid-email")); // false
예제 2: 로그에서 IP 주소 추출 (Python)
import re
log = "2026-02-02 10:30:15 192.168.1.100 GET /api/users 200"
ip_pattern = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
ip = re.search(ip_pattern, log)
print(ip.group()) # 192.168.1.100
예제 3: 텍스트 치환 (날짜 형식 변환)
import re
text = "오늘은 2026-02-02입니다."
# YYYY-MM-DD → DD/MM/YYYY
new_text = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\3/\2/\1', text)
print(new_text) # 오늘은 02/02/2026입니다.
예제 4: HTML 태그 제거
import re
html = "<p>Hello <strong>World</strong></p>"
clean = re.sub(r'<[^>]+>', '', html)
print(clean) # Hello World
성능과 보안 주의사항
ReDoS 공격 (Regular Expression Denial of Service)
복잡한 정규식은 백트래킹 폭발로 인해 CPU를 과도하게 사용할 수 있습니다.
(a+)+b
문제: “aaaaaaaaaaaaaaaaaaa”를 처리할 때 지수 시간 복잡도
ReDoS 방지법
- 중첩 수량자 피하기:
(a+)+,(a*)*같은 패턴 제거 - 타임아웃 설정: Python
re대신regex라이브러리 사용 (timeout 옵션) - 입력 길이 제한: 사용자 입력을 검증하기 전에 길이 체크
- 비캡처 그룹 사용:
(?:...)로 불필요한 캡처 제거
성능 최적화 팁
| 느린 패턴 | 빠른 패턴 | 이유 |
|---|---|---|
.* |
[^\s]+ |
구체적인 클래스가 백트래킹 감소 |
(a|b|c) |
[abc] |
문자 클래스가 더 빠름 |
^.*keyword.*$ |
keyword |
앵커와 .* 불필요 |
학습 도구와 리소스
추천 학습 사이트
- RegexOne: https://regexone.com/ – 대화형 튜토리얼
- Regex101: https://regex101.com/ – 실시간 테스트 + 설명
- RegexLearn: https://regexlearn.com/ – 게임처럼 배우기
ToolZipper 정규식 도구
결론
정규표현식은 처음엔 복잡해 보이지만, 기본 패턴만 익히면 텍스트 처리 생산성이 크게 향상됩니다. 이메일 검증, 로그 파싱, 데이터 추출 등 실무에서 매일 사용하는 필수 기술입니다.
핵심 요약
- 정규표현식은 ‘패턴 매칭 언어’로 거의 모든 프로그래밍 언어에서 지원
- 메타문자
. ^ $ * + ? {} [] | \와 문자 클래스\d \w \s이해 필수 - 이메일:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ - 캡처 그룹
( )으로 데이터 추출, 역참조\1로 재사용 - ReDoS 공격 주의: 중첩 수량자
(a+)+피하기
지금 바로 정규식 테스터에서 연습해보세요!