본문 바로가기
IT⦁영어⦁하자보수/IT

10. 파이썬 기초 - 8장 정규표현식 [조코딩]

by 별꽃74 2025. 9. 21.

파이썬 기초 - 8장 정규표현식 | 2024 점프 투 파이썬

 
여러분, 안녕하세요! 👨‍🏫 오늘은 '점프 투 파이썬' 강의의 여덟 번째 시간, **'정규 표현식(Regular Expressions)'**에 대해 깊이 있는 이야기를 나눠볼까 합니다. 드디어 파이썬 코딩의 신세계로 진입하는 순간이군요! 🚀
만약 여러분에게 "수많은 문서 속에서 'a'로 시작하고 'b'로 끝나는 모든 단어를 찾아줘!"라고 누군가 부탁한다면, 어떻게 하시겠어요? 아마도 일일이 눈으로 찾아내거나 복잡한 코드를 짜야 할 겁니다. 하지만 정규 표현식이라는 마법 같은 언어를 사용하면, 이 복잡한 문제를 단 몇 줄의 코드로 해결할 수 있습니다. 🪄
정규 표현식은 단순히 파이썬에만 있는 특별한 문법이 아닙니다. 이것은 텍스트 편집기, 데이터베이스, 심지어 운영체제에까지 사용되는, 문자열의 패턴을 정의하는 범용적인 언어입니다. 이 글에서는 마치 숙련된 탐정처럼 정규 표현식의 세계를 꼼꼼하게 탐색하며, 복잡한 문자열 처리의 비밀을 파헤쳐 드릴게요. 🕵️‍♂️✨


정규 표현식, 왜 배워야 할까? 🧐

정규 표현식은 'RegEx' 또는 'RegExp'라고도 불리며, 문자열에서 특정 패턴을 찾고, 추출하고, 혹은 바꾸는 데 사용됩니다. 왜 이것을 배워야 할까요? 그 이유는 다음과 같습니다.

  • 코드의 간결성: 복잡한 조건문과 반복문으로 가득 차 있던 문자열 처리 코드를 단 한 줄로 압축할 수 있습니다.
  • 강력한 기능: 이메일 주소 형식 유효성 검사, 전화번호 추출, HTML 태그 제거 등 복잡한 패턴을 손쉽게 다룰 수 있습니다.
  • 높은 효율성: 대용량의 텍스트 데이터에서 원하는 정보를 빠르게 찾아내는 데 최적화되어 있습니다.

예를 들어, 주민등록번호 뒷자리를 별표(*)로 바꾸는 작업을 생각해봅시다. 정규 표현식을 사용하지 않으면 조건문과 슬라이싱을 복잡하게 조합해야 하지만, 정규 표현식은 단 두 줄로 끝낼 수 있습니다. 이처럼 정규 표현식은 **'패턴'**에 집중하여 문제를 해결하는 강력한 도구입니다.


정규 표현식의 기본: 메타 문자 📝

정규 표현식을 이해하려면, 우선 **'메타 문자(Meta Characters)'**를 알아야 합니다. 메타 문자는 그 문자가 가진 본래의 뜻이 아니라, 특별한 의미를 가진 문자들입니다. 마치 일반 글자(문자)가 아니라 명령을 내리는 특수 키(메타)라고 생각하면 쉽습니다.

1. 문자 클래스 []

대괄호 [] 안에 들어가는 문자들이 매치되는지 확인합니다.

  • [abc]: 'a', 'b', 'c' 중 한 문자와 매치됩니다.
  • [a-zA-Z]: 모든 알파벳 대문자 또는 소문자와 매치됩니다.
  • [0-9]: 모든 숫자와 매치됩니다. \d와 동일합니다.
  • [^0-9]: 캐럿(^)이 맨 앞에 오면 '부정'의 의미를 가집니다. 즉, 숫자를 제외한 모든 문자와 매치됩니다.

2. 점(.)

줄바꿈 문자(\n)를 제외한 모든 한 문자와 매치됩니다.

  • a.b: 'a'와 'b' 사이에 어떤 한 문자가 오는 경우(예: acb, a!b) 매치됩니다.

