이름 붙은 그룹(Named Groups)이란?
대부분의 최신 정규식 엔진은 번호가 매겨진 캡처 그룹(numbered capturing group)과 역참조(backreference)를 지원합니다. 그러나 그룹과 역참조가 많아지면 정규식 전체가 길어져 읽고 이해하기가 매우 어려워집니다. 더 큰 문제는 정규식 중간에 캡처 그룹을 추가하거나 삭제할 때마다, 해당 위치 뒤에 있는 모든 그룹의 번호가 함께 밀리거나 당겨진다는 점입니다.
파이썬의 re 모듈은 바로 이 문제에 대한 해결책을 업계 최초로 도입했는데, 그것이 바로 이름 붙은 캡처 그룹(named capturing group)과 이름 붙은 역참조(named backreference)입니다.
기본 문법
(?P<name>group) 형태로 그룹을 지정하면, 해당 그룹이 매칭한 문자열이 name이라는 이름으로 저장됩니다. 이때 주의할 점은 다음과 같습니다.
name은 반드시 문자로 시작하는 영숫자(alphanumeric) 조합이어야 합니다.group자리에는 어떤 정규식이든 올 수 있습니다.- 저장된 내용은
(?P=name)형태의 이름 붙은 역참조로 다시 참조할 수 있습니다.
물음표(?), P, 꺾쇠 괄호(<>), 등호(=)는 모두 문법의 일부이므로 생략할 수 없습니다. 특히 이름 붙은 역참조 (?P=name)은 괄호로 감싸져 있지만, 실제로는 아무것도 캡처하거나 묶지 않는 단순한 역참조일 뿐입니다.
실전 예제: HTML 태그 매칭
앞서 살펴본 HTML 태그 매칭 예제는 이름 붙은 그룹을 사용해 다음과 같이 작성할 수 있습니다.
<(?P<tag>[A-Z][A-Z0-9]*)\b[^>]*>.*?</(?P=tag)>여기서 여는 태그의 태그 이름이 tag라는 이름으로 캡처되고, 닫는 태그에서 (?P=tag)를 통해 동일한 이름인지 검사합니다. 덕분에 그룹 번호를 외울 필요 없이 의미를 바로 파악할 수 있습니다.
파이썬 코드에서 활용하기
매칭 결과에서 이름 붙은 그룹의 값은 그룹 이름으로 직접 가져올 수 있습니다.
import re
pattern = re.compile(r'<(?P<tag>[A-Z][A-Z0-9]*)\b[^>]*>.*?</(?P=tag)>')
m = pattern.search('<B>굵은 텍스트</B>')
if m:
print(m.group('tag')) # 출력: B
print(m.groupdict()) # 출력: {'tag': 'B'}이처럼 이름 붙은 그룹을 사용하면 복잡한 정규식도 가독성과 유지보수성이 크게 향상됩니다. 특히 그룹이 자주 추가되거나 삭제되는 패턴을 다룰 때는 번호 기반 그룹 대신 이름 붙은 그룹을 사용하는 것이 좋은 습관입니다.