[Python] 정규표현식

2026. 3. 13. 11:51·Python

목차

    1. 정규표현식이란?
    2. Python re 모듈 기초
    3. re.compile() — 왜 사용하는가?
    4. 정규표현식 핵심 문법
    5. 실전 예제 — HTML 태그 찾기
    6. re 옵션 플래그
    7. 실전 활용 예제
    8. 그룹 캡처 — 더 강력하게 활용하기

 


1. 정규표현식이란?

정규표현식(Regular Expression, Regex)은 특정 패턴을 가진 문자열을 검색, 추출, 변환하기 위한 형식 언어입니다.

단순히 "특정 단어 찾기"를 넘어, 이메일·전화번호·URL처럼 규칙을 가진 문자열 패턴을 정의하고 한 번에 처리할 수 있습니다.

쉽게 말하면, 정규표현식은 문자열에 대한 "검색 공식" 입니다.

정규표현식을 사용하는 이유

코드 10줄로 처리할 작업을 정규표현식 1줄로 끝낼 수 있습니다. 문자열 처리 로직이 복잡할수록 정규표현식의 가치는 극대화됩니다.

정규표현식이 없다면 어떻게 될까요? 이메일 형식 검증을 예로 들겠습니다.

# 정규표현식 없이 이메일 검증 (복잡하고 불완전)
def is_email(text):
    if '@' not in text:
        return False
    parts = text.split('@')
    if len(parts) != 2:
        return False
    if '.' not in parts[1]:
        return False
    # ... 계속 늘어나는 조건들 ...
    return True
# 정규표현식으로 이메일 검증 (간결하고 정확)
import re

pattern = re.compile(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}')
result = pattern.match('user@example.com')
print(bool(result))  # True

정규표현식이 꼭 필요한 상황

  • 웹 크롤링에서 HTML 태그 제거 또는 특정 요소 추출
  • 로그 파일에서 에러 코드, IP 주소, 타임스탬프 추출
  • 사용자 입력 데이터 유효성 검사 (이메일, 전화번호, 비밀번호)
  • 대용량 텍스트 데이터에서 패턴 기반 정보 추출
  • 코드 리팩토링 시 특정 패턴의 변수/함수명 일괄 변경

2. Python re 모듈 기초

Python은 표준 라이브러리에 re 모듈을 내장하고 있어 별도 설치 없이 정규표현식을 사용할 수 있습니다.

모듈 re는 regular expression의 약자로 외워두시면 좋을 것 같습니다.

import re

re 모듈의 주요 함수

함수                                    동작                                                                       반환값

re.match() 문자열 시작부터 매칭 Match 객체 또는 None
re.search() 문자열 전체에서 첫 매칭 Match 객체 또는 None
re.findall() 모든 매칭 문자열 반환 리스트(list)
re.finditer() 모든 매칭 이터레이터 Iterator
re.sub() 매칭 문자열 치환 치환된 문자열
re.split() 패턴으로 문자열 분리 리스트(list)

3. re.compile() — 왜 사용하는가?

re.compile()은 정규표현식 패턴을 미리 컴파일하여 재사용 가능한 패턴 객체를 만드는 함수입니다.

 

re.compile() 기본 사용법

import re

pattern = re.compile('python')

# findall - 모든 매칭 반환
result = pattern.findall('I love python and python programming')
print(result)  # ['python', 'python']

# search - 첫 번째 매칭
m = pattern.search('I love python')
print(m.group())  # python

# sub - 치환
new_text = pattern.sub('Java', 'I love python')
print(new_text)  # I love Java

4. 정규표현식 핵심 문법

기본 메타 문자

패턴 의미 예시

. 임의의 문자 1개 (줄바꿈 제외) a.c → abc, a1c
[] 문자 클래스 (안의 문자 중 1개) [abc] → a, b, c
[^] 부정 문자 클래스 [^0-9] → 숫자 제외
| OR 연산자 cat|dog → cat 또는 dog
() 그룹화 및 캡처 (ab)+ → ab, abab

수량자(Quantifier)

패턴 의미 예시

+ 1개 이상 반복 a+ → a, aa, aaa
* 0개 이상 반복 a* → '', a, aa
? 0개 또는 1개 colou?r → color, colour
{n} 정확히 n번 반복 a{3} → aaa
{n,} n번 이상 반복 a{2,} → aa, aaa, ...
{n,m} n번 이상 m번 이하 a{2,4} → aa, aaa, aaaa