3. 반복 관련 메타 문자

  • * (별표): 바로 앞 문자가 0번 이상 반복되는 경우와 매치됩니다.
    • ca*t: 'ct', 'cat', 'caat' 등 'a'가 없거나 여러 번 반복되는 경우 모두 매치됩니다.
  • + (플러스): 바로 앞 문자가 1번 이상 반복되는 경우와 매치됩니다.
    • ca+t: 'cat', 'caat' 등 'a'가 최소 한 번 이상 반복되는 경우만 매치됩니다.
  • ? (물음표): 바로 앞 문자가 0번 또는 1번 반복되는 경우와 매치됩니다. {0,1}과 동일합니다.
  • {m, n} (중괄호): 바로 앞 문자가 최소 m번, 최대 n번 반복되는 경우와 매치됩니다.
    • ca{2}t: 'caat'만 매치됩니다.
    • ca{2,4}t: 'caat', 'caaat', 'caaaat'가 매치됩니다.
    • ca{2,}t: 'a'가 2번 이상 반복되는 모든 경우와 매치됩니다.

4. 위치 관련 메타 문자

  • ^ (캐럿): 문자열의 시작점과 매치됩니다.
    • ^Life: 'Life is too short'와는 매치되지만, 'I love Life'와는 매치되지 않습니다.
  • $ (달러): 문자열의 끝점과 매치됩니다.
    • short$: 'Life is too short'와 매치됩니다.
  • \b (단어 경계): 단어의 시작점이나 끝점에 매치됩니다.
    • \bclass: 'class'라는 단어 자체와 매치됩니다. 'multiclass'의 'class'와는 매치되지 않습니다.
  • \B (비 단어 경계): \b와 반대로, 단어의 경계가 아닌 곳과 매치됩니다.

5. 그 외 유용한 메타 문자

  • | (파이프): OR 연산과 동일합니다. 'A|B'는 'A' 또는 'B'와 매치됩니다.
  • () (소괄호): 그룹핑에 사용됩니다. 이 안에 있는 내용을 하나의 덩어리로 묶을 수 있습니다.

파이썬에서 정규 표현식 사용하기 🐍

파이썬에서는 re 모듈을 사용하여 정규 표현식을 다룹니다.

1. re.compile()

정규 표현식을 컴파일하여 **'패턴 객체'**를 만듭니다. 이렇게 하면 같은 패턴을 여러 번 사용할 때 훨씬 효율적입니다.

2. match() vs. search()

  • match(): 문자열의 처음부터 정규식과 매치되는지 조사합니다. 처음부터 매치되지 않으면 None을 반환합니다.
  • search(): 문자열 전체를 탐색하여 정규식과 매치되는 첫 번째 경우를 찾습니다.
import re

pattern = re.compile('apple')
text = 'I have an apple and a pear.'

m = pattern.match(text)    # None (문자열 시작이 'apple'이 아님)
s = pattern.search(text)   # <re.Match object> (전체에서 'apple'을 찾음)

if s:
    print("찾았다!")

3. findall() vs. finditer()

  • findall(): 매치되는 모든 문자열을 찾아 리스트(list) 형태로 반환합니다.
  • finditer(): 매치되는 모든 문자열을 찾지만, **반복 가능한 객체(iterator)**를 반환합니다. 이 객체를 사용하면 대용량 데이터에서 메모리를 효율적으로 사용할 수 있습니다.
import re

text = '123 abc 456 def'
pattern = re.compile('\d+') # 숫자가 1번 이상 반복

found_list = pattern.findall(text) # ['123', '456']
print(found_list)

found_iter = pattern.finditer(text)
for match in found_iter:
    print(match.group()) # '123', '456'을 하나씩 출력

4. 매치 객체 메서드

match()나 search()에 성공하면 **'매치 객체'**가 반환됩니다. 이 객체에는 매치된 결과에 대한 다양한 정보가 담겨 있습니다.

  • group(): 매치된 문자열을 반환합니다.
  • start(): 매치된 문자열의 시작 위치 인덱스를 반환합니다.
  • end(): 매치된 문자열의 끝 위치 인덱스(미만)를 반환합니다.
  • span(): 매치된 문자열의 시작과 끝 위치를 (시작, 끝) 형태의 튜플로 반환합니다.

5. 문자열 바꾸기: re.sub()

re.sub(pattern, replace, string) 메서드는 문자열에서 패턴과 일치하는 모든 부분을 다른 문자열로 바꿉니다.

import re

text = "전화번호: 010-1234-5678, 이메일: example@test.com"
# 전화번호 패턴을 찾아 '***-****-****'로 바꾸기
new_text = re.sub('\d{3}-\d{4}-\d{4}', '***-****-****', text)
print(new_text) # 출력: 전화번호: ***-****-****, 이메일: example@test.com

정규 표현식의 심화 개념 🧠

1. 그룹핑 ()

소괄호 ()를 사용하여 정규식의 일부를 하나의 그룹으로 묶을 수 있습니다.

  • 그룹 참조: group(인덱스)를 사용하여 매치된 문자열 중 특정 그룹의 내용만 가져올 수 있습니다. group(0)은 전체 매치 결과를 의미합니다.
  • 이름 있는 그룹: (?P<이름>...) 형식을 사용하면 그룹에 이름을 붙일 수 있습니다.
  • 재참조: \1, \2와 같이 \와 숫자를 사용하여 앞에서 매치된 그룹을 다시 참조할 수 있습니다.
import re

text = "John Smith is a good person. Kim Smith is also nice."
pattern = re.compile(r'(\w+)\s+(Smith)') # 그룹 1: 이름, 그룹 2: 성
match = pattern.search(text)

if match:
    print(match.group(1))   # 출력: John
    print(match.group(2))   # 출력: Smith

2. 전방 탐색 (Lookaround) 🔎

전방 탐색은 패턴을 매치시키되, 결과 문자열에는 포함시키지 않는 기능입니다.

  • 긍정형 전방 탐색 (?=...): ...에 해당하는 패턴이 나와야 매치됩니다. (예: .*(?=apple)는 'apple' 앞에 있는 모든 문자를 매치)
  • 부정형 전방 탐색 (?!...): ...에 해당하는 패턴이 나오지 않아야 매치됩니다. (예: .*(?!apple)는 'apple'이 아닌 단어 앞의 문자를 매치)

3. 탐욕성(Greedy) vs. 비탐욕성(Non-Greedy) 🤯

정규 표현식의 반복 관련 메타 문자(*, +, {m,n})는 기본적으로 가장 긴 문자열을 매치하려는 '탐욕성'을 가집니다.

  • a.*b는 a...b...b라는 문자열에서 a부터 가장 마지막 b까지 모두 매치합니다.
  • ?를 추가하여 a.*?b와 같이 만들면, 가장 짧은 문자열을 매치하려는 **'비탐욕성'**을 가지게 됩니다.

정규 표현식 실전 활용 예제 💡

예제 1: 이메일 유효성 검사

import re

email_pattern = re.compile(r'^[a-zA-Z0-9+-\_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')

emails = ["test@example.com", "invalid-email@", "name@domain.co.kr"]

for email in emails:
    if email_pattern.match(email):
        print(f"{email}은(는) 유효한 이메일입니다.")
    else:
        print(f"{email}은(는) 유효하지 않은 이메일입니다.")
  • ^: 문자열 시작
  • [a-zA-Z0-9+-\_.]+: @ 앞의 사용자명 부분
  • @: @ 문자
  • [a-zA-Z0-9-]+: @ 뒤의 도메인 이름
  • \.: . 문자
  • [a-zA-Z0-9-.]+: 도메인 최상위 부분
  • $: 문자열 끝

예제 2: HTML 태그 제거하기

import re

html_text = "<p>이것은 **정규 표현식** 강의입니다.</p>"
# <...> 패턴을 찾아서 제거
clean_text = re.sub('<.*?>', '', html_text)
print(clean_text) # 출력: 이것은 **정규 표현식** 강의입니다.
  • <.*>: 태그의 시작과 끝을 포함하는 패턴. *는 탐욕성을 가지므로, <p>...</b>와 같은 여러 태그를 한 번에 제거할 수 있습니다.
  • <.*?>: 비탐욕성을 사용하여 <p>만 매치하고 다음 <...>를 다시 찾습니다.

마무리하며... ✍️

오늘은 파이썬의 꽃이라 불리는 정규 표현식에 대해 알아봤습니다.

  • 정규 표현식은 복잡한 문자열 패턴을 간결하게 정의하는 언어입니다.
  • re 모듈과 match, search, sub 같은 함수를 통해 파이썬에서 사용할 수 있습니다.
  • 메타 문자를 조합하여 원하는 패턴을 자유자재로 만들 수 있습니다.

정규 표현식은 처음에는 어렵고 낯설게 느껴질 수 있지만, 익숙해지면 여러분의 코딩 생산성을 비약적으로 높여주는 최고의 무기가 될 것입니다. 🛠️ 모든 패턴을 외우려 하기보다는, 필요한 패턴을 그때그때 검색하며 익숙해지는 것이 중요합니다. 이제 여러분의 파이썬 코딩 여정에 힘찬 날개가 달렸으니, 더 높이, 더 멀리 날아오르세요! 🦅