앵커(Anchor) & 특수 시퀀스

패턴 의미 예시

^ 문자열/줄의 시작 ^Hello → Hello로 시작
$ 문자열/줄의 끝 world$ → world로 끝
\d 숫자 [0-9] \d+ → 123, 42
\D 비숫자 [^0-9] \D+ → abc, !@#
\w 단어 문자 [a-zA-Z0-9_] \w+ → hello, var_1
\W 비단어 문자 \W+ → !!, ...
\s 공백 문자 \s+ → 스페이스, 탭
\b 단어 경계 \bcat\b → cat (단독)

5. 실전 예제 — HTML 태그 찾기

웹 크롤링과 데이터 파싱에서 가장 자주 마주치는 작업 중 하나가 HTML 태그 처리입니다.

HTML 태그 패턴 분석

pattern = re.compile(r"<[a-z0-9]+>|</[a-z0-9]+>", re.IGNORECASE)

패턴 요소 설명

< HTML 태그 시작 기호 (리터럴 매칭)
[a-z0-9] 태그 이름: 알파벳 소문자 또는 숫자
+ 태그 이름은 1자 이상 (p, div, h1 등)
> HTML 태그 종료 기호 (리터럴 매칭)
| OR — 여는 태그 또는 닫는 태그
</[a-z0-9]+> 닫는 태그 패턴 (</p>, </div> 등)
re.IGNORECASE <DIV>, <div>, <Div> 모두 매칭

실행 코드 및 결과

import re

text = "<p>Hello</p> <DIV>World</DIV> <H1>Title</H1>"

# 태그 찾기
pattern = re.compile(r"<[a-z0-9]+>|</[a-z0-9]+>", re.IGNORECASE)
tags = pattern.findall(text)
print("찾은 태그:", tags)
# 찾은 태그: ['<p>', '</p>', '<DIV>', '</DIV>', '<H1>', '</H1>']

# 태그 제거 (텍스트만 추출)
clean_text = pattern.sub("", text)
print("순수 텍스트:", clean_text)
# 순수 텍스트:  Hello  World  Title

6. re 옵션 플래그

re.compile()의 두 번째 인자로 플래그를 지정하면 매칭 동작을 세밀하게 제어할 수 있습니다.

import re

# re.IGNORECASE (re.I) — 대소문자 무시
p1 = re.compile('hello', re.IGNORECASE)
print(p1.findall('Hello HELLO hello'))  # ['Hello', 'HELLO', 'hello']

# re.MULTILINE (re.M) — ^, $ 가 각 줄의 시작/끝에 적용
p2 = re.compile('^line', re.MULTILINE)
text = 'line1\nline2\nline3'
print(p2.findall(text))  # ['line', 'line', 'line']

# re.DOTALL (re.S) — . 이 줄바꿈도 매칭
p3 = re.compile('<.*?>', re.DOTALL)

# 플래그 결합 — | 로 여러 개 동시 사용
p4 = re.compile('pattern', re.IGNORECASE | re.MULTILINE)

7. 실전 활용 예제

1. 이메일 주소 추출

import re

text = "문의: admin@company.com 또는 support@help.co.kr"
email_pattern = re.compile(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}')
emails = email_pattern.findall(text)
print(emails)  # ['admin@company.com', 'support@help.co.kr']

2. 전화번호 검증

import re

phone_pattern = re.compile(r'01[016789]-?\d{3,4}-?\d{4}')

phones = ['010-1234-5678', '01012345678', '011-999-9999', '02-1234-5678']
for p in phones:
    is_valid = bool(phone_pattern.fullmatch(p))
    print(f'{p}: {"유효" if is_valid else "무효"}')

# 010-1234-5678: 유효
# 01012345678: 유효
# 011-999-9999: 유효
# 02-1234-5678: 무효

3. 로그 데이터 파싱

import re

log = '192.168.1.100 - [2024/01/15 10:30:00] "GET /api/data" 200 1234'

# IP 주소 추출
ip_pattern = re.compile(r'(\d{1,3}\.){3}\d{1,3}')
ip = ip_pattern.search(log).group()
print('IP:', ip)  # 192.168.1.100

# 상태 코드 추출
status_pattern = re.compile(r'"\s(\d{3})\s')
status = status_pattern.search(log).group(1)
print('Status:', status)  # 200

# 날짜 추출
date_pattern = re.compile(r'\[(.*?)\]')
date = date_pattern.search(log).group(1)
print('Date:', date)  # 2024/01/15 10:30:00

4. URL에서 도메인 추출

import re

urls = [
    'https://www.google.com/search?q=python',
    'http://blog.example.co.kr/post/123',
    'https://api.github.com/users/octocat',
]

domain_pattern = re.compile(r'https?://([\w.-]+)')
for url in urls:
    domain = domain_pattern.search(url).group(1)
    print(domain)

# www.google.com
# blog.example.co.kr
# api.github.com

8. 그룹 캡처 — 더 강력하게 활용하기

괄호 ()를 사용하면 매칭된 패턴 안에서 특정 부분만 추출할 수 있습니다. 이를 그룹 캡처라고 합니다.

import re

# 날짜 형식에서 연/월/일 각각 추출
date_pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2})')
m = date_pattern.search('오늘은 2024-01-15 입니다')

print(m.group(0))  # 2024-01-15  (전체 매칭)
print(m.group(1))  # 2024        (첫 번째 그룹: 연도)
print(m.group(2))  # 01          (두 번째 그룹: 월)
print(m.group(3))  # 15          (세 번째 그룹: 일)

# 이름 있는 그룹 (Named Group) - 더 가독성 좋은 방법
named_pattern = re.compile(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})')
m2 = named_pattern.search('2024-01-15')
print(m2.group('year'))   # 2024
print(m2.group('month'))  # 01
print(m2.group('day'))    # 15

 

자주 하는 실수

  • Raw string 미사용: r'\d+' 대신 '\\d+'처럼 이중 이스케이프가 필요해져 가독성이 떨어집니다. 항상 r''를 사용하세요.
  • re.match vs re.search 혼동: match()는 문자열 시작에서만 탐색하고, search()는 전체를 탐색합니다.

마무리

정규표현식은 처음 마주하면 암호처럼 보이지만, 핵심 패턴 몇 가지만 익히면 문자열 처리 능력이 비약적으로 향상됩니다.

중요한 것은 외우는 것이 아니라, 필요할 때 찾아보고 직접 테스트해보는 것입니다.

 

'Python' 카테고리의 다른 글

[Python] sort(), reverse()정리  (0) 2026.03.27
[Python] Selenium에서의 innerHTML, innerText, textContent 차이점  (0) 2026.03.18
[Python] pytest를 이용한 테스트 코드 작성법  (0) 2026.03.11
[Python] json.dumps() 사용법, 사용이유  (1) 2026.03.10
[Python] API 요청 방법  (0) 2026.03.09
'Python' 카테고리의 다른 글
  • [Python] sort(), reverse()정리
  • [Python] Selenium에서의 innerHTML, innerText, textContent 차이점
  • [Python] pytest를 이용한 테스트 코드 작성법
  • [Python] json.dumps() 사용법, 사용이유
byhy0
byhy0
byhy0 님의 블로그 입니다.
  • byhy0
    byhy0 님의 블로그
    byhy0
  • 전체
    오늘
    어제
    • 분류 전체보기 (62)
      • T아카데미 (4)
      • Project (2)
      • Airflow (4)
      • Python (16)
        • Django (0)
      • Java (1)
      • Spring (4)
        • Board Project (3)
      • SQL (3)
      • Docker (1)
      • 클라우드 (2)
      • Error (3)
      • Git (5)
      • 코딩테스트 (12)
        • SQL (5)
        • Python (7)
      • TIL (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    API 요청 #API
    T아카데미 #SK플래닛 #회고 #1주차
    #Python #정규표현식 #Regex #웹크롤링 #데이터처리
    git #github #repository 생성
    Spring
    티스토리챌린지
    T아카데미 #면접 #데이터 엔지니어 #K-Digital Traning
    venv #파이썬 가상환경 #가상환경
    programmers # 코딩테스트 #sql
    BigQuery #SQL
    python #pytest #테스트
    Git #설치법
    오블완
    게시판
    programmers #SQL #코딩테스트
    T아카데미 #2주차 회고 #데이터 엔지니어 2기
    #클라우드 #클라우드컴퓨팅 #CloudComputing #온프레미스 #CS기초 #IT인프라 #서버
    T아카데미#SK플래닛#데이터엔지니어2기
    push #pull #git연동
    vscode #git #git연동법
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
byhy0
[Python] 정규표현식
상단으로

티스토리툴바